security: fix target name memory leak in Kerberos
[siplcs.git] / src / core / sip-sec-tls-dsk.c
blob473bcf0927b4d46d78fa374cd0e7bc69f52b13d6
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 #include <string.h>
34 #include <glib.h>
36 #include "sipe-common.h"
37 #include "sip-sec.h"
38 #include "sip-sec-mech.h"
39 #include "sip-sec-tls-dsk.h"
40 #include "sipe-backend.h"
41 #include "sipe-digest.h"
42 #include "sipe-tls.h"
44 /* Security context for TLS-DSK */
45 typedef struct _context_tls_dsk {
46 struct sip_sec_context common;
47 struct sipe_tls_state *state;
48 enum sipe_tls_digest_algorithm algorithm;
49 guchar *client_key;
50 guchar *server_key;
51 gsize key_length;
52 } *context_tls_dsk;
54 /* sip-sec-mech.h API implementation for TLS-DSK */
56 static sip_uint32
57 sip_sec_acquire_cred__tls_dsk(SipSecContext context,
58 SIPE_UNUSED_PARAMETER const char *domain,
59 SIPE_UNUSED_PARAMETER const char *username,
60 const char *password)
62 context_tls_dsk ctx = (context_tls_dsk)context;
64 ctx->state = sipe_tls_start((gpointer) password);
65 return(ctx->state ? SIP_SEC_E_OK : SIP_SEC_E_INTERNAL_ERROR);
68 static sip_uint32
69 sip_sec_init_sec_context__tls_dsk(SipSecContext context,
70 SipSecBuffer in_buff,
71 SipSecBuffer *out_buff,
72 SIPE_UNUSED_PARAMETER const char *service_name)
74 context_tls_dsk ctx = (context_tls_dsk) context;
75 struct sipe_tls_state *state = ctx->state;
77 state->in_buffer = in_buff.value;
78 state->in_length = in_buff.length;
80 if (sipe_tls_next(state)) {
81 if ((state->algorithm != SIPE_TLS_DIGEST_ALGORITHM_NONE) &&
82 state->client_key && state->server_key) {
83 /* Authentication is completed */
84 ctx->common.is_ready = TRUE;
86 /* copy key pair */
87 ctx->algorithm = state->algorithm;
88 ctx->key_length = state->key_length;
89 ctx->client_key = g_memdup(state->client_key,
90 state->key_length);
91 ctx->server_key = g_memdup(state->server_key,
92 state->key_length);
94 /* [MS-SIPAE] Section 3.2.2 Timers
96 * ... For an SA established using the TLS-DSK
97 * authentication protocol, the client MUST
98 * retrieve the expiration time of its certificate.
99 * The expiration timer value is the lesser of the
100 * interval to the certificate expiration and eight
101 * hours, ...
103 ctx->common.expires = sipe_tls_expires(state);
104 if (ctx->common.expires > (8 * 60 * 60))
105 ctx->common.expires = 8 * 60 * 60;
107 SIPE_DEBUG_INFO("sip_sec_init_sec_context__tls_dsk: handshake completed, algorithm %d, key length %" G_GSIZE_FORMAT ", expires %d",
108 ctx->algorithm, ctx->key_length, ctx->common.expires);
110 sipe_tls_free(state);
111 ctx->state = NULL;
112 } else {
113 out_buff->value = state->out_buffer;
114 out_buff->length = state->out_length;
115 /* we take ownership of the buffer */
116 state->out_buffer = NULL;
118 } else {
119 sipe_tls_free(state);
120 ctx->state = NULL;
123 return((ctx->common.is_ready || ctx->state) ? SIP_SEC_E_OK : SIP_SEC_E_INTERNAL_ERROR);
126 static sip_uint32
127 sip_sec_make_signature__tls_dsk(SipSecContext context,
128 const char *message,
129 SipSecBuffer *signature)
131 context_tls_dsk ctx = (context_tls_dsk) context;
132 sip_uint32 result = SIP_SEC_E_INTERNAL_ERROR;
134 switch (ctx->algorithm) {
135 case SIPE_TLS_DIGEST_ALGORITHM_MD5:
136 signature->length = SIPE_DIGEST_HMAC_MD5_LENGTH;
137 signature->value = g_malloc0(signature->length);
138 sipe_digest_hmac_md5(ctx->client_key, ctx->key_length,
139 (guchar *) message, strlen(message),
140 signature->value);
141 result = SIP_SEC_E_OK;
142 break;
144 case SIPE_TLS_DIGEST_ALGORITHM_SHA1:
145 signature->length = SIPE_DIGEST_HMAC_SHA1_LENGTH;
146 signature->value = g_malloc0(signature->length);
147 sipe_digest_hmac_sha1(ctx->client_key, ctx->key_length,
148 (guchar *) message, strlen(message),
149 signature->value);
150 result = SIP_SEC_E_OK;
151 break;
153 default:
154 /* this should not happen */
155 break;
158 return(result);
161 static sip_uint32
162 sip_sec_verify_signature__tls_dsk(SipSecContext context,
163 const char *message,
164 SipSecBuffer signature)
166 context_tls_dsk ctx = (context_tls_dsk) context;
167 SipSecBuffer mac = { 0, NULL };
168 sip_uint32 result = SIP_SEC_E_INTERNAL_ERROR;
170 switch (ctx->algorithm) {
171 case SIPE_TLS_DIGEST_ALGORITHM_MD5:
172 mac.length = SIPE_DIGEST_HMAC_MD5_LENGTH;
173 mac.value = g_malloc0(mac.length);
174 sipe_digest_hmac_md5(ctx->server_key, ctx->key_length,
175 (guchar *) message, strlen(message),
176 mac.value);
177 break;
179 case SIPE_TLS_DIGEST_ALGORITHM_SHA1:
180 mac.length = SIPE_DIGEST_HMAC_SHA1_LENGTH;
181 mac.value = g_malloc0(mac.length);
182 sipe_digest_hmac_sha1(ctx->server_key, ctx->key_length,
183 (guchar *) message, strlen(message),
184 mac.value);
185 break;
187 default:
188 /* this should not happen */
189 break;
192 if (mac.value) {
193 result = memcmp(signature.value, mac.value, mac.length) ?
194 SIP_SEC_E_INTERNAL_ERROR : SIP_SEC_E_OK;
195 g_free(mac.value);
198 return(result);
201 static void
202 sip_sec_destroy_sec_context__tls_dsk(SipSecContext context)
204 context_tls_dsk ctx = (context_tls_dsk) context;
206 sipe_tls_free(ctx->state);
207 g_free(ctx->client_key);
208 g_free(ctx->server_key);
209 g_free(ctx);
212 SipSecContext
213 sip_sec_create_context__tls_dsk(SIPE_UNUSED_PARAMETER guint type)
215 context_tls_dsk context = g_malloc0(sizeof(struct _context_tls_dsk));
216 if (!context) return(NULL);
218 context->common.acquire_cred_func = sip_sec_acquire_cred__tls_dsk;
219 context->common.init_context_func = sip_sec_init_sec_context__tls_dsk;
220 context->common.destroy_context_func = sip_sec_destroy_sec_context__tls_dsk;
221 context->common.make_signature_func = sip_sec_make_signature__tls_dsk;
222 context->common.verify_signature_func = sip_sec_verify_signature__tls_dsk;
224 return((SipSecContext) context);
227 gboolean sip_sec_password__tls_dsk(void)
229 return(TRUE);
233 Local Variables:
234 mode: c
235 c-file-style: "bsd"
236 indent-tabs-mode: t
237 tab-width: 8
238 End: