purple: make it compile against 3.0.x API
[siplcs.git] / src / core / sip-transport.c
blobec7307ffb2548b055b8a99b1926be0fab9766c9d
1 /**
2 * @file sip-transport.c
4 * pidgin-sipe
6 * Copyright (C) 2010-11 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 int version;
88 int retries;
89 int ntlm_num;
90 int 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 */
118 /* Keep in sync with sipe_transport_type! */
119 static const char *transport_descriptor[] = { "", "tls", "tcp"};
120 #define TRANSPORT_DESCRIPTOR (transport_descriptor[transport->connection->type])
122 static char *genbranch()
124 return g_strdup_printf("z9hG4bK%04X%04X%04X%04X%04X",
125 rand() & 0xFFFF, rand() & 0xFFFF, rand() & 0xFFFF,
126 rand() & 0xFFFF, rand() & 0xFFFF);
129 static void sipe_auth_free(struct sip_auth *auth)
131 g_free(auth->opaque);
132 auth->opaque = NULL;
133 auth->protocol = NULL;
134 g_free(auth->realm);
135 auth->realm = NULL;
136 g_free(auth->sts_uri);
137 auth->sts_uri = NULL;
138 g_free(auth->target);
139 auth->target = NULL;
140 auth->version = 0;
141 auth->type = AUTH_TYPE_UNSET;
142 auth->retries = 0;
143 auth->expires = 0;
144 g_free(auth->gssapi_data);
145 auth->gssapi_data = NULL;
146 sip_sec_destroy_context(auth->gssapi_context);
147 auth->gssapi_context = NULL;
150 static void sipe_make_signature(struct sipe_core_private *sipe_private,
151 struct sipmsg *msg)
153 struct sip_transport *transport = sipe_private->transport;
154 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
155 struct sipmsg_breakdown msgbd;
156 gchar *signature_input_str;
157 msgbd.msg = msg;
158 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
159 transport->registrar.protocol);
160 msgbd.rand = g_strdup_printf("%08x", g_random_int());
161 transport->registrar.ntlm_num++;
162 msgbd.num = g_strdup_printf("%d", transport->registrar.ntlm_num);
163 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
164 if (signature_input_str != NULL) {
165 char *signature_hex = sip_sec_make_signature(transport->registrar.gssapi_context, signature_input_str);
166 msg->signature = signature_hex;
167 msg->rand = g_strdup(msgbd.rand);
168 msg->num = g_strdup(msgbd.num);
169 g_free(signature_input_str);
171 sipmsg_breakdown_free(&msgbd);
175 static gchar *auth_header_version(struct sip_auth *auth)
177 return(auth->version > 2 ?
178 g_strdup_printf(", version=%d", auth->version) :
179 g_strdup(""));
182 static const gchar *const auth_type_to_protocol[] = {
183 NULL, /* AUTH_TYPE_UNSET */
184 "NTLM", /* AUTH_TYPE_NTLM */
185 "Kerberos", /* AUTH_TYPE_KERBEROS */
186 NULL, /* AUTH_TYPE_NEGOTIATE */
187 "TLS-DSK", /* AUTH_TYPE_TLS_DSK */
189 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
191 static gchar *msg_signature_to_auth(struct sip_auth *auth,
192 struct sipmsg *msg)
194 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
195 auth->protocol,
196 auth->opaque, auth->realm, auth->target,
197 msg->rand, msg->num, msg->signature));
200 static gchar *initialize_auth_context(struct sipe_core_private *sipe_private,
201 struct sip_auth *auth,
202 struct sipmsg *msg)
204 gchar *ret;
205 gchar *gssapi_data = NULL;
206 gchar *sign_str;
207 gchar *gssapi_str;
208 gchar *opaque_str;
209 gchar *version_str;
211 /* Create security context or handshake continuation? */
212 if (auth->gssapi_context) {
213 /* Perform next step in authentication handshake */
214 int status = sip_sec_init_context_step(auth->gssapi_context,
215 auth->target,
216 auth->gssapi_data,
217 &gssapi_data,
218 &auth->expires);
220 /* If authentication is completed gssapi_data can be NULL */
221 if ((status < 0) ||
222 !(sip_sec_context_is_ready(auth->gssapi_context) || gssapi_data)) {
223 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
224 g_free(gssapi_data);
225 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
226 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
227 _("Failed to authenticate to server"));
228 return NULL;
231 } else {
232 /* Create security context */
233 const gchar *authuser = sipe_private->authuser;
234 gpointer password = sipe_private->password;
236 if (is_empty(authuser)) {
237 authuser = sipe_private->username;
240 /* For TLS-DSK the "password" is a certificate */
241 if (auth->type == AUTH_TYPE_TLS_DSK) {
242 password = sipe_certificate_tls_dsk_find(sipe_private,
243 auth->target);
245 if (!password) {
246 if (auth->sts_uri) {
247 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
248 auth->sts_uri);
249 if (!sipe_certificate_tls_dsk_generate(sipe_private,
250 auth->target,
251 auth->sts_uri)) {
252 gchar *tmp = g_strdup_printf(_("Can't request certificate from %s"),
253 auth->sts_uri);
254 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
255 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
256 tmp);
257 g_free(tmp);
259 } else {
260 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
261 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
262 _("No URI for certificate provisioning service provided"));
265 /* we can't authenticate the message yet */
266 sipe_private->transport->auth_incomplete = TRUE;
268 return(NULL);
269 } else {
270 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
271 auth->target);
275 gssapi_data = sip_sec_init_context(&(auth->gssapi_context),
276 &(auth->expires),
277 auth->type,
278 SIPE_CORE_PUBLIC_FLAG_IS(SSO),
279 sipe_private->authdomain ? sipe_private->authdomain : "",
280 authuser,
281 password,
282 auth->target,
283 auth->gssapi_data);
284 if (!gssapi_data || !auth->gssapi_context) {
285 g_free(gssapi_data);
286 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
287 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
288 _("Failed to authenticate to server"));
289 return NULL;
293 if ((auth->version > 3) &&
294 sip_sec_context_is_ready(auth->gssapi_context)) {
295 sipe_make_signature(sipe_private, msg);
296 sign_str = g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
297 msg->rand, msg->num, msg->signature);
298 } else {
299 sign_str = g_strdup("");
302 if (gssapi_data) {
303 gssapi_str = g_strdup_printf(", gssapi-data=\"%s\"",
304 gssapi_data);
305 g_free(gssapi_data);
306 } else {
307 gssapi_str = g_strdup("");
310 opaque_str = auth->opaque ? g_strdup_printf(", opaque=\"%s\"", auth->opaque) : g_strdup("");
311 version_str = auth_header_version(auth);
312 ret = g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
313 auth->protocol, opaque_str,
314 auth->realm, auth->target,
315 gssapi_str, version_str, sign_str);
316 g_free(version_str);
317 g_free(opaque_str);
318 g_free(gssapi_str);
319 g_free(sign_str);
321 return(ret);
324 static gchar *start_auth_handshake(struct sip_auth *auth)
326 gchar *version_str = auth_header_version(auth);
327 gchar *ret = g_strdup_printf("%s qop=\"auth\", realm=\"%s\", targetname=\"%s\", gssapi-data=\"\"%s",
328 auth->protocol,
329 auth->realm, auth->target,
330 version_str);
331 g_free(version_str);
332 return(ret);
335 static gchar *auth_header(struct sipe_core_private *sipe_private,
336 struct sip_auth *auth,
337 struct sipmsg *msg)
339 gchar *ret = NULL;
342 * If the message is already signed then we have an authentication
343 * context, i.e. the authentication handshake is complete. Generate
344 * authentication header from message signature.
346 if (msg->signature) {
347 ret = msg_signature_to_auth(auth, msg);
350 * If the message isn't signed then we don't have a initialized
351 * authentication context yet.
353 * Start the authentication handshake if NTLM is selected.
355 } else if ((auth->type == AUTH_TYPE_NTLM) && !auth->gssapi_data) {
356 ret = start_auth_handshake(auth);
359 * We should reach this point only when the authentication context
360 * needs to be initialized.
362 } else {
363 ret = initialize_auth_context(sipe_private, auth, msg);
366 return(ret);
369 static void fill_auth(const gchar *hdr, struct sip_auth *auth)
371 const gchar *param;
373 /* skip authentication identifier */
374 hdr = strchr(hdr, ' ');
375 if (!hdr) {
376 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
377 return;
379 while (*hdr == ' ')
380 hdr++;
382 /* start of next parameter value */
383 while ((param = strchr(hdr, '=')) != NULL) {
384 const gchar *end;
386 /* parameter value type */
387 param++;
388 if (*param == '"') {
389 /* string: xyz="..."(,) */
390 end = strchr(++param, '"');
391 if (!end) {
392 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr);
393 break;
395 } else {
396 /* number: xyz=12345(,) */
397 end = strchr(param, ',');
398 if (!end) {
399 /* last parameter */
400 end = param + strlen(param);
404 #if 0
405 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr);
406 SIPE_DEBUG_INFO("fill_auth: param '%s'", param);
407 SIPE_DEBUG_INFO("fill_auth: end '%s'", end);
408 #endif
410 /* parameter type */
411 if (g_str_has_prefix(hdr, "gssapi-data=\"")) {
412 g_free(auth->gssapi_data);
413 auth->gssapi_data = g_strndup(param, end - param);
414 } else if (g_str_has_prefix(hdr, "opaque=\"")) {
415 g_free(auth->opaque);
416 auth->opaque = g_strndup(param, end - param);
417 } else if (g_str_has_prefix(hdr, "realm=\"")) {
418 g_free(auth->realm);
419 auth->realm = g_strndup(param, end - param);
420 } else if (g_str_has_prefix(hdr, "sts-uri=\"")) {
421 /* Only used with AUTH_TYPE_TLS_DSK */
422 g_free(auth->sts_uri);
423 auth->sts_uri = g_strndup(param, end - param);
424 } else if (g_str_has_prefix(hdr, "targetname=\"")) {
425 g_free(auth->target);
426 auth->target = g_strndup(param, end - param);
427 } else if (g_str_has_prefix(hdr, "version=")) {
428 auth->version = atoi(param);
431 /* skip to next parameter */
432 while ((*end == '"') || (*end == ',') || (*end == ' '))
433 end++;
434 hdr = end;
437 return;
440 static void sign_outgoing_message(struct sipe_core_private *sipe_private,
441 struct sipmsg *msg)
443 struct sip_transport *transport = sipe_private->transport;
444 gchar *buf;
446 if (transport->registrar.type == AUTH_TYPE_UNSET) {
447 return;
450 sipe_make_signature(sipe_private, msg);
452 buf = auth_header(sipe_private, &transport->registrar, msg);
453 if (buf) {
454 sipmsg_add_header_now_pos(msg, "Authorization", buf, 5);
455 g_free(buf);
459 static const gchar *sip_transport_user_agent(struct sipe_core_private *sipe_private)
461 struct sip_transport *transport = sipe_private->transport;
463 if (!transport->user_agent) {
464 const gchar *useragent = sipe_backend_setting(SIPE_CORE_PUBLIC,
465 SIPE_SETTING_USER_AGENT);
466 if (is_empty(useragent)) {
467 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
468 /* ref: lzodefs.h */
469 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
470 #define SIPE_TARGET_PLATFORM "linux"
471 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
472 #define SIPE_TARGET_PLATFORM "bsd"
473 #elif defined(__APPLE__) || defined(__MACOS__)
474 #define SIPE_TARGET_PLATFORM "macosx"
475 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
476 #define SIPE_TARGET_PLATFORM "aix"
477 #elif defined(__solaris__) || defined(__sun)
478 #define SIPE_TARGET_PLATFORM "sun"
479 #elif defined(_WIN32)
480 #define SIPE_TARGET_PLATFORM "win"
481 #elif defined(__CYGWIN__)
482 #define SIPE_TARGET_PLATFORM "cygwin"
483 #elif defined(__hpux__)
484 #define SIPE_TARGET_PLATFORM "hpux"
485 #elif defined(__sgi__)
486 #define SIPE_TARGET_PLATFORM "irix"
487 #else
488 #define SIPE_TARGET_PLATFORM "unknown"
489 #endif
491 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
492 #define SIPE_TARGET_ARCH "x86_64"
493 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
494 #define SIPE_TARGET_ARCH "i386"
495 #elif defined(__ppc64__)
496 #define SIPE_TARGET_ARCH "ppc64"
497 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
498 #define SIPE_TARGET_ARCH "ppc"
499 #elif defined(__hppa__) || defined(__hppa)
500 #define SIPE_TARGET_ARCH "hppa"
501 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
502 #define SIPE_TARGET_ARCH "mips"
503 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
504 #define SIPE_TARGET_ARCH "s390"
505 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
506 #define SIPE_TARGET_ARCH "sparc"
507 #elif defined(__arm__)
508 #define SIPE_TARGET_ARCH "arm"
509 #else
510 #define SIPE_TARGET_ARCH "other"
511 #endif
512 gchar *backend = sipe_backend_version();
513 transport->user_agent = g_strdup_printf("%s Sipe/" PACKAGE_VERSION " (" SIPE_TARGET_PLATFORM "-" SIPE_TARGET_ARCH "; %s)",
514 backend,
515 transport->server_version ? transport->server_version : "");
516 g_free(backend);
517 } else {
518 transport->user_agent = g_strdup(useragent);
521 return(transport->user_agent);
524 void sip_transport_response(struct sipe_core_private *sipe_private,
525 struct sipmsg *msg,
526 guint code,
527 const char *text,
528 const char *body)
530 gchar *name;
531 gchar *value;
532 GString *outstr = g_string_new("");
533 gchar *contact;
534 GSList *tmp;
535 const gchar *keepers[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL };
537 /* Can return NULL! */
538 contact = get_contact(sipe_private);
539 if (contact) {
540 sipmsg_add_header(msg, "Contact", contact);
541 g_free(contact);
544 if (body) {
545 gchar *len = g_strdup_printf("%" G_GSIZE_FORMAT , (gsize) strlen(body));
546 sipmsg_add_header(msg, "Content-Length", len);
547 g_free(len);
548 } else {
549 sipmsg_add_header(msg, "Content-Length", "0");
552 sipmsg_add_header(msg, "User-Agent", sip_transport_user_agent(sipe_private));
554 msg->response = code;
556 sipmsg_strip_headers(msg, keepers);
557 sipmsg_merge_new_headers(msg);
558 sign_outgoing_message(sipe_private, msg);
560 g_string_append_printf(outstr, "SIP/2.0 %d %s\r\n", code, text);
561 tmp = msg->headers;
562 while (tmp) {
563 name = ((struct sipnameval*) (tmp->data))->name;
564 value = ((struct sipnameval*) (tmp->data))->value;
566 g_string_append_printf(outstr, "%s: %s\r\n", name, value);
567 tmp = g_slist_next(tmp);
569 g_string_append_printf(outstr, "\r\n%s", body ? body : "");
570 sipe_utils_message_debug("SIP", outstr->str, NULL, TRUE);
571 sipe_backend_transport_message(sipe_private->transport->connection, outstr->str);
572 g_string_free(outstr, TRUE);
575 static void transactions_remove(struct sipe_core_private *sipe_private,
576 struct transaction *trans)
578 struct sip_transport *transport = sipe_private->transport;
579 if (transport->transactions) {
580 transport->transactions = g_slist_remove(transport->transactions,
581 trans);
582 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport->transactions));
584 if (trans->msg) sipmsg_free(trans->msg);
585 if (trans->payload) {
586 (*trans->payload->destroy)(trans->payload->data);
587 g_free(trans->payload);
589 g_free(trans->key);
590 if (trans->timeout_key) {
591 sipe_schedule_cancel(sipe_private, trans->timeout_key);
592 g_free(trans->timeout_key);
594 g_free(trans);
598 static struct transaction *transactions_find(struct sip_transport *transport,
599 struct sipmsg *msg)
601 GSList *transactions = transport->transactions;
602 const gchar *call_id = sipmsg_find_header(msg, "Call-ID");
603 const gchar *cseq = sipmsg_find_header(msg, "CSeq");
604 gchar *key;
606 if (!call_id || !cseq) {
607 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
608 return NULL;
611 key = g_strdup_printf("<%s><%s>", call_id, cseq);
612 while (transactions) {
613 struct transaction *trans = transactions->data;
614 if (!g_strcasecmp(trans->key, key)) {
615 g_free(key);
616 return trans;
618 transactions = transactions->next;
620 g_free(key);
622 return NULL;
625 static void transaction_timeout_cb(struct sipe_core_private *sipe_private,
626 gpointer data)
628 struct transaction *trans = data;
629 (trans->timeout_callback)(sipe_private, trans->msg, trans);
630 transactions_remove(sipe_private, trans);
633 struct transaction *sip_transport_request_timeout(struct sipe_core_private *sipe_private,
634 const gchar *method,
635 const gchar *url,
636 const gchar *to,
637 const gchar *addheaders,
638 const gchar *body,
639 struct sip_dialog *dialog,
640 TransCallback callback,
641 guint timeout,
642 TransCallback timeout_callback)
644 struct sip_transport *transport = sipe_private->transport;
645 char *buf;
646 struct sipmsg *msg;
647 gchar *ourtag = dialog && dialog->ourtag ? g_strdup(dialog->ourtag) : NULL;
648 gchar *theirtag = dialog && dialog->theirtag ? g_strdup(dialog->theirtag) : NULL;
649 gchar *theirepid = dialog && dialog->theirepid ? g_strdup(dialog->theirepid) : NULL;
650 gchar *callid = dialog && dialog->callid ? g_strdup(dialog->callid) : gencallid();
651 gchar *branch = dialog && dialog->callid ? NULL : genbranch();
652 gchar *route = g_strdup("");
653 gchar *epid = get_epid(sipe_private);
654 int cseq = dialog ? ++dialog->cseq : 1 /* as Call-Id is new in this case */;
655 struct transaction *trans = NULL;
657 if (dialog && dialog->routes)
659 GSList *iter = dialog->routes;
661 while(iter)
663 char *tmp = route;
664 route = g_strdup_printf("%sRoute: %s\r\n", route, (char *)iter->data);
665 g_free(tmp);
666 iter = g_slist_next(iter);
670 if (!ourtag && !dialog) {
671 ourtag = gentag();
674 if (sipe_strequal(method, "REGISTER")) {
675 if (sipe_private->register_callid) {
676 g_free(callid);
677 callid = g_strdup(sipe_private->register_callid);
678 } else {
679 sipe_private->register_callid = g_strdup(callid);
681 cseq = ++transport->cseq;
684 buf = g_strdup_printf("%s %s SIP/2.0\r\n"
685 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
686 "From: <sip:%s>%s%s;epid=%s\r\n"
687 "To: <%s>%s%s%s%s\r\n"
688 "Max-Forwards: 70\r\n"
689 "CSeq: %d %s\r\n"
690 "User-Agent: %s\r\n"
691 "Call-ID: %s\r\n"
692 "%s%s"
693 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n%s",
694 method,
695 dialog && dialog->request ? dialog->request : url,
696 TRANSPORT_DESCRIPTOR,
697 sipe_backend_network_ip_address(),
698 transport->connection->client_port,
699 branch ? ";branch=" : "",
700 branch ? branch : "",
701 sipe_private->username,
702 ourtag ? ";tag=" : "",
703 ourtag ? ourtag : "",
704 epid,
706 theirtag ? ";tag=" : "",
707 theirtag ? theirtag : "",
708 theirepid ? ";epid=" : "",
709 theirepid ? theirepid : "",
710 cseq,
711 method,
712 sip_transport_user_agent(sipe_private),
713 callid,
714 route,
715 addheaders ? addheaders : "",
716 body ? (gsize) strlen(body) : 0,
717 body ? body : "");
720 //printf ("parsing msg buf:\n%s\n\n", buf);
721 msg = sipmsg_parse_msg(buf);
723 g_free(buf);
724 g_free(ourtag);
725 g_free(theirtag);
726 g_free(theirepid);
727 g_free(branch);
728 g_free(route);
729 g_free(epid);
731 sign_outgoing_message(sipe_private, msg);
733 /* The authentication scheme is not ready so we can't send the message.
734 This should only happen for REGISTER messages. */
735 if (!transport->auth_incomplete) {
736 buf = sipmsg_to_string(msg);
738 /* add to ongoing transactions */
739 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
740 if (!sipe_strequal(method, "ACK")) {
741 trans = g_new0(struct transaction, 1);
742 trans->callback = callback;
743 trans->msg = msg;
744 trans->key = g_strdup_printf("<%s><%d %s>", callid, cseq, method);
745 if (timeout_callback) {
746 trans->timeout_callback = timeout_callback;
747 trans->timeout_key = g_strdup_printf("<transaction timeout>%s", trans->key);
748 sipe_schedule_seconds(sipe_private,
749 trans->timeout_key,
750 trans,
751 timeout,
752 transaction_timeout_cb,
753 NULL);
755 transport->transactions = g_slist_append(transport->transactions,
756 trans);
757 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport->transactions));
760 sipe_utils_message_debug("SIP", buf, NULL, TRUE);
761 sipe_backend_transport_message(transport->connection, buf);
762 g_free(buf);
765 if (!trans) sipmsg_free(msg);
766 g_free(callid);
767 return trans;
770 struct transaction *sip_transport_request(struct sipe_core_private *sipe_private,
771 const gchar *method,
772 const gchar *url,
773 const gchar *to,
774 const gchar *addheaders,
775 const gchar *body,
776 struct sip_dialog *dialog,
777 TransCallback callback)
779 return sip_transport_request_timeout(sipe_private,
780 method,
781 url,
783 addheaders,
784 body,
785 dialog,
786 callback,
788 NULL);
791 static void sip_transport_simple_request(struct sipe_core_private *sipe_private,
792 const gchar *method,
793 struct sip_dialog *dialog)
795 sip_transport_request(sipe_private,
796 method,
797 dialog->with,
798 dialog->with,
799 NULL,
800 NULL,
801 dialog,
802 NULL);
805 void sip_transport_ack(struct sipe_core_private *sipe_private,
806 struct sip_dialog *dialog)
808 sip_transport_simple_request(sipe_private, "ACK", dialog);
811 void sip_transport_bye(struct sipe_core_private *sipe_private,
812 struct sip_dialog *dialog)
814 sip_transport_simple_request(sipe_private, "BYE", dialog);
817 struct transaction *sip_transport_info(struct sipe_core_private *sipe_private,
818 const gchar *addheaders,
819 const gchar *body,
820 struct sip_dialog *dialog,
821 TransCallback callback)
823 return sip_transport_request(sipe_private,
824 "INFO",
825 dialog->with,
826 dialog->with,
827 addheaders,
828 body,
829 dialog,
830 callback);
833 struct transaction *sip_transport_invite(struct sipe_core_private *sipe_private,
834 const gchar *addheaders,
835 const gchar *body,
836 struct sip_dialog *dialog,
837 TransCallback callback)
839 return sip_transport_request(sipe_private,
840 "INVITE",
841 dialog->with,
842 dialog->with,
843 addheaders,
844 body,
845 dialog,
846 callback);
849 struct transaction *sip_transport_service(struct sipe_core_private *sipe_private,
850 const gchar *uri,
851 const gchar *addheaders,
852 const gchar *body,
853 TransCallback callback)
855 return sip_transport_request(sipe_private,
856 "SERVICE",
857 uri,
858 uri,
859 addheaders,
860 body,
861 NULL,
862 callback);
865 void sip_transport_subscribe(struct sipe_core_private *sipe_private,
866 const gchar *uri,
867 const gchar *addheaders,
868 const gchar *body,
869 struct sip_dialog *dialog,
870 TransCallback callback)
872 sip_transport_request(sipe_private,
873 "SUBSCRIBE",
874 uri,
875 uri,
876 addheaders,
877 body,
878 dialog,
879 callback);
882 static const gchar *get_auth_header(struct sipe_core_private *sipe_private,
883 struct sip_auth *auth,
884 struct sipmsg *msg)
886 auth->type = AUTH_TYPE_NTLM;
887 #if defined(HAVE_LIBKRB5) || defined(HAVE_SSPI)
888 if (SIPE_CORE_PUBLIC_FLAG_IS(KRB5)) {
889 auth->type = AUTH_TYPE_KERBEROS;
891 #endif
892 if (SIPE_CORE_PUBLIC_FLAG_IS(TLS_DSK)) {
893 auth->type = AUTH_TYPE_TLS_DSK;
895 auth->protocol = auth_type_to_protocol[auth->type];
897 return(sipmsg_find_auth_header(msg, auth->protocol));
900 static void do_register(struct sipe_core_private *sipe_private,
901 gboolean deregister);
903 static void do_reauthenticate_cb(struct sipe_core_private *sipe_private,
904 SIPE_UNUSED_PARAMETER gpointer unused)
906 struct sip_transport *transport = sipe_private->transport;
908 /* register again when security token expires */
909 /* we have to start a new authentication as the security token
910 * is almost expired by sending a not signed REGISTER message */
911 SIPE_DEBUG_INFO_NOFORMAT("do a full reauthentication");
912 sipe_auth_free(&transport->registrar);
913 sipe_auth_free(&transport->proxy);
914 sipe_schedule_cancel(sipe_private, "<registration>");
915 transport->reregister_set = FALSE;
916 transport->register_attempt = 0;
917 do_register(sipe_private, FALSE);
918 transport->reauthenticate_set = FALSE;
921 static void sip_transport_default_contact(struct sipe_core_private *sipe_private)
923 struct sip_transport *transport = sipe_private->transport;
924 sipe_private->contact = g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
925 sipe_private->username,
926 transport->connection->client_port,
927 sipe_backend_network_ip_address(),
928 TRANSPORT_DESCRIPTOR);
931 static void do_register_cb(struct sipe_core_private *sipe_private,
932 SIPE_UNUSED_PARAMETER void *unused)
934 do_register(sipe_private, FALSE);
937 static void sip_transport_set_reregister(struct sipe_core_private *sipe_private,
938 int expires)
940 sipe_schedule_seconds(sipe_private,
941 "<registration>",
942 NULL,
943 expires,
944 do_register_cb,
945 NULL);
948 static void sipe_server_register(struct sipe_core_private *sipe_private,
949 guint type,
950 gchar *server_name,
951 guint server_port);
953 static gboolean process_register_response(struct sipe_core_private *sipe_private,
954 struct sipmsg *msg,
955 SIPE_UNUSED_PARAMETER struct transaction *trans)
957 struct sip_transport *transport = sipe_private->transport;
958 const gchar *expires_header;
959 int expires, i;
960 GSList *hdr = msg->headers;
961 struct sipnameval *elem;
963 expires_header = sipmsg_find_header(msg, "Expires");
964 expires = expires_header != NULL ? strtol(expires_header, NULL, 10) : 0;
965 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires);
967 switch (msg->response) {
968 case 200:
969 if (expires) {
970 const gchar *contact_hdr;
971 const gchar *auth_hdr;
972 gchar *gruu = NULL;
973 gchar *uuid;
974 gchar *timeout;
975 const gchar *server_hdr = sipmsg_find_header(msg, "Server");
977 if (!transport->reregister_set) {
978 sip_transport_set_reregister(sipe_private,
979 expires);
980 transport->reregister_set = TRUE;
983 if (server_hdr && !transport->server_version) {
984 transport->server_version = g_strdup(server_hdr);
985 g_free(transport->user_agent);
986 transport->user_agent = NULL;
989 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
990 if (auth_hdr) {
991 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
992 fill_auth(auth_hdr, &transport->registrar);
995 if (!transport->reauthenticate_set) {
996 gchar *action_name = g_strdup_printf("<%s>", "+reauthentication");
997 guint reauth_timeout;
999 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1001 if (transport->registrar.type == AUTH_TYPE_KERBEROS && transport->registrar.expires > 0) {
1002 /* assuming normal Kerberos ticket expiration of about 8-10 hours */
1003 reauth_timeout = transport->registrar.expires - 300;
1004 } else {
1005 /* NTLM: we have to reauthenticate as our security token expires
1006 after eight hours (be five minutes early) */
1007 reauth_timeout = (8 * 3600) - 300;
1009 sipe_schedule_seconds(sipe_private,
1010 action_name,
1011 NULL,
1012 reauth_timeout,
1013 do_reauthenticate_cb,
1014 NULL);
1015 g_free(action_name);
1016 transport->reauthenticate_set = TRUE;
1019 sipe_backend_connection_completed(SIPE_CORE_PUBLIC);
1021 uuid = get_uuid(sipe_private);
1023 // There can be multiple Contact headers (one per location where the user is logged in) so
1024 // make sure to only get the one for this uuid
1025 for (i = 0; (contact_hdr = sipmsg_find_header_instance (msg, "Contact", i)); i++) {
1026 gchar * valid_contact = sipmsg_find_part_of_header (contact_hdr, uuid, NULL, NULL);
1027 if (valid_contact) {
1028 gruu = sipmsg_find_part_of_header(contact_hdr, "gruu=\"", "\"", NULL);
1029 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1030 g_free(valid_contact);
1031 break;
1032 } else {
1033 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1036 g_free(uuid);
1038 g_free(sipe_private->contact);
1039 if(gruu) {
1040 sipe_private->contact = g_strdup_printf("<%s>", gruu);
1041 g_free(gruu);
1042 } else {
1043 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1044 sip_transport_default_contact(sipe_private);
1046 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007);
1047 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER);
1048 SIPE_CORE_PRIVATE_FLAG_UNSET(BATCHED_SUPPORT);
1050 while(hdr)
1052 elem = hdr->data;
1053 if (sipe_strcase_equal(elem->name, "Supported")) {
1054 if (sipe_strcase_equal(elem->value, "msrtc-event-categories")) {
1055 /* We interpret this as OCS2007+ indicator */
1056 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007);
1057 SIPE_DEBUG_INFO("Supported: %s (indicates OCS2007+)", elem->value);
1059 if (sipe_strcase_equal(elem->value, "adhoclist")) {
1060 SIPE_CORE_PRIVATE_FLAG_SET(BATCHED_SUPPORT);
1061 SIPE_DEBUG_INFO("Supported: %s", elem->value);
1064 if (sipe_strcase_equal(elem->name, "Allow-Events")){
1065 gchar **caps = g_strsplit(elem->value,",",0);
1066 i = 0;
1067 while (caps[i]) {
1068 sipe_private->allowed_events = g_slist_append(sipe_private->allowed_events, g_strdup(caps[i]));
1069 SIPE_DEBUG_INFO("Allow-Events: %s", caps[i]);
1070 i++;
1072 g_strfreev(caps);
1074 if (sipe_strcase_equal(elem->name, "ms-user-logon-data")) {
1075 if (sipe_strcase_equal(elem->value, "RemoteUser")) {
1076 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER);
1077 SIPE_DEBUG_INFO_NOFORMAT("ms-user-logon-data: RemoteUser (connected "
1078 "via Edge Server)");
1081 hdr = g_slist_next(hdr);
1084 /* rejoin open chats to be able to use them by continue to send messages */
1085 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC);
1087 /* subscriptions */
1088 if (!transport->subscribed) { //do it just once, not every re-register
1090 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-contacts",
1091 (GCompareFunc)g_ascii_strcasecmp)) {
1092 sipe_subscribe_roaming_contacts(sipe_private);
1095 /* For 2007+ it does not make sence to subscribe to:
1096 * vnd-microsoft-roaming-ACL
1097 * vnd-microsoft-provisioning (not v2)
1098 * presence.wpending
1099 * These are for backward compatibility.
1101 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))
1103 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-self",
1104 (GCompareFunc)g_ascii_strcasecmp)) {
1105 sipe_subscribe_roaming_self(sipe_private);
1107 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-provisioning-v2",
1108 (GCompareFunc)g_ascii_strcasecmp)) {
1109 sipe_subscribe_roaming_provisioning_v2(sipe_private);
1112 /* For 2005- servers */
1113 else
1115 //sipe_options_request(sip, sipe_private->public.sip_domain);
1117 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-roaming-ACL",
1118 (GCompareFunc)g_ascii_strcasecmp)) {
1119 sipe_subscribe_roaming_acl(sipe_private);
1121 if (g_slist_find_custom(sipe_private->allowed_events, "vnd-microsoft-provisioning",
1122 (GCompareFunc)g_ascii_strcasecmp)) {
1123 sipe_subscribe_roaming_provisioning(sipe_private);
1125 if (g_slist_find_custom(sipe_private->allowed_events, "presence.wpending",
1126 (GCompareFunc)g_ascii_strcasecmp)) {
1127 sipe_subscribe_presence_wpending(sipe_private,
1128 NULL);
1131 /* For 2007+ we publish our initial statuses and calendar data only after
1132 * received our existing publications in sipe_process_roaming_self()
1133 * Only in this case we know versions of current publications made
1134 * on our behalf.
1136 /* For 2005- we publish our initial statuses only after
1137 * received our existing UserInfo data in response to
1138 * self subscription.
1139 * Only in this case we won't override existing UserInfo data
1140 * set earlier or by other client on our behalf.
1144 transport->subscribed = TRUE;
1147 timeout = sipmsg_find_part_of_header(sipmsg_find_header(msg, "ms-keep-alive"),
1148 "timeout=", ";", NULL);
1149 if (timeout != NULL) {
1150 sscanf(timeout, "%u", &sipe_private->public.keepalive_timeout);
1151 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1152 sipe_private->public.keepalive_timeout);
1153 g_free(timeout);
1156 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport->cseq);
1158 break;
1159 case 301:
1161 gchar *redirect = parse_from(sipmsg_find_header(msg, "Contact"));
1163 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1165 if (redirect && (g_strncasecmp("sip:", redirect, 4) == 0)) {
1166 gchar **parts = g_strsplit(redirect + 4, ";", 0);
1167 gchar **tmp;
1168 gchar *hostname;
1169 int port = 0;
1170 guint transport = SIPE_TRANSPORT_TLS;
1171 int i = 1;
1173 tmp = g_strsplit(parts[0], ":", 0);
1174 hostname = g_strdup(tmp[0]);
1175 if (tmp[1]) port = strtoul(tmp[1], NULL, 10);
1176 g_strfreev(tmp);
1178 while (parts[i]) {
1179 tmp = g_strsplit(parts[i], "=", 0);
1180 if (tmp[1]) {
1181 if (g_strcasecmp("transport", tmp[0]) == 0) {
1182 if (g_strcasecmp("tcp", tmp[1]) == 0) {
1183 transport = SIPE_TRANSPORT_TCP;
1187 g_strfreev(tmp);
1188 i++;
1190 g_strfreev(parts);
1192 /* Close old connection */
1193 sipe_core_connection_cleanup(sipe_private);
1195 /* Create new connection */
1196 sipe_server_register(sipe_private, transport, hostname, port);
1197 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1198 hostname, port, transport);
1200 g_free(redirect);
1202 break;
1203 case 401:
1205 const char *auth_hdr;
1207 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport->registrar.retries);
1208 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1209 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1210 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1211 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
1212 _("Authentication failed"));
1213 return TRUE;
1216 if (transport->reauthenticate_set) {
1217 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1218 do_reauthenticate_cb(sipe_private, NULL);
1219 return TRUE;
1222 auth_hdr = get_auth_header(sipe_private, &transport->registrar, msg);
1223 if (!auth_hdr) {
1224 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1225 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
1226 _("Incompatible authentication scheme chosen"));
1227 return TRUE;
1229 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr);
1230 fill_auth(auth_hdr, &transport->registrar);
1231 transport->reregister_set = FALSE;
1232 transport->register_attempt = 0;
1233 do_register(sipe_private,
1234 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC));
1236 break;
1237 case 403:
1239 gchar *reason;
1240 gchar *warning;
1241 sipmsg_parse_warning(msg, &reason);
1242 reason = reason ? reason : sipmsg_get_ms_diagnostics_public_reason(msg);
1243 warning = g_strdup_printf(_("You have been rejected by the server: %s"),
1244 reason ? reason : _("no reason given"));
1245 g_free(reason);
1247 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1248 SIPE_CONNECTION_ERROR_INVALID_SETTINGS,
1249 warning);
1250 g_free(warning);
1251 return TRUE;
1253 break;
1254 case 404:
1256 const gchar *diagnostics = sipmsg_find_header(msg, "ms-diagnostics");
1257 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1258 gchar *warning;
1259 warning = g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1260 diagnostics ? (reason ? reason : _("no reason given")) :
1261 _("SIP is either not enabled for the destination URI or it does not exist"));
1262 g_free(reason);
1264 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1265 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
1266 warning);
1267 g_free(warning);
1268 return TRUE;
1270 break;
1271 case 504: /* Server time-out */
1272 /* first attempt + 5 retries */
1273 if (transport->register_attempt < 6) {
1274 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1275 transport->register_attempt);
1276 sip_transport_set_reregister(sipe_private, 60);
1277 return TRUE;
1279 /* FALLTHROUGH */
1280 case 503:
1282 gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);
1283 gchar *warning;
1284 warning = g_strdup_printf(_("Service unavailable: %s"), reason ? reason : _("no reason given"));
1285 g_free(reason);
1287 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1288 SIPE_CONNECTION_ERROR_NETWORK,
1289 warning);
1290 g_free(warning);
1291 return TRUE;
1293 break;
1295 return TRUE;
1298 static gboolean register_response_timeout(struct sipe_core_private *sipe_private,
1299 SIPE_UNUSED_PARAMETER struct sipmsg *msg,
1300 SIPE_UNUSED_PARAMETER struct transaction *trans)
1302 struct sip_transport *transport = sipe_private->transport;
1303 if (transport->register_attempt < 6) {
1304 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1305 transport->register_attempt);
1306 do_register(sipe_private, FALSE);
1307 } else {
1308 gchar *warning = g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1309 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1310 SIPE_CONNECTION_ERROR_NETWORK,
1311 warning);
1312 g_free(warning);
1314 return TRUE;
1317 static void do_register(struct sipe_core_private *sipe_private,
1318 gboolean deregister)
1320 struct sip_transport *transport = sipe_private->transport;
1321 char *uri;
1322 char *to;
1323 char *hdr;
1324 char *uuid;
1326 if (!sipe_private->public.sip_domain) return;
1328 if (!deregister) {
1329 if (transport->reregister_set) {
1330 transport->reregister_set = FALSE;
1331 transport->register_attempt = 1;
1332 } else {
1333 transport->register_attempt++;
1337 transport->auth_incomplete = FALSE;
1339 uuid = get_uuid(sipe_private);
1340 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"
1341 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1342 "Event: registration\r\n"
1343 "Allow-Events: presence\r\n"
1344 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1345 "%s",
1346 sipe_backend_network_ip_address(),
1347 transport->connection->client_port,
1348 TRANSPORT_DESCRIPTOR,
1349 uuid,
1350 deregister ? "Expires: 0\r\n" : "");
1351 g_free(uuid);
1353 uri = sip_uri_from_name(sipe_private->public.sip_domain);
1354 to = sip_uri_self(sipe_private);
1355 sip_transport_request_timeout(sipe_private,
1356 "REGISTER",
1357 uri,
1359 hdr,
1361 NULL,
1362 process_register_response,
1364 deregister ? NULL : register_response_timeout);
1365 g_free(to);
1366 g_free(uri);
1367 g_free(hdr);
1369 if (deregister) {
1370 /* Make sure that all messages are pushed to the server
1371 before the connection gets shut down */
1372 SIPE_DEBUG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1373 sipe_backend_transport_flush(transport->connection);
1377 void sip_transport_deregister(struct sipe_core_private *sipe_private)
1379 do_register(sipe_private, TRUE);
1382 void sip_transport_disconnect(struct sipe_core_private *sipe_private)
1384 struct sip_transport *transport = sipe_private->transport;
1386 /* transport can be NULL during connection setup */
1387 if (transport) {
1388 sipe_backend_transport_disconnect(transport->connection);
1390 sipe_auth_free(&transport->registrar);
1391 sipe_auth_free(&transport->proxy);
1393 g_free(transport->server_name);
1394 g_free(transport->server_version);
1395 g_free(transport->user_agent);
1397 while (transport->transactions)
1398 transactions_remove(sipe_private,
1399 transport->transactions->data);
1401 g_free(transport);
1404 sipe_private->transport = NULL;
1405 sipe_private->service_data = NULL;
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, TRUE, FALSE);
1438 } else if (sipe_strequal(method, "BENOTIFY")) {
1439 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1440 process_incoming_notify(sipe_private, msg, TRUE, TRUE);
1441 } else if (sipe_strequal(method, "INVITE")) {
1442 process_incoming_invite(sipe_private, msg);
1443 } else if (sipe_strequal(method, "REFER")) {
1444 process_incoming_refer(sipe_private, msg);
1445 } else if (sipe_strequal(method, "OPTIONS")) {
1446 process_incoming_options(sipe_private, msg);
1447 } else if (sipe_strequal(method, "INFO")) {
1448 process_incoming_info(sipe_private, msg);
1449 } else if (sipe_strequal(method, "ACK")) {
1450 /* ACK's don't need any response */
1451 } else if (sipe_strequal(method, "PRACK")) {
1452 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1453 } else if (sipe_strequal(method, "SUBSCRIBE")) {
1454 /* LCS 2005 sends us these - just respond 200 OK */
1455 sip_transport_response(sipe_private, msg, 200, "OK", NULL);
1456 } else if (sipe_strequal(method, "CANCEL")) {
1457 process_incoming_cancel(sipe_private, msg);
1458 } else if (sipe_strequal(method, "BYE")) {
1459 process_incoming_bye(sipe_private, msg);
1460 } else {
1461 sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
1462 notfound = TRUE;
1465 } else { /* response */
1466 struct transaction *trans = transactions_find(transport, msg);
1467 if (trans) {
1468 if (msg->response < 200) {
1469 /* ignore provisional response */
1470 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg->response);
1472 /* Transaction not yet completed */
1473 trans = NULL;
1475 } else if (msg->response == 401) { /* Unauthorized */
1477 if (sipe_strequal(trans->msg->method, "REGISTER")) {
1478 /* Expected response during authentication handshake */
1479 transport->registrar.retries++;
1480 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport->cseq);
1481 } else {
1482 gchar *resend;
1484 /* Are we registered? */
1485 if (transport->reregister_set) {
1486 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1487 sign_outgoing_message(sipe_private,
1488 trans->msg);
1489 } else {
1491 * We don't have a valid authentication at the moment.
1492 * Resend message unchanged. It will be rejected again
1493 * and hopefully by then we have a valid authentication.
1495 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1498 /* Resend request */
1499 resend = sipmsg_to_string(trans->msg);
1500 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1501 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1502 g_free(resend);
1504 /* Transaction not yet completed */
1505 trans = NULL;
1508 } else if (msg->response == 407) { /* Proxy Authentication Required */
1510 if (transport->proxy.retries > 30) {
1511 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1512 } else {
1513 gchar *resend, *auth;
1514 const gchar *auth_hdr;
1516 transport->proxy.retries++;
1518 /* do proxy authentication */
1519 auth_hdr = sipmsg_find_header(msg, "Proxy-Authenticate");
1520 if (auth_hdr) {
1521 guint i;
1522 transport->proxy.type = AUTH_TYPE_UNSET;
1523 for (i = 0; i < AUTH_PROTOCOLS; i++) {
1524 const gchar *protocol = auth_type_to_protocol[i];
1525 if (protocol &&
1526 !g_strncasecmp(auth_hdr, protocol, strlen(protocol))) {
1527 SIPE_DEBUG_INFO("proxy auth: type %s", protocol);
1528 transport->proxy.type = i;
1529 transport->proxy.protocol = protocol;
1530 break;
1533 if (transport->proxy.type == AUTH_TYPE_UNSET)
1534 SIPE_DEBUG_ERROR("Unknown proxy authentication: %s", auth_hdr);
1535 fill_auth(auth_hdr, &transport->proxy);
1537 auth = auth_header(sipe_private, &transport->proxy, trans->msg);
1538 if (auth) {
1539 sipmsg_remove_header_now(trans->msg, "Proxy-Authorization");
1540 sipmsg_add_header_now_pos(trans->msg, "Proxy-Authorization", auth, 5);
1541 g_free(auth);
1544 /* resend request */
1545 resend = sipmsg_to_string(trans->msg);
1546 sipe_utils_message_debug("SIP", resend, NULL, TRUE);
1547 sipe_backend_transport_message(sipe_private->transport->connection, resend);
1548 g_free(resend);
1550 /* Transaction not yet completed */
1551 trans = NULL;
1554 } else {
1555 transport->registrar.retries = 0;
1556 transport->proxy.retries = 0;
1559 /* Is transaction completed? */
1560 if (trans) {
1561 if (trans->callback) {
1562 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1563 /* call the callback to process response */
1564 (trans->callback)(sipe_private, msg, trans);
1567 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport->cseq);
1568 transactions_remove(sipe_private, trans);
1570 } else {
1571 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1572 notfound = TRUE;
1576 if (notfound) {
1577 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method, msg->response);
1581 static void sip_transport_input(struct sipe_transport_connection *conn)
1583 struct sipe_core_private *sipe_private = conn->user_data;
1584 struct sip_transport *transport = sipe_private->transport;
1585 gchar *cur = conn->buffer;
1587 /* according to the RFC remove CRLF at the beginning */
1588 while (*cur == '\r' || *cur == '\n') {
1589 cur++;
1591 if (cur != conn->buffer)
1592 sipe_utils_shrink_buffer(conn, cur);
1594 /* Received a full Header? */
1595 transport->processing_input = TRUE;
1596 while (transport->processing_input &&
1597 ((cur = strstr(conn->buffer, "\r\n\r\n")) != NULL)) {
1598 struct sipmsg *msg;
1599 guint remainder;
1601 cur += 2;
1602 cur[0] = '\0';
1603 msg = sipmsg_parse_header(conn->buffer);
1605 cur += 2;
1606 remainder = conn->buffer_used - (cur - conn->buffer);
1607 if (msg && remainder >= (guint) msg->bodylen) {
1608 char *dummy = g_malloc(msg->bodylen + 1);
1609 memcpy(dummy, cur, msg->bodylen);
1610 dummy[msg->bodylen] = '\0';
1611 msg->body = dummy;
1612 cur += msg->bodylen;
1613 sipe_utils_message_debug("SIP",
1614 conn->buffer,
1615 msg->body,
1616 FALSE);
1617 sipe_utils_shrink_buffer(conn, cur);
1618 } else {
1619 if (msg){
1620 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder, msg->bodylen, (int)strlen(conn->buffer));
1621 sipmsg_free(msg);
1624 /* restore header for next try */
1625 cur[-2] = '\r';
1626 return;
1629 // Verify the signature before processing it
1630 if (sip_sec_context_is_ready(transport->registrar.gssapi_context)) {
1631 struct sipmsg_breakdown msgbd;
1632 gchar *signature_input_str;
1633 gchar *rspauth;
1634 msgbd.msg = msg;
1635 sipmsg_breakdown_parse(&msgbd, transport->registrar.realm, transport->registrar.target,
1636 transport->registrar.protocol);
1637 signature_input_str = sipmsg_breakdown_get_string(transport->registrar.version, &msgbd);
1639 rspauth = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Authentication-Info"), "rspauth=\"", "\"", NULL);
1641 if (rspauth != NULL) {
1642 if (!sip_sec_verify_signature(transport->registrar.gssapi_context, signature_input_str, rspauth)) {
1643 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1644 process_input_message(sipe_private, msg);
1645 } else {
1646 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1647 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1648 SIPE_CONNECTION_ERROR_NETWORK,
1649 _("Invalid message signature received"));
1651 } else if ((msg->response == 401) ||
1652 sipe_strequal(msg->method, "REGISTER")) {
1653 /* a) Retry non-REGISTER requests with updated authentication */
1654 /* b) We must always process REGISTER responses */
1655 process_input_message(sipe_private, msg);
1656 } else {
1657 /* OCS sends provisional messages that are *not* signed */
1658 if (msg->response >= 200) {
1659 /* We are not calling process_input_message(),
1660 so we need to drop the transaction here. */
1661 struct transaction *trans = transactions_find(transport, msg);
1662 if (trans) transactions_remove(sipe_private, trans);
1664 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1666 g_free(signature_input_str);
1668 g_free(rspauth);
1669 sipmsg_breakdown_free(&msgbd);
1670 } else {
1671 process_input_message(sipe_private, msg);
1674 sipmsg_free(msg);
1676 /* Redirect: old content of "transport" is no longer valid */
1677 transport = sipe_private->transport;
1681 static void sip_transport_connected(struct sipe_transport_connection *conn)
1683 struct sipe_core_private *sipe_private = conn->user_data;
1684 sipe_private->service_data = NULL;
1685 do_register(sipe_private, FALSE);
1688 static void resolve_next_service(struct sipe_core_private *sipe_private,
1689 const struct sip_service_data *start);
1690 static void sip_transport_error(struct sipe_transport_connection *conn,
1691 const gchar *msg)
1693 struct sipe_core_private *sipe_private = conn->user_data;
1695 /* This failed attempt was based on a DNS SRV record */
1696 if (sipe_private->service_data) {
1697 resolve_next_service(sipe_private, NULL);
1698 } else {
1699 sipe_backend_connection_error(SIPE_CORE_PUBLIC,
1700 SIPE_CONNECTION_ERROR_NETWORK,
1701 msg);
1705 /* server_name must be g_alloc()'ed */
1706 static void sipe_server_register(struct sipe_core_private *sipe_private,
1707 guint type,
1708 gchar *server_name,
1709 guint server_port)
1711 sipe_connect_setup setup = {
1712 type,
1713 server_name,
1714 (server_port != 0) ? server_port :
1715 (type == SIPE_TRANSPORT_TLS) ? 5061 : 5060,
1716 sipe_private,
1717 sip_transport_connected,
1718 sip_transport_input,
1719 sip_transport_error
1721 struct sip_transport *transport = g_new0(struct sip_transport, 1);
1723 transport->server_name = server_name;
1724 transport->server_port = setup.server_port;
1725 transport->connection = sipe_backend_transport_connect(SIPE_CORE_PUBLIC,
1726 &setup);
1727 sipe_private->transport = transport;
1730 struct sip_service_data {
1731 const char *protocol;
1732 const char *transport;
1733 guint type;
1736 /* Service list for autodection */
1737 static const struct sip_service_data service_autodetect[] = {
1738 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1739 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1740 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1741 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1742 { NULL, NULL, 0 }
1745 /* Service list for SSL/TLS */
1746 static const struct sip_service_data service_tls[] = {
1747 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS }, /* for internal TLS connections */
1748 { "sip", "tls", SIPE_TRANSPORT_TLS }, /* for external TLS connections */
1749 { NULL, NULL, 0 }
1752 /* Service list for TCP */
1753 static const struct sip_service_data service_tcp[] = {
1754 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP }, /* for internal TCP connections */
1755 { "sip", "tcp", SIPE_TRANSPORT_TCP }, /*.for external TCP connections */
1756 { NULL, NULL, 0 }
1759 static const struct sip_service_data *services[] = {
1760 service_autodetect, /* SIPE_TRANSPORT_AUTO */
1761 service_tls, /* SIPE_TRANSPORT_TLS */
1762 service_tcp /* SIPE_TRANSPORT_TCP */
1765 static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public,
1766 const gchar *hostname, guint port)
1768 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1770 sipe_private->dns_query = NULL;
1772 if (hostname) {
1773 SIPE_DEBUG_INFO("sipe_core_dns_resolved - SRV hostname: %s port: %d",
1774 hostname, port);
1775 sipe_server_register(sipe_private,
1776 sipe_private->service_data->type,
1777 g_strdup(hostname), port);
1778 } else {
1779 resolve_next_service(SIPE_CORE_PRIVATE, NULL);
1783 static void resolve_next_service(struct sipe_core_private *sipe_private,
1784 const struct sip_service_data *start)
1786 if (start) {
1787 sipe_private->service_data = start;
1788 } else {
1789 sipe_private->service_data++;
1790 if (sipe_private->service_data->protocol == NULL) {
1791 guint type = sipe_private->transport_type;
1793 /* We tried all services */
1794 sipe_private->service_data = NULL;
1796 /* Try connecting to the SIP hostname directly */
1797 SIPE_DEBUG_INFO_NOFORMAT("no SRV records found; using SIP domain as fallback");
1798 if (type == SIPE_TRANSPORT_AUTO)
1799 type = SIPE_TRANSPORT_TLS;
1801 sipe_server_register(sipe_private, type,
1802 g_strdup(sipe_private->public.sip_domain),
1804 return;
1808 /* Try to resolve next service */
1809 sipe_private->dns_query = sipe_backend_dns_query_srv(
1810 SIPE_CORE_PUBLIC,
1811 sipe_private->service_data->protocol,
1812 sipe_private->service_data->transport,
1813 sipe_private->public.sip_domain,
1814 (sipe_dns_resolved_cb) sipe_core_dns_resolved,
1815 SIPE_CORE_PUBLIC);
1818 void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public,
1819 guint transport,
1820 const gchar *server,
1821 const gchar *port)
1823 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
1826 * Initializing the certificate sub-system will trigger the generation
1827 * of a cryptographic key pair which takes time. If we do this after we
1828 * have connected to the server then there is a risk that we run into a
1829 * SIP connection timeout. So let's get this out of the way now...
1831 * This is currently only needed if the user has selected TLS-DSK.
1833 if (SIPE_CORE_PUBLIC_FLAG_IS(TLS_DSK))
1834 sipe_certificate_init(sipe_private);
1836 if (server) {
1837 /* Use user specified server[:port] */
1838 int port_number = 0;
1840 if (port)
1841 port_number = atoi(port);
1843 SIPE_DEBUG_INFO("sipe_core_connect: user specified SIP server %s:%d",
1844 server, port_number);
1846 sipe_server_register(sipe_private, transport,
1847 g_strdup(server), port_number);
1848 } else {
1849 /* Server auto-discovery */
1851 /* Remember user specified transport type */
1852 sipe_private->transport_type = transport;
1853 resolve_next_service(sipe_private, services[transport]);
1857 void sipe_core_transport_sip_keepalive(struct sipe_core_public *sipe_public)
1859 SIPE_DEBUG_INFO("sending keep alive %d",
1860 sipe_public->keepalive_timeout);
1861 sipe_utils_message_debug("SIP", "", NULL, TRUE);
1862 sipe_backend_transport_message(SIPE_CORE_PRIVATE->transport->connection,
1863 "\r\n\r\n");
1866 int sip_transaction_cseq(struct transaction *trans)
1868 int cseq;
1870 g_return_val_if_fail(trans && trans->key, 0);
1872 sscanf(trans->key, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq);
1873 return cseq;
1877 Local Variables:
1878 mode: c
1879 c-file-style: "bsd"
1880 indent-tabs-mode: t
1881 tab-width: 8
1882 End: