2 * @file sip-sec-tls-dsk.c
6 * Copyright (C) 2011-2015 SIPE Project <http://sipe.sourceforge.net/>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Specification references:
26 * - [MS-SIPAE]: http://msdn.microsoft.com/en-us/library/cc431510.aspx
27 * - [MS-OCAUTHWS]: http://msdn.microsoft.com/en-us/library/ff595592.aspx
28 * - MS Tech-Ed Europe 2010 "UNC310: Microsoft Lync 2010 Technology Explained"
29 * http://ecn.channel9.msdn.com/o9/te/Europe/2010/pptx/unc310.pptx
40 #include "sipe-common.h"
42 #include "sip-sec-mech.h"
43 #include "sip-sec-tls-dsk.h"
44 #include "sipe-backend.h"
45 #include "sipe-digest.h"
48 /* Security context for TLS-DSK */
49 typedef struct _context_tls_dsk
{
50 struct sip_sec_context common
;
51 struct sipe_tls_state
*state
;
52 enum sipe_tls_digest_algorithm algorithm
;
58 /* sip-sec-mech.h API implementation for TLS-DSK */
61 sip_sec_acquire_cred__tls_dsk(SipSecContext context
,
62 SIPE_UNUSED_PARAMETER
const gchar
*username
,
63 const gchar
*password
)
65 context_tls_dsk ctx
= (context_tls_dsk
) context
;
67 return((ctx
->state
= sipe_tls_start((gpointer
) password
)) != NULL
);
71 sip_sec_init_sec_context__tls_dsk(SipSecContext context
,
73 SipSecBuffer
*out_buff
,
74 SIPE_UNUSED_PARAMETER
const gchar
*service_name
)
76 context_tls_dsk ctx
= (context_tls_dsk
) context
;
77 struct sipe_tls_state
*state
= ctx
->state
;
79 state
->in_buffer
= in_buff
.value
;
80 state
->in_length
= in_buff
.length
;
82 if (sipe_tls_next(state
)) {
83 if ((state
->algorithm
!= SIPE_TLS_DIGEST_ALGORITHM_NONE
) &&
84 state
->client_key
&& state
->server_key
) {
85 /* Authentication is completed */
86 context
->flags
|= SIP_SEC_FLAG_COMMON_READY
;
89 ctx
->algorithm
= state
->algorithm
;
90 ctx
->key_length
= state
->key_length
;
91 ctx
->client_key
= g_memdup(state
->client_key
,
93 ctx
->server_key
= g_memdup(state
->server_key
,
96 /* [MS-SIPAE] Section 3.2.2 Timers
98 * ... For an SA established using the TLS-DSK
99 * authentication protocol, the client MUST
100 * retrieve the expiration time of its certificate.
101 * The expiration timer value is the lesser of the
102 * interval to the certificate expiration and eight
105 ctx
->common
.expires
= sipe_tls_expires(state
);
106 if (ctx
->common
.expires
> (8 * 60 * 60))
107 ctx
->common
.expires
= 8 * 60 * 60;
109 SIPE_DEBUG_INFO("sip_sec_init_sec_context__tls_dsk: handshake completed, algorithm %d, key length %" G_GSIZE_FORMAT
", expires %d",
110 ctx
->algorithm
, ctx
->key_length
, ctx
->common
.expires
);
112 sipe_tls_free(state
);
115 out_buff
->value
= state
->out_buffer
;
116 out_buff
->length
= state
->out_length
;
117 /* we take ownership of the buffer */
118 state
->out_buffer
= NULL
;
121 sipe_tls_free(state
);
125 return(((context
->flags
& SIP_SEC_FLAG_COMMON_READY
) ||
130 sip_sec_make_signature__tls_dsk(SipSecContext context
,
131 const gchar
*message
,
132 SipSecBuffer
*signature
)
134 context_tls_dsk ctx
= (context_tls_dsk
) context
;
135 gboolean result
= FALSE
;
137 switch (ctx
->algorithm
) {
138 case SIPE_TLS_DIGEST_ALGORITHM_MD5
:
139 signature
->length
= SIPE_DIGEST_HMAC_MD5_LENGTH
;
140 signature
->value
= g_malloc0(signature
->length
);
141 sipe_digest_hmac_md5(ctx
->client_key
, ctx
->key_length
,
142 (guchar
*) message
, strlen(message
),
147 case SIPE_TLS_DIGEST_ALGORITHM_SHA1
:
148 signature
->length
= SIPE_DIGEST_HMAC_SHA1_LENGTH
;
149 signature
->value
= g_malloc0(signature
->length
);
150 sipe_digest_hmac_sha1(ctx
->client_key
, ctx
->key_length
,
151 (guchar
*) message
, strlen(message
),
157 /* this should not happen */
165 sip_sec_verify_signature__tls_dsk(SipSecContext context
,
166 const gchar
*message
,
167 SipSecBuffer signature
)
169 context_tls_dsk ctx
= (context_tls_dsk
) context
;
170 SipSecBuffer mac
= { 0, NULL
};
171 gboolean result
= FALSE
;
173 switch (ctx
->algorithm
) {
174 case SIPE_TLS_DIGEST_ALGORITHM_MD5
:
175 mac
.length
= SIPE_DIGEST_HMAC_MD5_LENGTH
;
176 mac
.value
= g_malloc0(mac
.length
);
177 sipe_digest_hmac_md5(ctx
->server_key
, ctx
->key_length
,
178 (guchar
*) message
, strlen(message
),
182 case SIPE_TLS_DIGEST_ALGORITHM_SHA1
:
183 mac
.length
= SIPE_DIGEST_HMAC_SHA1_LENGTH
;
184 mac
.value
= g_malloc0(mac
.length
);
185 sipe_digest_hmac_sha1(ctx
->server_key
, ctx
->key_length
,
186 (guchar
*) message
, strlen(message
),
191 /* this should not happen */
196 result
= memcmp(signature
.value
, mac
.value
, mac
.length
) == 0;
204 sip_sec_destroy_sec_context__tls_dsk(SipSecContext context
)
206 context_tls_dsk ctx
= (context_tls_dsk
) context
;
208 sipe_tls_free(ctx
->state
);
209 g_free(ctx
->client_key
);
210 g_free(ctx
->server_key
);
215 sip_sec_context_name__tls_dsk(SIPE_UNUSED_PARAMETER SipSecContext context
)
221 sip_sec_create_context__tls_dsk(SIPE_UNUSED_PARAMETER guint type
)
223 context_tls_dsk context
= g_malloc0(sizeof(struct _context_tls_dsk
));
224 if (!context
) return(NULL
);
226 context
->common
.acquire_cred_func
= sip_sec_acquire_cred__tls_dsk
;
227 context
->common
.init_context_func
= sip_sec_init_sec_context__tls_dsk
;
228 context
->common
.destroy_context_func
= sip_sec_destroy_sec_context__tls_dsk
;
229 context
->common
.make_signature_func
= sip_sec_make_signature__tls_dsk
;
230 context
->common
.verify_signature_func
= sip_sec_verify_signature__tls_dsk
;
231 context
->common
.context_name_func
= sip_sec_context_name__tls_dsk
;
233 return((SipSecContext
) context
);
236 gboolean
sip_sec_password__tls_dsk(void)
238 #if defined(HAVE_SSPI) || defined(HAVE_GSSAPI_GSSAPI_H)
240 * TLS-DSK authenticates with a published client certificate. This
241 * process uses Web Tickets and therefore goes through HTTP. If we
242 * have authentication schemes compiled in which allow Single Sign-On
243 * then we should allow password-less configurations.