2 * @file sip-transport.c
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
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
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.
61 #include "sipe-common.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"
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"
81 struct sip_sec_context
*gssapi_context
;
84 const gchar
*protocol
;
94 /* sip-transport.c private data */
95 struct sip_transport
{
96 struct sipe_transport_connection
*connection
;
100 gchar
*server_version
;
104 GSList
*transactions
;
106 struct sip_auth registrar
;
107 struct sip_auth proxy
;
110 guint register_attempt
;
112 gboolean processing_input
; /* whether full header received */
113 gboolean auth_incomplete
; /* whether authentication not completed */
114 gboolean reregister_set
; /* whether reregister timer set */
115 gboolean reauthenticate_set
; /* whether reauthenticate timer set */
116 gboolean subscribed
; /* whether subscribed to events, except buddies presence */
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
);
134 auth
->protocol
= NULL
;
137 g_free(auth
->sts_uri
);
138 auth
->sts_uri
= NULL
;
139 g_free(auth
->target
);
142 auth
->type
= AUTH_TYPE_UNSET
;
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
,
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
;
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 gchar
*auth_header_version(struct sip_auth
*auth
)
178 return(auth
->version
> 2 ?
179 g_strdup_printf(", version=%d", auth
->version
) :
183 static const gchar
*const auth_type_to_protocol
[] = {
184 NULL
, /* AUTH_TYPE_UNSET */
185 "NTLM", /* AUTH_TYPE_NTLM */
186 "Kerberos", /* AUTH_TYPE_KERBEROS */
187 NULL
, /* AUTH_TYPE_NEGOTIATE */
188 "TLS-DSK", /* AUTH_TYPE_TLS_DSK */
190 #define AUTH_PROTOCOLS (sizeof(auth_type_to_protocol)/sizeof(gchar *))
192 static gchar
*msg_signature_to_auth(struct sip_auth
*auth
,
195 return(g_strdup_printf("%s qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
197 auth
->opaque
, auth
->realm
, auth
->target
,
198 msg
->rand
, msg
->num
, msg
->signature
));
201 static gchar
*initialize_auth_context(struct sipe_core_private
*sipe_private
,
202 struct sip_auth
*auth
,
206 gchar
*gssapi_data
= NULL
;
212 /* Create security context or handshake continuation? */
213 if (auth
->gssapi_context
) {
214 /* Perform next step in authentication handshake */
215 int status
= sip_sec_init_context_step(auth
->gssapi_context
,
221 /* If authentication is completed gssapi_data can be NULL */
223 !(sip_sec_context_is_ready(auth
->gssapi_context
) || gssapi_data
)) {
224 SIPE_DEBUG_ERROR_NOFORMAT("initialize_auth_context: security context continuation failed");
226 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
227 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
,
228 _("Failed to authenticate to server"));
233 /* Create security context */
234 struct sipe_account_data
*sip
= SIPE_ACCOUNT_DATA_PRIVATE
;
235 const gchar
*authuser
= sip
->authuser
;
236 gpointer password
= sip
->password
;
238 if (is_empty(authuser
)) {
239 authuser
= sipe_private
->username
;
242 /* For TLS-DSK the "password" is a certificate */
243 if (auth
->type
== AUTH_TYPE_TLS_DSK
) {
244 password
= sipe_certificate_tls_dsk_find(sipe_private
,
249 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK Certificate Provisioning URI %s",
251 if (!sipe_certificate_tls_dsk_generate(sipe_private
,
255 gchar
*tmp
= g_strdup_printf(_("Can't request certificate from %s"),
257 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
258 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
,
263 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
264 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
,
265 _("No URI for certificate provisioning service provided"));
268 /* we can't authenticate the message yet */
269 sipe_private
->transport
->auth_incomplete
= TRUE
;
273 SIPE_DEBUG_INFO("initialize_auth_context: TLS-DSK certificate for target '%s' found.",
278 gssapi_data
= sip_sec_init_context(&(auth
->gssapi_context
),
281 SIPE_CORE_PUBLIC_FLAG_IS(SSO
),
282 sip
->authdomain
? sip
->authdomain
: "",
287 if (!gssapi_data
|| !auth
->gssapi_context
) {
289 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
290 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
,
291 _("Failed to authenticate to server"));
296 if ((auth
->version
> 3) &&
297 sip_sec_context_is_ready(auth
->gssapi_context
)) {
298 sipe_make_signature(sipe_private
, msg
);
299 sign_str
= g_strdup_printf(", crand=\"%s\", cnum=\"%s\", response=\"%s\"",
300 msg
->rand
, msg
->num
, msg
->signature
);
302 sign_str
= g_strdup("");
306 gssapi_str
= g_strdup_printf(", gssapi-data=\"%s\"",
310 gssapi_str
= g_strdup("");
313 opaque_str
= auth
->opaque
? g_strdup_printf(", opaque=\"%s\"", auth
->opaque
) : g_strdup("");
314 version_str
= auth_header_version(auth
);
315 ret
= g_strdup_printf("%s qop=\"auth\"%s, realm=\"%s\", targetname=\"%s\"%s%s%s",
316 auth
->protocol
, opaque_str
,
317 auth
->realm
, auth
->target
,
318 gssapi_str
, version_str
, sign_str
);
327 static gchar
*start_auth_handshake(struct sip_auth
*auth
)
329 gchar
*version_str
= auth_header_version(auth
);
330 gchar
*ret
= g_strdup_printf("%s qop=\"auth\", realm=\"%s\", targetname=\"%s\", gssapi-data=\"\"%s",
332 auth
->realm
, auth
->target
,
338 static gchar
*auth_header(struct sipe_core_private
*sipe_private
,
339 struct sip_auth
*auth
,
345 * If the message is already signed then we have an authentication
346 * context, i.e. the authentication handshake is complete. Generate
347 * authentication header from message signature.
349 if (msg
->signature
) {
350 ret
= msg_signature_to_auth(auth
, msg
);
353 * If the message isn't signed then we don't have a initialized
354 * authentication context yet.
356 * Start the authentication handshake if NTLM is selected.
358 } else if ((auth
->type
== AUTH_TYPE_NTLM
) && !auth
->gssapi_data
) {
359 ret
= start_auth_handshake(auth
);
362 * We should reach this point only when the authentication context
363 * needs to be initialized.
366 ret
= initialize_auth_context(sipe_private
, auth
, msg
);
372 static void fill_auth(const gchar
*hdr
, struct sip_auth
*auth
)
376 /* skip authentication identifier */
377 hdr
= strchr(hdr
, ' ');
379 SIPE_DEBUG_ERROR_NOFORMAT("fill_auth: corrupted authentication header");
385 /* start of next parameter value */
386 while ((param
= strchr(hdr
, '=')) != NULL
) {
389 /* parameter value type */
392 /* string: xyz="..."(,) */
393 end
= strchr(++param
, '"');
395 SIPE_DEBUG_ERROR("fill_auth: corrupted string parameter near '%s'", hdr
);
399 /* number: xyz=12345(,) */
400 end
= strchr(param
, ',');
403 end
= param
+ strlen(param
);
408 SIPE_DEBUG_INFO("fill_auth: hdr '%s'", hdr
);
409 SIPE_DEBUG_INFO("fill_auth: param '%s'", param
);
410 SIPE_DEBUG_INFO("fill_auth: end '%s'", end
);
414 if (g_str_has_prefix(hdr
, "gssapi-data=\"")) {
415 g_free(auth
->gssapi_data
);
416 auth
->gssapi_data
= g_strndup(param
, end
- param
);
417 } else if (g_str_has_prefix(hdr
, "opaque=\"")) {
418 g_free(auth
->opaque
);
419 auth
->opaque
= g_strndup(param
, end
- param
);
420 } else if (g_str_has_prefix(hdr
, "realm=\"")) {
422 auth
->realm
= g_strndup(param
, end
- param
);
423 } else if (g_str_has_prefix(hdr
, "sts-uri=\"")) {
424 /* Only used with AUTH_TYPE_TLS_DSK */
425 g_free(auth
->sts_uri
);
426 auth
->sts_uri
= g_strndup(param
, end
- param
);
427 } else if (g_str_has_prefix(hdr
, "targetname=\"")) {
428 g_free(auth
->target
);
429 auth
->target
= g_strndup(param
, end
- param
);
430 } else if (g_str_has_prefix(hdr
, "version=")) {
431 auth
->version
= atoi(param
);
434 /* skip to next parameter */
435 while ((*end
== '"') || (*end
== ',') || (*end
== ' '))
443 static void sign_outgoing_message(struct sipe_core_private
*sipe_private
,
446 struct sip_transport
*transport
= sipe_private
->transport
;
449 if (transport
->registrar
.type
== AUTH_TYPE_UNSET
) {
453 sipe_make_signature(sipe_private
, msg
);
455 buf
= auth_header(sipe_private
, &transport
->registrar
, msg
);
457 sipmsg_add_header_now_pos(msg
, "Authorization", buf
, 5);
462 static const gchar
*sip_transport_user_agent(struct sipe_core_private
*sipe_private
)
464 struct sip_transport
*transport
= sipe_private
->transport
;
466 if (!transport
->user_agent
) {
467 const gchar
*useragent
= sipe_backend_setting(SIPE_CORE_PUBLIC
,
468 SIPE_SETTING_USER_AGENT
);
469 if (is_empty(useragent
)) {
470 /*@TODO: better approach to define _user_ OS, it's version and host architecture */
472 #if defined(__linux__) || defined(__linux) || defined(__LINUX__)
473 #define SIPE_TARGET_PLATFORM "linux"
474 #elif defined(__NetBSD__) ||defined( __OpenBSD__) || defined(__FreeBSD__)
475 #define SIPE_TARGET_PLATFORM "bsd"
476 #elif defined(__APPLE__) || defined(__MACOS__)
477 #define SIPE_TARGET_PLATFORM "macosx"
478 #elif defined(_AIX) || defined(__AIX__) || defined(__aix__)
479 #define SIPE_TARGET_PLATFORM "aix"
480 #elif defined(__solaris__) || defined(__sun)
481 #define SIPE_TARGET_PLATFORM "sun"
482 #elif defined(_WIN32)
483 #define SIPE_TARGET_PLATFORM "win"
484 #elif defined(__CYGWIN__)
485 #define SIPE_TARGET_PLATFORM "cygwin"
486 #elif defined(__hpux__)
487 #define SIPE_TARGET_PLATFORM "hpux"
488 #elif defined(__sgi__)
489 #define SIPE_TARGET_PLATFORM "irix"
491 #define SIPE_TARGET_PLATFORM "unknown"
494 #if defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)
495 #define SIPE_TARGET_ARCH "x86_64"
496 #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386)
497 #define SIPE_TARGET_ARCH "i386"
498 #elif defined(__ppc64__)
499 #define SIPE_TARGET_ARCH "ppc64"
500 #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR)
501 #define SIPE_TARGET_ARCH "ppc"
502 #elif defined(__hppa__) || defined(__hppa)
503 #define SIPE_TARGET_ARCH "hppa"
504 #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000)
505 #define SIPE_TARGET_ARCH "mips"
506 #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x)
507 #define SIPE_TARGET_ARCH "s390"
508 #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8)
509 #define SIPE_TARGET_ARCH "sparc"
510 #elif defined(__arm__)
511 #define SIPE_TARGET_ARCH "arm"
513 #define SIPE_TARGET_ARCH "other"
515 gchar
*backend
= sipe_backend_version();
516 transport
->user_agent
= g_strdup_printf("%s Sipe/" PACKAGE_VERSION
" (" SIPE_TARGET_PLATFORM
"-" SIPE_TARGET_ARCH
"; %s)",
518 transport
->server_version
? transport
->server_version
: "");
521 transport
->user_agent
= g_strdup(useragent
);
524 return(transport
->user_agent
);
527 void sip_transport_response(struct sipe_core_private
*sipe_private
,
535 GString
*outstr
= g_string_new("");
538 const gchar
*keepers
[] = { "To", "From", "Call-ID", "CSeq", "Via", "Record-Route", NULL
};
540 /* Can return NULL! */
541 contact
= get_contact(sipe_private
);
543 sipmsg_add_header(msg
, "Contact", contact
);
548 gchar
*len
= g_strdup_printf("%" G_GSIZE_FORMAT
, (gsize
) strlen(body
));
549 sipmsg_add_header(msg
, "Content-Length", len
);
552 sipmsg_add_header(msg
, "Content-Length", "0");
555 sipmsg_add_header(msg
, "User-Agent", sip_transport_user_agent(sipe_private
));
557 msg
->response
= code
;
559 sipmsg_strip_headers(msg
, keepers
);
560 sipmsg_merge_new_headers(msg
);
561 sign_outgoing_message(sipe_private
, msg
);
563 g_string_append_printf(outstr
, "SIP/2.0 %d %s\r\n", code
, text
);
566 name
= ((struct sipnameval
*) (tmp
->data
))->name
;
567 value
= ((struct sipnameval
*) (tmp
->data
))->value
;
569 g_string_append_printf(outstr
, "%s: %s\r\n", name
, value
);
570 tmp
= g_slist_next(tmp
);
572 g_string_append_printf(outstr
, "\r\n%s", body
? body
: "");
573 sipe_utils_message_debug("SIP", outstr
->str
, NULL
, TRUE
);
574 sipe_backend_transport_message(sipe_private
->transport
->connection
, outstr
->str
);
575 g_string_free(outstr
, TRUE
);
578 static void transactions_remove(struct sipe_core_private
*sipe_private
,
579 struct transaction
*trans
)
581 struct sip_transport
*transport
= sipe_private
->transport
;
582 if (transport
->transactions
) {
583 transport
->transactions
= g_slist_remove(transport
->transactions
,
585 SIPE_DEBUG_INFO("SIP transactions count:%d after removal", g_slist_length(transport
->transactions
));
587 if (trans
->msg
) sipmsg_free(trans
->msg
);
588 if (trans
->payload
) {
589 (*trans
->payload
->destroy
)(trans
->payload
->data
);
590 g_free(trans
->payload
);
593 if (trans
->timeout_key
) {
594 sipe_schedule_cancel(sipe_private
, trans
->timeout_key
);
595 g_free(trans
->timeout_key
);
601 static struct transaction
*transactions_find(struct sip_transport
*transport
,
604 GSList
*transactions
= transport
->transactions
;
605 const gchar
*call_id
= sipmsg_find_header(msg
, "Call-ID");
606 const gchar
*cseq
= sipmsg_find_header(msg
, "CSeq");
609 if (!call_id
|| !cseq
) {
610 SIPE_DEBUG_ERROR_NOFORMAT("transaction_find: no Call-ID or CSeq!");
614 key
= g_strdup_printf("<%s><%s>", call_id
, cseq
);
615 while (transactions
) {
616 struct transaction
*trans
= transactions
->data
;
617 if (!g_strcasecmp(trans
->key
, key
)) {
621 transactions
= transactions
->next
;
628 static void transaction_timeout_cb(struct sipe_core_private
*sipe_private
,
631 struct transaction
*trans
= data
;
632 (trans
->timeout_callback
)(sipe_private
, trans
->msg
, trans
);
633 transactions_remove(sipe_private
, trans
);
636 struct transaction
*sip_transport_request_timeout(struct sipe_core_private
*sipe_private
,
640 const gchar
*addheaders
,
642 struct sip_dialog
*dialog
,
643 TransCallback callback
,
645 TransCallback timeout_callback
)
647 struct sip_transport
*transport
= sipe_private
->transport
;
648 struct sipe_account_data
*sip
= SIPE_ACCOUNT_DATA_PRIVATE
;
651 gchar
*ourtag
= dialog
&& dialog
->ourtag
? g_strdup(dialog
->ourtag
) : NULL
;
652 gchar
*theirtag
= dialog
&& dialog
->theirtag
? g_strdup(dialog
->theirtag
) : NULL
;
653 gchar
*theirepid
= dialog
&& dialog
->theirepid
? g_strdup(dialog
->theirepid
) : NULL
;
654 gchar
*callid
= dialog
&& dialog
->callid
? g_strdup(dialog
->callid
) : gencallid();
655 gchar
*branch
= dialog
&& dialog
->callid
? NULL
: genbranch();
656 gchar
*route
= g_strdup("");
657 gchar
*epid
= get_epid(sipe_private
);
658 int cseq
= dialog
? ++dialog
->cseq
: 1 /* as Call-Id is new in this case */;
659 struct transaction
*trans
= NULL
;
661 if (dialog
&& dialog
->routes
)
663 GSList
*iter
= dialog
->routes
;
668 route
= g_strdup_printf("%sRoute: %s\r\n", route
, (char *)iter
->data
);
670 iter
= g_slist_next(iter
);
674 if (!ourtag
&& !dialog
) {
678 if (sipe_strequal(method
, "REGISTER")) {
679 if (sip
->regcallid
) {
681 callid
= g_strdup(sip
->regcallid
);
683 sip
->regcallid
= g_strdup(callid
);
685 cseq
= ++transport
->cseq
;
688 buf
= g_strdup_printf("%s %s SIP/2.0\r\n"
689 "Via: SIP/2.0/%s %s:%d%s%s\r\n"
690 "From: <sip:%s>%s%s;epid=%s\r\n"
691 "To: <%s>%s%s%s%s\r\n"
692 "Max-Forwards: 70\r\n"
697 "Content-Length: %" G_GSIZE_FORMAT
"\r\n\r\n%s",
699 dialog
&& dialog
->request
? dialog
->request
: url
,
700 TRANSPORT_DESCRIPTOR
,
701 sipe_backend_network_ip_address(),
702 transport
->connection
->client_port
,
703 branch
? ";branch=" : "",
704 branch
? branch
: "",
705 sipe_private
->username
,
706 ourtag
? ";tag=" : "",
707 ourtag
? ourtag
: "",
710 theirtag
? ";tag=" : "",
711 theirtag
? theirtag
: "",
712 theirepid
? ";epid=" : "",
713 theirepid
? theirepid
: "",
716 sip_transport_user_agent(sipe_private
),
719 addheaders
? addheaders
: "",
720 body
? (gsize
) strlen(body
) : 0,
724 //printf ("parsing msg buf:\n%s\n\n", buf);
725 msg
= sipmsg_parse_msg(buf
);
735 sign_outgoing_message(sipe_private
, msg
);
737 /* The authentication scheme is not ready so we can't send the message.
738 This should only happen for REGISTER messages. */
739 if (!transport
->auth_incomplete
) {
740 buf
= sipmsg_to_string(msg
);
742 /* add to ongoing transactions */
743 /* ACK isn't supposed to be answered ever. So we do not keep transaction for it. */
744 if (!sipe_strequal(method
, "ACK")) {
745 trans
= g_new0(struct transaction
, 1);
746 trans
->callback
= callback
;
748 trans
->key
= g_strdup_printf("<%s><%d %s>", callid
, cseq
, method
);
749 if (timeout_callback
) {
750 trans
->timeout_callback
= timeout_callback
;
751 trans
->timeout_key
= g_strdup_printf("<transaction timeout>%s", trans
->key
);
752 sipe_schedule_seconds(sipe_private
,
756 transaction_timeout_cb
,
759 transport
->transactions
= g_slist_append(transport
->transactions
,
761 SIPE_DEBUG_INFO("SIP transactions count:%d after addition", g_slist_length(transport
->transactions
));
764 sipe_utils_message_debug("SIP", buf
, NULL
, TRUE
);
765 sipe_backend_transport_message(transport
->connection
, buf
);
769 if (!trans
) sipmsg_free(msg
);
774 struct transaction
*sip_transport_request(struct sipe_core_private
*sipe_private
,
778 const gchar
*addheaders
,
780 struct sip_dialog
*dialog
,
781 TransCallback callback
)
783 return sip_transport_request_timeout(sipe_private
,
795 static void sip_transport_simple_request(struct sipe_core_private
*sipe_private
,
797 struct sip_dialog
*dialog
)
799 sip_transport_request(sipe_private
,
809 void sip_transport_ack(struct sipe_core_private
*sipe_private
,
810 struct sip_dialog
*dialog
)
812 sip_transport_simple_request(sipe_private
, "ACK", dialog
);
815 void sip_transport_bye(struct sipe_core_private
*sipe_private
,
816 struct sip_dialog
*dialog
)
818 sip_transport_simple_request(sipe_private
, "BYE", dialog
);
821 struct transaction
*sip_transport_info(struct sipe_core_private
*sipe_private
,
822 const gchar
*addheaders
,
824 struct sip_dialog
*dialog
,
825 TransCallback callback
)
827 return sip_transport_request(sipe_private
,
837 struct transaction
*sip_transport_invite(struct sipe_core_private
*sipe_private
,
838 const gchar
*addheaders
,
840 struct sip_dialog
*dialog
,
841 TransCallback callback
)
843 return sip_transport_request(sipe_private
,
853 struct transaction
*sip_transport_service(struct sipe_core_private
*sipe_private
,
855 const gchar
*addheaders
,
857 TransCallback callback
)
859 return sip_transport_request(sipe_private
,
869 void sip_transport_subscribe(struct sipe_core_private
*sipe_private
,
871 const gchar
*addheaders
,
873 struct sip_dialog
*dialog
,
874 TransCallback callback
)
876 sip_transport_request(sipe_private
,
886 static const gchar
*get_auth_header(struct sipe_core_private
*sipe_private
,
887 struct sip_auth
*auth
,
890 auth
->type
= AUTH_TYPE_NTLM
;
891 #if defined(HAVE_LIBKRB5) || defined(HAVE_SSPI)
892 if (SIPE_CORE_PUBLIC_FLAG_IS(KRB5
)) {
893 auth
->type
= AUTH_TYPE_KERBEROS
;
896 if (SIPE_CORE_PUBLIC_FLAG_IS(TLS_DSK
)) {
897 auth
->type
= AUTH_TYPE_TLS_DSK
;
899 auth
->protocol
= auth_type_to_protocol
[auth
->type
];
901 return(sipmsg_find_auth_header(msg
, auth
->protocol
));
904 static void do_register(struct sipe_core_private
*sipe_private
,
905 gboolean deregister
);
907 static void do_reauthenticate_cb(struct sipe_core_private
*sipe_private
,
908 SIPE_UNUSED_PARAMETER gpointer unused
)
910 struct sip_transport
*transport
= sipe_private
->transport
;
912 /* register again when security token expires */
913 /* we have to start a new authentication as the security token
914 * is almost expired by sending a not signed REGISTER message */
915 SIPE_DEBUG_INFO_NOFORMAT("do a full reauthentication");
916 sipe_auth_free(&transport
->registrar
);
917 sipe_auth_free(&transport
->proxy
);
918 sipe_schedule_cancel(sipe_private
, "<registration>");
919 transport
->reregister_set
= FALSE
;
920 transport
->register_attempt
= 0;
921 do_register(sipe_private
, FALSE
);
922 transport
->reauthenticate_set
= FALSE
;
925 static void sip_transport_default_contact(struct sipe_core_private
*sipe_private
)
927 struct sip_transport
*transport
= sipe_private
->transport
;
928 sipe_private
->contact
= g_strdup_printf("<sip:%s:%d;maddr=%s;transport=%s>;proxy=replace",
929 sipe_private
->username
,
930 transport
->connection
->client_port
,
931 sipe_backend_network_ip_address(),
932 TRANSPORT_DESCRIPTOR
);
935 static void do_register_cb(struct sipe_core_private
*sipe_private
,
936 SIPE_UNUSED_PARAMETER
void *unused
)
938 do_register(sipe_private
, FALSE
);
941 static void sip_transport_set_reregister(struct sipe_core_private
*sipe_private
,
944 sipe_schedule_seconds(sipe_private
,
952 static void sipe_server_register(struct sipe_core_private
*sipe_private
,
957 static gboolean
process_register_response(struct sipe_core_private
*sipe_private
,
959 SIPE_UNUSED_PARAMETER
struct transaction
*trans
)
961 struct sip_transport
*transport
= sipe_private
->transport
;
962 struct sipe_account_data
*sip
= SIPE_ACCOUNT_DATA_PRIVATE
;
963 const gchar
*expires_header
;
965 GSList
*hdr
= msg
->headers
;
966 struct sipnameval
*elem
;
968 expires_header
= sipmsg_find_header(msg
, "Expires");
969 expires
= expires_header
!= NULL
? strtol(expires_header
, NULL
, 10) : 0;
970 SIPE_DEBUG_INFO("process_register_response: got response to REGISTER; expires = %d", expires
);
972 switch (msg
->response
) {
975 const gchar
*contact_hdr
;
976 const gchar
*auth_hdr
;
980 const gchar
*server_hdr
= sipmsg_find_header(msg
, "Server");
982 if (!transport
->reregister_set
) {
983 sip_transport_set_reregister(sipe_private
,
985 transport
->reregister_set
= TRUE
;
988 if (server_hdr
&& !transport
->server_version
) {
989 transport
->server_version
= g_strdup(server_hdr
);
990 g_free(transport
->user_agent
);
991 transport
->user_agent
= NULL
;
994 auth_hdr
= get_auth_header(sipe_private
, &transport
->registrar
, msg
);
996 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr
);
997 fill_auth(auth_hdr
, &transport
->registrar
);
1000 if (!transport
->reauthenticate_set
) {
1001 gchar
*action_name
= g_strdup_printf("<%s>", "+reauthentication");
1002 guint reauth_timeout
;
1004 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1006 if (transport
->registrar
.type
== AUTH_TYPE_KERBEROS
&& transport
->registrar
.expires
> 0) {
1007 /* assuming normal Kerberos ticket expiration of about 8-10 hours */
1008 reauth_timeout
= transport
->registrar
.expires
- 300;
1010 /* NTLM: we have to reauthenticate as our security token expires
1011 after eight hours (be five minutes early) */
1012 reauth_timeout
= (8 * 3600) - 300;
1014 sipe_schedule_seconds(sipe_private
,
1018 do_reauthenticate_cb
,
1020 g_free(action_name
);
1021 transport
->reauthenticate_set
= TRUE
;
1024 sipe_backend_connection_completed(SIPE_CORE_PUBLIC
);
1026 uuid
= get_uuid(sipe_private
);
1028 // There can be multiple Contact headers (one per location where the user is logged in) so
1029 // make sure to only get the one for this uuid
1030 for (i
= 0; (contact_hdr
= sipmsg_find_header_instance (msg
, "Contact", i
)); i
++) {
1031 gchar
* valid_contact
= sipmsg_find_part_of_header (contact_hdr
, uuid
, NULL
, NULL
);
1032 if (valid_contact
) {
1033 gruu
= sipmsg_find_part_of_header(contact_hdr
, "gruu=\"", "\"", NULL
);
1034 //SIPE_DEBUG_INFO("process_register_response: got gruu %s from contact hdr w/ right uuid: %s", gruu, contact_hdr);
1035 g_free(valid_contact
);
1038 //SIPE_DEBUG_INFO("process_register_response: ignoring contact hdr b/c not right uuid: %s", contact_hdr);
1043 g_free(sipe_private
->contact
);
1045 sipe_private
->contact
= g_strdup_printf("<%s>", gruu
);
1048 //SIPE_DEBUG_INFO_NOFORMAT("process_register_response: didn't find gruu in a Contact hdr");
1049 sip_transport_default_contact(sipe_private
);
1051 SIPE_CORE_PRIVATE_FLAG_UNSET(OCS2007
);
1052 SIPE_CORE_PRIVATE_FLAG_UNSET(REMOTE_USER
);
1053 sip
->batched_support
= FALSE
;
1058 if (sipe_strcase_equal(elem
->name
, "Supported")) {
1059 if (sipe_strcase_equal(elem
->value
, "msrtc-event-categories")) {
1060 /* We interpret this as OCS2007+ indicator */
1061 SIPE_CORE_PRIVATE_FLAG_SET(OCS2007
);
1062 SIPE_DEBUG_INFO("Supported: %s (indicates OCS2007+)", elem
->value
);
1064 if (sipe_strcase_equal(elem
->value
, "adhoclist")) {
1065 sip
->batched_support
= TRUE
;
1066 SIPE_DEBUG_INFO("Supported: %s", elem
->value
);
1069 if (sipe_strcase_equal(elem
->name
, "Allow-Events")){
1070 gchar
**caps
= g_strsplit(elem
->value
,",",0);
1073 sip
->allow_events
= g_slist_append(sip
->allow_events
, g_strdup(caps
[i
]));
1074 SIPE_DEBUG_INFO("Allow-Events: %s", caps
[i
]);
1079 if (sipe_strcase_equal(elem
->name
, "ms-user-logon-data")) {
1080 if (sipe_strcase_equal(elem
->value
, "RemoteUser")) {
1081 SIPE_CORE_PRIVATE_FLAG_SET(REMOTE_USER
);
1082 SIPE_DEBUG_INFO_NOFORMAT("ms-user-logon-data: RemoteUser (connected "
1083 "via Edge Server)");
1086 hdr
= g_slist_next(hdr
);
1089 /* rejoin open chats to be able to use them by continue to send messages */
1090 sipe_backend_chat_rejoin_all(SIPE_CORE_PUBLIC
);
1093 if (!transport
->subscribed
) { //do it just once, not every re-register
1095 if (g_slist_find_custom(sip
->allow_events
, "vnd-microsoft-roaming-contacts",
1096 (GCompareFunc
)g_ascii_strcasecmp
)) {
1097 sipe_subscribe_roaming_contacts(sipe_private
);
1100 /* For 2007+ it does not make sence to subscribe to:
1101 * vnd-microsoft-roaming-ACL
1102 * vnd-microsoft-provisioning (not v2)
1104 * These are for backward compatibility.
1106 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007
))
1108 if (g_slist_find_custom(sip
->allow_events
, "vnd-microsoft-roaming-self",
1109 (GCompareFunc
)g_ascii_strcasecmp
)) {
1110 sipe_subscribe_roaming_self(sipe_private
);
1112 if (g_slist_find_custom(sip
->allow_events
, "vnd-microsoft-provisioning-v2",
1113 (GCompareFunc
)g_ascii_strcasecmp
)) {
1114 sipe_subscribe_roaming_provisioning_v2(sipe_private
);
1117 /* For 2005- servers */
1120 //sipe_options_request(sip, sipe_private->public.sip_domain);
1122 if (g_slist_find_custom(sip
->allow_events
, "vnd-microsoft-roaming-ACL",
1123 (GCompareFunc
)g_ascii_strcasecmp
)) {
1124 sipe_subscribe_roaming_acl(sipe_private
);
1126 if (g_slist_find_custom(sip
->allow_events
, "vnd-microsoft-provisioning",
1127 (GCompareFunc
)g_ascii_strcasecmp
)) {
1128 sipe_subscribe_roaming_provisioning(sipe_private
);
1130 if (g_slist_find_custom(sip
->allow_events
, "presence.wpending",
1131 (GCompareFunc
)g_ascii_strcasecmp
)) {
1132 sipe_subscribe_presence_wpending(sipe_private
,
1136 /* For 2007+ we publish our initial statuses and calendar data only after
1137 * received our existing publications in sipe_process_roaming_self()
1138 * Only in this case we know versions of current publications made
1141 /* For 2005- we publish our initial statuses only after
1142 * received our existing UserInfo data in response to
1143 * self subscription.
1144 * Only in this case we won't override existing UserInfo data
1145 * set earlier or by other client on our behalf.
1149 transport
->subscribed
= TRUE
;
1152 timeout
= sipmsg_find_part_of_header(sipmsg_find_header(msg
, "ms-keep-alive"),
1153 "timeout=", ";", NULL
);
1154 if (timeout
!= NULL
) {
1155 sscanf(timeout
, "%u", &sipe_private
->public.keepalive_timeout
);
1156 SIPE_DEBUG_INFO("process_register_response: server determined keep alive timeout is %u seconds",
1157 sipe_private
->public.keepalive_timeout
);
1161 SIPE_DEBUG_INFO("process_register_response: got 200, removing CSeq: %d", transport
->cseq
);
1166 gchar
*redirect
= parse_from(sipmsg_find_header(msg
, "Contact"));
1168 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake completed successfully");
1170 if (redirect
&& (g_strncasecmp("sip:", redirect
, 4) == 0)) {
1171 gchar
**parts
= g_strsplit(redirect
+ 4, ";", 0);
1175 guint transport
= SIPE_TRANSPORT_TLS
;
1178 tmp
= g_strsplit(parts
[0], ":", 0);
1179 hostname
= g_strdup(tmp
[0]);
1180 if (tmp
[1]) port
= strtoul(tmp
[1], NULL
, 10);
1184 tmp
= g_strsplit(parts
[i
], "=", 0);
1186 if (g_strcasecmp("transport", tmp
[0]) == 0) {
1187 if (g_strcasecmp("tcp", tmp
[1]) == 0) {
1188 transport
= SIPE_TRANSPORT_TCP
;
1197 /* Close old connection */
1198 sipe_core_connection_cleanup(sipe_private
);
1200 /* Create new connection */
1201 sipe_server_register(sipe_private
, transport
, hostname
, port
);
1202 SIPE_DEBUG_INFO("process_register_response: redirected to host %s port %d transport %d",
1203 hostname
, port
, transport
);
1210 const char *auth_hdr
;
1212 SIPE_DEBUG_INFO("process_register_response: REGISTER retries %d", transport
->registrar
.retries
);
1213 if (sip_sec_context_is_ready(transport
->registrar
.gssapi_context
)) {
1214 SIPE_DEBUG_INFO_NOFORMAT("process_register_response: authentication handshake failed - giving up.");
1215 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1216 SIPE_CONNECTION_ERROR_AUTHENTICATION_FAILED
,
1217 _("Authentication failed"));
1221 if (transport
->reauthenticate_set
) {
1222 SIPE_DEBUG_ERROR_NOFORMAT("process_register_response: RE-REGISTER rejected, triggering re-authentication");
1223 do_reauthenticate_cb(sipe_private
, NULL
);
1227 auth_hdr
= get_auth_header(sipe_private
, &transport
->registrar
, msg
);
1229 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1230 SIPE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE
,
1231 _("Incompatible authentication scheme chosen"));
1234 SIPE_DEBUG_INFO("process_register_response: Auth header: %s", auth_hdr
);
1235 fill_auth(auth_hdr
, &transport
->registrar
);
1236 transport
->reregister_set
= FALSE
;
1237 transport
->register_attempt
= 0;
1238 do_register(sipe_private
,
1239 sipe_backend_connection_is_disconnecting(SIPE_CORE_PUBLIC
));
1246 sipmsg_parse_warning(msg
, &reason
);
1247 reason
= reason
? reason
: sipmsg_get_ms_diagnostics_public_reason(msg
);
1248 warning
= g_strdup_printf(_("You have been rejected by the server: %s"),
1249 reason
? reason
: _("no reason given"));
1252 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1253 SIPE_CONNECTION_ERROR_INVALID_SETTINGS
,
1261 const gchar
*diagnostics
= sipmsg_find_header(msg
, "ms-diagnostics");
1262 gchar
*reason
= sipmsg_get_ms_diagnostics_reason(msg
);
1264 warning
= g_strdup_printf(_("Not found: %s. Please contact your Administrator"),
1265 diagnostics
? (reason
? reason
: _("no reason given")) :
1266 _("SIP is either not enabled for the destination URI or it does not exist"));
1269 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1270 SIPE_CONNECTION_ERROR_INVALID_USERNAME
,
1276 case 504: /* Server time-out */
1277 /* first attempt + 5 retries */
1278 if (transport
->register_attempt
< 6) {
1279 SIPE_DEBUG_INFO("process_register_response: RE-REGISTER timeout on attempt %d, retrying later",
1280 transport
->register_attempt
);
1281 sip_transport_set_reregister(sipe_private
, 60);
1287 gchar
*reason
= sipmsg_get_ms_diagnostics_reason(msg
);
1289 warning
= g_strdup_printf(_("Service unavailable: %s"), reason
? reason
: _("no reason given"));
1292 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1293 SIPE_CONNECTION_ERROR_NETWORK
,
1303 static gboolean
register_response_timeout(struct sipe_core_private
*sipe_private
,
1304 SIPE_UNUSED_PARAMETER
struct sipmsg
*msg
,
1305 SIPE_UNUSED_PARAMETER
struct transaction
*trans
)
1307 struct sip_transport
*transport
= sipe_private
->transport
;
1308 if (transport
->register_attempt
< 6) {
1309 SIPE_DEBUG_INFO("register_response_timeout: no answer to attempt %d, retrying",
1310 transport
->register_attempt
);
1311 do_register(sipe_private
, FALSE
);
1313 gchar
*warning
= g_strdup_printf(_("Service unavailable: %s"), _("no reason given"));
1314 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1315 SIPE_CONNECTION_ERROR_NETWORK
,
1322 static void do_register(struct sipe_core_private
*sipe_private
,
1323 gboolean deregister
)
1325 struct sip_transport
*transport
= sipe_private
->transport
;
1331 if (!sipe_private
->public.sip_domain
) return;
1334 if (transport
->reregister_set
) {
1335 transport
->reregister_set
= FALSE
;
1336 transport
->register_attempt
= 1;
1338 transport
->register_attempt
++;
1342 transport
->auth_incomplete
= FALSE
;
1344 uuid
= get_uuid(sipe_private
);
1345 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"
1346 "Supported: gruu-10, adhoclist, msrtc-event-categories, com.microsoft.msrtc.presence\r\n"
1347 "Event: registration\r\n"
1348 "Allow-Events: presence\r\n"
1349 "ms-keep-alive: UAC;hop-hop=yes\r\n"
1351 sipe_backend_network_ip_address(),
1352 transport
->connection
->client_port
,
1353 TRANSPORT_DESCRIPTOR
,
1355 deregister
? "Expires: 0\r\n" : "");
1358 uri
= sip_uri_from_name(sipe_private
->public.sip_domain
);
1359 to
= sip_uri_self(sipe_private
);
1360 sip_transport_request_timeout(sipe_private
,
1367 process_register_response
,
1369 deregister
? NULL
: register_response_timeout
);
1375 /* Make sure that all messages are pushed to the server
1376 before the connection gets shut down */
1377 SIPE_DEBUG_INFO_NOFORMAT("De-register from server. Flushing outstanding messages.");
1378 sipe_backend_transport_flush(transport
->connection
);
1382 void sip_transport_deregister(struct sipe_core_private
*sipe_private
)
1384 do_register(sipe_private
, TRUE
);
1387 void sip_transport_disconnect(struct sipe_core_private
*sipe_private
)
1389 struct sip_transport
*transport
= sipe_private
->transport
;
1391 /* transport can be NULL during connection setup */
1393 sipe_backend_transport_disconnect(transport
->connection
);
1395 sipe_auth_free(&transport
->registrar
);
1396 sipe_auth_free(&transport
->proxy
);
1398 g_free(transport
->server_name
);
1399 g_free(transport
->server_version
);
1400 g_free(transport
->user_agent
);
1402 while (transport
->transactions
)
1403 transactions_remove(sipe_private
,
1404 transport
->transactions
->data
);
1409 sipe_private
->transport
= NULL
;
1410 sipe_private
->service_data
= NULL
;
1412 if (sipe_private
->dns_query
)
1413 sipe_backend_dns_query_cancel(sipe_private
->dns_query
);
1417 void sip_transport_authentication_completed(struct sipe_core_private
*sipe_private
)
1419 do_reauthenticate_cb(sipe_private
, NULL
);
1422 guint
sip_transport_port(struct sipe_core_private
*sipe_private
)
1424 return sipe_private
->transport
->server_port
;
1427 static void process_input_message(struct sipe_core_private
*sipe_private
,
1430 struct sip_transport
*transport
= sipe_private
->transport
;
1431 gboolean notfound
= FALSE
;
1432 const char *method
= msg
->method
? msg
->method
: "NOT FOUND";
1434 SIPE_DEBUG_INFO("process_input_message: msg->response(%d),msg->method(%s)",
1435 msg
->response
, method
);
1437 if (msg
->response
== 0) { /* request */
1438 if (sipe_strequal(method
, "MESSAGE")) {
1439 process_incoming_message(sipe_private
, msg
);
1440 } else if (sipe_strequal(method
, "NOTIFY")) {
1441 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_notify");
1442 process_incoming_notify(sipe_private
, msg
, TRUE
, FALSE
);
1443 } else if (sipe_strequal(method
, "BENOTIFY")) {
1444 SIPE_DEBUG_INFO_NOFORMAT("send->process_incoming_benotify");
1445 process_incoming_notify(sipe_private
, msg
, TRUE
, TRUE
);
1446 } else if (sipe_strequal(method
, "INVITE")) {
1447 process_incoming_invite(sipe_private
, msg
);
1448 } else if (sipe_strequal(method
, "REFER")) {
1449 process_incoming_refer(sipe_private
, msg
);
1450 } else if (sipe_strequal(method
, "OPTIONS")) {
1451 process_incoming_options(sipe_private
, msg
);
1452 } else if (sipe_strequal(method
, "INFO")) {
1453 process_incoming_info(sipe_private
, msg
);
1454 } else if (sipe_strequal(method
, "ACK")) {
1455 /* ACK's don't need any response */
1456 } else if (sipe_strequal(method
, "PRACK")) {
1457 sip_transport_response(sipe_private
, msg
, 200, "OK", NULL
);
1458 } else if (sipe_strequal(method
, "SUBSCRIBE")) {
1459 /* LCS 2005 sends us these - just respond 200 OK */
1460 sip_transport_response(sipe_private
, msg
, 200, "OK", NULL
);
1461 } else if (sipe_strequal(method
, "CANCEL")) {
1462 process_incoming_cancel(sipe_private
, msg
);
1463 } else if (sipe_strequal(method
, "BYE")) {
1464 process_incoming_bye(sipe_private
, msg
);
1466 sip_transport_response(sipe_private
, msg
, 501, "Not implemented", NULL
);
1470 } else { /* response */
1471 struct transaction
*trans
= transactions_find(transport
, msg
);
1473 if (msg
->response
< 200) {
1474 /* ignore provisional response */
1475 SIPE_DEBUG_INFO("process_input_message: got provisional (%d) response, ignoring", msg
->response
);
1477 /* Transaction not yet completed */
1480 } else if (msg
->response
== 401) { /* Unauthorized */
1482 if (sipe_strequal(trans
->msg
->method
, "REGISTER")) {
1483 /* Expected response during authentication handshake */
1484 transport
->registrar
.retries
++;
1485 SIPE_DEBUG_INFO("process_input_message: RE-REGISTER CSeq: %d", transport
->cseq
);
1489 /* Are we registered? */
1490 if (transport
->reregister_set
) {
1491 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Retrying with new authentication.");
1492 sign_outgoing_message(sipe_private
,
1496 * We don't have a valid authentication at the moment.
1497 * Resend message unchanged. It will be rejected again
1498 * and hopefully by then we have a valid authentication.
1500 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: 401 response to non-REGISTER message. Bouncing...");
1503 /* Resend request */
1504 resend
= sipmsg_to_string(trans
->msg
);
1505 sipe_utils_message_debug("SIP", resend
, NULL
, TRUE
);
1506 sipe_backend_transport_message(sipe_private
->transport
->connection
, resend
);
1509 /* Transaction not yet completed */
1513 } else if (msg
->response
== 407) { /* Proxy Authentication Required */
1515 if (transport
->proxy
.retries
> 30) {
1516 SIPE_DEBUG_ERROR_NOFORMAT("process_input_message: too many proxy authentication retries. Giving up.");
1518 gchar
*resend
, *auth
;
1519 const gchar
*auth_hdr
;
1521 transport
->proxy
.retries
++;
1523 /* do proxy authentication */
1524 auth_hdr
= sipmsg_find_header(msg
, "Proxy-Authenticate");
1527 transport
->proxy
.type
= AUTH_TYPE_UNSET
;
1528 for (i
= 0; i
< AUTH_PROTOCOLS
; i
++) {
1529 const gchar
*protocol
= auth_type_to_protocol
[i
];
1531 !g_strncasecmp(auth_hdr
, protocol
, strlen(protocol
))) {
1532 SIPE_DEBUG_INFO("proxy auth: type %s", protocol
);
1533 transport
->proxy
.type
= i
;
1534 transport
->proxy
.protocol
= protocol
;
1538 if (transport
->proxy
.type
== AUTH_TYPE_UNSET
)
1539 SIPE_DEBUG_ERROR("Unknown proxy authentication: %s", auth_hdr
);
1540 fill_auth(auth_hdr
, &transport
->proxy
);
1542 auth
= auth_header(sipe_private
, &transport
->proxy
, trans
->msg
);
1544 sipmsg_remove_header_now(trans
->msg
, "Proxy-Authorization");
1545 sipmsg_add_header_now_pos(trans
->msg
, "Proxy-Authorization", auth
, 5);
1549 /* resend request */
1550 resend
= sipmsg_to_string(trans
->msg
);
1551 sipe_utils_message_debug("SIP", resend
, NULL
, TRUE
);
1552 sipe_backend_transport_message(sipe_private
->transport
->connection
, resend
);
1555 /* Transaction not yet completed */
1560 transport
->registrar
.retries
= 0;
1561 transport
->proxy
.retries
= 0;
1564 /* Is transaction completed? */
1566 if (trans
->callback
) {
1567 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: we have a transaction callback");
1568 /* call the callback to process response */
1569 (trans
->callback
)(sipe_private
, msg
, trans
);
1572 SIPE_DEBUG_INFO("process_input_message: removing CSeq %d", transport
->cseq
);
1573 transactions_remove(sipe_private
, trans
);
1576 SIPE_DEBUG_INFO_NOFORMAT("process_input_message: received response to unknown transaction");
1582 SIPE_DEBUG_INFO("received a unknown sip message with method %s and response %d", method
, msg
->response
);
1586 static void sip_transport_input(struct sipe_transport_connection
*conn
)
1588 struct sipe_core_private
*sipe_private
= conn
->user_data
;
1589 struct sip_transport
*transport
= sipe_private
->transport
;
1590 gchar
*cur
= conn
->buffer
;
1592 /* according to the RFC remove CRLF at the beginning */
1593 while (*cur
== '\r' || *cur
== '\n') {
1596 if (cur
!= conn
->buffer
)
1597 sipe_utils_shrink_buffer(conn
, cur
);
1599 /* Received a full Header? */
1600 transport
->processing_input
= TRUE
;
1601 while (transport
->processing_input
&&
1602 ((cur
= strstr(conn
->buffer
, "\r\n\r\n")) != NULL
)) {
1608 msg
= sipmsg_parse_header(conn
->buffer
);
1611 remainder
= conn
->buffer_used
- (cur
- conn
->buffer
);
1612 if (msg
&& remainder
>= (guint
) msg
->bodylen
) {
1613 char *dummy
= g_malloc(msg
->bodylen
+ 1);
1614 memcpy(dummy
, cur
, msg
->bodylen
);
1615 dummy
[msg
->bodylen
] = '\0';
1617 cur
+= msg
->bodylen
;
1618 sipe_utils_message_debug("SIP",
1622 sipe_utils_shrink_buffer(conn
, cur
);
1625 SIPE_DEBUG_INFO("sipe_transport_input: body too short (%d < %d, strlen %d) - ignoring message", remainder
, msg
->bodylen
, (int)strlen(conn
->buffer
));
1629 /* restore header for next try */
1634 // Verify the signature before processing it
1635 if (sip_sec_context_is_ready(transport
->registrar
.gssapi_context
)) {
1636 struct sipmsg_breakdown msgbd
;
1637 gchar
*signature_input_str
;
1640 sipmsg_breakdown_parse(&msgbd
, transport
->registrar
.realm
, transport
->registrar
.target
,
1641 transport
->registrar
.protocol
);
1642 signature_input_str
= sipmsg_breakdown_get_string(transport
->registrar
.version
, &msgbd
);
1644 rspauth
= sipmsg_find_part_of_header(sipmsg_find_header(msg
, "Authentication-Info"), "rspauth=\"", "\"", NULL
);
1646 if (rspauth
!= NULL
) {
1647 if (!sip_sec_verify_signature(transport
->registrar
.gssapi_context
, signature_input_str
, rspauth
)) {
1648 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message validated");
1649 process_input_message(sipe_private
, msg
);
1651 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: signature of incoming message is invalid.");
1652 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1653 SIPE_CONNECTION_ERROR_NETWORK
,
1654 _("Invalid message signature received"));
1656 } else if ((msg
->response
== 401) ||
1657 sipe_strequal(msg
->method
, "REGISTER")) {
1658 /* a) Retry non-REGISTER requests with updated authentication */
1659 /* b) We must always process REGISTER responses */
1660 process_input_message(sipe_private
, msg
);
1662 /* OCS sends provisional messages that are *not* signed */
1663 if (msg
->response
>= 200) {
1664 /* We are not calling process_input_message(),
1665 so we need to drop the transaction here. */
1666 struct transaction
*trans
= transactions_find(transport
, msg
);
1667 if (trans
) transactions_remove(sipe_private
, trans
);
1669 SIPE_DEBUG_INFO_NOFORMAT("sip_transport_input: message without authentication data - ignoring");
1671 g_free(signature_input_str
);
1674 sipmsg_breakdown_free(&msgbd
);
1676 process_input_message(sipe_private
, msg
);
1681 /* Redirect: old content of "transport" is no longer valid */
1682 transport
= sipe_private
->transport
;
1686 static void sip_transport_connected(struct sipe_transport_connection
*conn
)
1688 struct sipe_core_private
*sipe_private
= conn
->user_data
;
1689 sipe_private
->service_data
= NULL
;
1690 do_register(sipe_private
, FALSE
);
1693 static void resolve_next_service(struct sipe_core_private
*sipe_private
,
1694 const struct sip_service_data
*start
);
1695 static void sip_transport_error(struct sipe_transport_connection
*conn
,
1698 struct sipe_core_private
*sipe_private
= conn
->user_data
;
1700 /* This failed attempt was based on a DNS SRV record */
1701 if (sipe_private
->service_data
) {
1702 resolve_next_service(sipe_private
, NULL
);
1704 sipe_backend_connection_error(SIPE_CORE_PUBLIC
,
1705 SIPE_CONNECTION_ERROR_NETWORK
,
1710 /* server_name must be g_alloc()'ed */
1711 static void sipe_server_register(struct sipe_core_private
*sipe_private
,
1716 sipe_connect_setup setup
= {
1719 (server_port
!= 0) ? server_port
:
1720 (type
== SIPE_TRANSPORT_TLS
) ? 5061 : 5060,
1722 sip_transport_connected
,
1723 sip_transport_input
,
1726 struct sip_transport
*transport
= g_new0(struct sip_transport
, 1);
1728 transport
->server_name
= server_name
;
1729 transport
->server_port
= setup
.server_port
;
1730 transport
->connection
= sipe_backend_transport_connect(SIPE_CORE_PUBLIC
,
1732 sipe_private
->transport
= transport
;
1735 struct sip_service_data
{
1736 const char *protocol
;
1737 const char *transport
;
1741 /* Service list for autodection */
1742 static const struct sip_service_data service_autodetect
[] = {
1743 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS
}, /* for internal TLS connections */
1744 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP
}, /* for internal TCP connections */
1745 { "sip", "tls", SIPE_TRANSPORT_TLS
}, /* for external TLS connections */
1746 { "sip", "tcp", SIPE_TRANSPORT_TCP
}, /*.for external TCP connections */
1750 /* Service list for SSL/TLS */
1751 static const struct sip_service_data service_tls
[] = {
1752 { "sipinternaltls", "tcp", SIPE_TRANSPORT_TLS
}, /* for internal TLS connections */
1753 { "sip", "tls", SIPE_TRANSPORT_TLS
}, /* for external TLS connections */
1757 /* Service list for TCP */
1758 static const struct sip_service_data service_tcp
[] = {
1759 { "sipinternal", "tcp", SIPE_TRANSPORT_TCP
}, /* for internal TCP connections */
1760 { "sip", "tcp", SIPE_TRANSPORT_TCP
}, /*.for external TCP connections */
1764 static const struct sip_service_data
*services
[] = {
1765 service_autodetect
, /* SIPE_TRANSPORT_AUTO */
1766 service_tls
, /* SIPE_TRANSPORT_TLS */
1767 service_tcp
/* SIPE_TRANSPORT_TCP */
1770 static void sipe_core_dns_resolved(struct sipe_core_public
*sipe_public
,
1771 const gchar
*hostname
, guint port
)
1773 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
1775 sipe_private
->dns_query
= NULL
;
1778 SIPE_DEBUG_INFO("sipe_core_dns_resolved - SRV hostname: %s port: %d",
1780 sipe_server_register(sipe_private
,
1781 sipe_private
->service_data
->type
,
1782 g_strdup(hostname
), port
);
1784 resolve_next_service(SIPE_CORE_PRIVATE
, NULL
);
1788 static void resolve_next_service(struct sipe_core_private
*sipe_private
,
1789 const struct sip_service_data
*start
)
1792 sipe_private
->service_data
= start
;
1794 sipe_private
->service_data
++;
1795 if (sipe_private
->service_data
->protocol
== NULL
) {
1796 guint type
= sipe_private
->transport_type
;
1798 /* We tried all services */
1799 sipe_private
->service_data
= NULL
;
1801 /* Try connecting to the SIP hostname directly */
1802 SIPE_DEBUG_INFO_NOFORMAT("no SRV records found; using SIP domain as fallback");
1803 if (type
== SIPE_TRANSPORT_AUTO
)
1804 type
= SIPE_TRANSPORT_TLS
;
1806 sipe_server_register(sipe_private
, type
,
1807 g_strdup(sipe_private
->public.sip_domain
),
1813 /* Try to resolve next service */
1814 sipe_private
->dns_query
= sipe_backend_dns_query_srv(
1815 sipe_private
->service_data
->protocol
,
1816 sipe_private
->service_data
->transport
,
1817 sipe_private
->public.sip_domain
,
1818 (sipe_dns_resolved_cb
) sipe_core_dns_resolved
,
1822 void sipe_core_transport_sip_connect(struct sipe_core_public
*sipe_public
,
1824 const gchar
*server
,
1827 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
1830 /* Use user specified server[:port] */
1831 int port_number
= 0;
1834 port_number
= atoi(port
);
1836 SIPE_DEBUG_INFO("sipe_core_connect: user specified SIP server %s:%d",
1837 server
, port_number
);
1839 sipe_server_register(sipe_private
, transport
,
1840 g_strdup(server
), port_number
);
1842 /* Server auto-discovery */
1844 /* Remember user specified transport type */
1845 sipe_private
->transport_type
= transport
;
1846 resolve_next_service(sipe_private
, services
[transport
]);
1850 void sipe_core_transport_sip_keepalive(struct sipe_core_public
*sipe_public
)
1852 SIPE_DEBUG_INFO("sending keep alive %d",
1853 sipe_public
->keepalive_timeout
);
1854 sipe_utils_message_debug("SIP", "", NULL
, TRUE
);
1855 sipe_backend_transport_message(SIPE_CORE_PRIVATE
->transport
->connection
,
1859 int sip_transaction_cseq(struct transaction
*trans
)
1863 g_return_val_if_fail(trans
&& trans
->key
, 0);
1865 sscanf(trans
->key
, "<%*[a-zA-Z0-9]><%d INVITE>", &cseq
);