media: fix relay-info with Farstream 0.2
[siplcs.git] / src / core / sip-sec-tls-dsk.c
blobfbc5da92699f402be2987ef06812642c7a1b4b88
1 /**
2 * @file sip-sec-tls-dsk.c
4 * pidgin-sipe
6 * Copyright (C) 2011-2013 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
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <string.h>
38 #include <glib.h>
40 #include "sipe-common.h"
41 #include "sip-sec.h"
42 #include "sip-sec-mech.h"
43 #include "sip-sec-tls-dsk.h"
44 #include "sipe-backend.h"
45 #include "sipe-digest.h"
46 #include "sipe-tls.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;
53 guchar *client_key;
54 guchar *server_key;
55 gsize key_length;
56 } *context_tls_dsk;
58 /* sip-sec-mech.h API implementation for TLS-DSK */
60 static gboolean
61 sip_sec_acquire_cred__tls_dsk(SipSecContext context,
62 SIPE_UNUSED_PARAMETER const gchar *domain,
63 SIPE_UNUSED_PARAMETER const gchar *username,
64 const gchar *password)
66 context_tls_dsk ctx = (context_tls_dsk) context;
68 return((ctx->state = sipe_tls_start((gpointer) password)) != NULL);
71 static gboolean
72 sip_sec_init_sec_context__tls_dsk(SipSecContext context,
73 SipSecBuffer in_buff,
74 SipSecBuffer *out_buff,
75 SIPE_UNUSED_PARAMETER const gchar *service_name)
77 context_tls_dsk ctx = (context_tls_dsk) context;
78 struct sipe_tls_state *state = ctx->state;
80 state->in_buffer = in_buff.value;
81 state->in_length = in_buff.length;
83 if (sipe_tls_next(state)) {
84 if ((state->algorithm != SIPE_TLS_DIGEST_ALGORITHM_NONE) &&
85 state->client_key && state->server_key) {
86 /* Authentication is completed */
87 context->flags |= SIP_SEC_FLAG_COMMON_READY;
89 /* copy key pair */
90 ctx->algorithm = state->algorithm;
91 ctx->key_length = state->key_length;
92 ctx->client_key = g_memdup(state->client_key,
93 state->key_length);
94 ctx->server_key = g_memdup(state->server_key,
95 state->key_length);
97 /* [MS-SIPAE] Section 3.2.2 Timers
99 * ... For an SA established using the TLS-DSK
100 * authentication protocol, the client MUST
101 * retrieve the expiration time of its certificate.
102 * The expiration timer value is the lesser of the
103 * interval to the certificate expiration and eight
104 * hours, ...
106 ctx->common.expires = sipe_tls_expires(state);
107 if (ctx->common.expires > (8 * 60 * 60))
108 ctx->common.expires = 8 * 60 * 60;
110 SIPE_DEBUG_INFO("sip_sec_init_sec_context__tls_dsk: handshake completed, algorithm %d, key length %" G_GSIZE_FORMAT ", expires %d",
111 ctx->algorithm, ctx->key_length, ctx->common.expires);
113 sipe_tls_free(state);
114 ctx->state = NULL;
115 } else {
116 out_buff->value = state->out_buffer;
117 out_buff->length = state->out_length;
118 /* we take ownership of the buffer */
119 state->out_buffer = NULL;
121 } else {
122 sipe_tls_free(state);
123 ctx->state = NULL;
126 return(((context->flags & SIP_SEC_FLAG_COMMON_READY) ||
127 ctx->state));
130 static gboolean
131 sip_sec_make_signature__tls_dsk(SipSecContext context,
132 const gchar *message,
133 SipSecBuffer *signature)
135 context_tls_dsk ctx = (context_tls_dsk) context;
136 gboolean result = FALSE;
138 switch (ctx->algorithm) {
139 case SIPE_TLS_DIGEST_ALGORITHM_MD5:
140 signature->length = SIPE_DIGEST_HMAC_MD5_LENGTH;
141 signature->value = g_malloc0(signature->length);
142 sipe_digest_hmac_md5(ctx->client_key, ctx->key_length,
143 (guchar *) message, strlen(message),
144 signature->value);
145 result = TRUE;
146 break;
148 case SIPE_TLS_DIGEST_ALGORITHM_SHA1:
149 signature->length = SIPE_DIGEST_HMAC_SHA1_LENGTH;
150 signature->value = g_malloc0(signature->length);
151 sipe_digest_hmac_sha1(ctx->client_key, ctx->key_length,
152 (guchar *) message, strlen(message),
153 signature->value);
154 result = TRUE;
155 break;
157 default:
158 /* this should not happen */
159 break;
162 return(result);
165 static gboolean
166 sip_sec_verify_signature__tls_dsk(SipSecContext context,
167 const gchar *message,
168 SipSecBuffer signature)
170 context_tls_dsk ctx = (context_tls_dsk) context;
171 SipSecBuffer mac = { 0, NULL };
172 gboolean result = FALSE;
174 switch (ctx->algorithm) {
175 case SIPE_TLS_DIGEST_ALGORITHM_MD5:
176 mac.length = SIPE_DIGEST_HMAC_MD5_LENGTH;
177 mac.value = g_malloc0(mac.length);
178 sipe_digest_hmac_md5(ctx->server_key, ctx->key_length,
179 (guchar *) message, strlen(message),
180 mac.value);
181 break;
183 case SIPE_TLS_DIGEST_ALGORITHM_SHA1:
184 mac.length = SIPE_DIGEST_HMAC_SHA1_LENGTH;
185 mac.value = g_malloc0(mac.length);
186 sipe_digest_hmac_sha1(ctx->server_key, ctx->key_length,
187 (guchar *) message, strlen(message),
188 mac.value);
189 break;
191 default:
192 /* this should not happen */
193 break;
196 if (mac.value) {
197 result = memcmp(signature.value, mac.value, mac.length) == 0;
198 g_free(mac.value);
201 return(result);
204 static void
205 sip_sec_destroy_sec_context__tls_dsk(SipSecContext context)
207 context_tls_dsk ctx = (context_tls_dsk) context;
209 sipe_tls_free(ctx->state);
210 g_free(ctx->client_key);
211 g_free(ctx->server_key);
212 g_free(ctx);
215 static const gchar *
216 sip_sec_context_name__tls_dsk(SIPE_UNUSED_PARAMETER SipSecContext context)
218 return("TLS-DSK");
221 SipSecContext
222 sip_sec_create_context__tls_dsk(SIPE_UNUSED_PARAMETER guint type)
224 context_tls_dsk context = g_malloc0(sizeof(struct _context_tls_dsk));
225 if (!context) return(NULL);
227 context->common.acquire_cred_func = sip_sec_acquire_cred__tls_dsk;
228 context->common.init_context_func = sip_sec_init_sec_context__tls_dsk;
229 context->common.destroy_context_func = sip_sec_destroy_sec_context__tls_dsk;
230 context->common.make_signature_func = sip_sec_make_signature__tls_dsk;
231 context->common.verify_signature_func = sip_sec_verify_signature__tls_dsk;
232 context->common.context_name_func = sip_sec_context_name__tls_dsk;
234 return((SipSecContext) context);
237 gboolean sip_sec_password__tls_dsk(void)
239 #if defined(HAVE_SSPI) || defined(HAVE_GSSAPI_GSSAPI_H)
241 * TLS-DSK authenticates with a published client certificate. This
242 * process uses Web Tickets and therefore goes through HTTP. If we
243 * have authentication schemes compiled in which allow Single Sign-On
244 * then we should allow password-less configurations.
246 return(FALSE);
247 #else
248 return(TRUE);
249 #endif
253 Local Variables:
254 mode: c
255 c-file-style: "bsd"
256 indent-tabs-mode: t
257 tab-width: 8
258 End: