security: remove domain from internal interface
[siplcs.git] / src / core / sip-sec.c
blob9fb255f778af3d8ce91de8b931f34ef7e117321b
1 /**
2 * @file sip-sec.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2015 SIPE Project <http://sipe.sourceforge.net/>
7 * Copyright (C) 2009 pier11 <pier11@operamail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <time.h>
34 #include <glib.h>
36 #include "sipe-common.h"
37 #include "sip-sec.h"
38 #include "sipe-backend.h"
39 #include "sipe-core.h"
40 #include "sipe-utils.h"
42 #include "sip-sec-mech.h"
44 /* SSPI is only supported on Windows platform */
45 #if defined(_WIN32) && defined(HAVE_SSPI)
46 #include "sip-sec-sspi.h"
47 #define SIP_SEC_WINDOWS_SSPI 1
48 #else
49 #define SIP_SEC_WINDOWS_SSPI 0
50 #endif
52 #ifdef HAVE_GSSAPI_GSSAPI_H
53 #include "sip-sec-gssapi.h"
54 #endif
56 /* SIPE_AUTHENTICATION_TYPE_BASIC */
57 #include "sip-sec-basic.h"
58 #define sip_sec_create_context__Basic sip_sec_create_context__basic
59 /* Basic is only used for HTTP, not for SIP */
60 #define sip_sec_password__Basic sip_sec_password__NONE
62 /* SIPE_AUTHENTICATION_TYPE_NTLM */
63 #if SIP_SEC_WINDOWS_SSPI
64 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
65 #define sip_sec_password__NTLM sip_sec_password__sspi
66 #elif defined(HAVE_GSSAPI_ONLY)
67 #define sip_sec_create_context__NTLM sip_sec_create_context__gssapi
68 #define sip_sec_password__NTLM sip_sec_password__gssapi
69 #else
70 #include "sip-sec-ntlm.h"
71 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
72 #define sip_sec_password__NTLM sip_sec_password__ntlm
73 #endif
75 /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
76 #if SIP_SEC_WINDOWS_SSPI
77 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
78 #define sip_sec_password__Kerberos sip_sec_password__sspi
79 #elif defined(HAVE_GSSAPI_GSSAPI_H)
80 #define sip_sec_create_context__Kerberos sip_sec_create_context__gssapi
81 #define sip_sec_password__Kerberos sip_sec_password__gssapi
82 #else
83 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
84 #define sip_sec_password__Kerberos sip_sec_password__NONE
85 #endif
87 /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
88 #if SIP_SEC_WINDOWS_SSPI
89 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
90 #elif defined(HAVE_GSSAPI_ONLY)
91 #define sip_sec_create_context__Negotiate sip_sec_create_context__gssapi
92 #elif defined(HAVE_GSSAPI_GSSAPI_H)
93 #include "sip-sec-negotiate.h"
94 #define sip_sec_create_context__Negotiate sip_sec_create_context__negotiate
95 #else
96 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
97 #endif
98 /* Negotiate is only used for HTTP, not for SIP */
99 #define sip_sec_password__Negotiate sip_sec_password__NONE
101 /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
102 #include "sip-sec-tls-dsk.h"
103 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
104 #define sip_sec_password__TLS_DSK sip_sec_password__tls_dsk
106 /* Dummy initialization hook */
107 static SipSecContext
108 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type)
110 return(NULL);
113 /* Dummy SIP password hooks */
114 static gboolean sip_sec_password__NONE(void)
116 /* Don't ask for a password */
117 return(FALSE);
120 /* sip_sec API methods */
121 SipSecContext
122 sip_sec_create_context(guint type,
123 gboolean sso,
124 gboolean http,
125 SIPE_UNUSED_PARAMETER const gchar *domain,
126 const gchar *username,
127 const gchar *password)
129 SipSecContext context = NULL;
131 /* Map authentication type to module initialization hook & name */
132 static sip_sec_create_context_func const auth_to_hook[] = {
133 sip_sec_create_context__NONE, /* SIPE_AUTHENTICATION_TYPE_UNSET */
134 sip_sec_create_context__Basic, /* SIPE_AUTHENTICATION_TYPE_BASIC */
135 sip_sec_create_context__NTLM, /* SIPE_AUTHENTICATION_TYPE_NTLM */
136 sip_sec_create_context__Kerberos, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
137 sip_sec_create_context__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
138 sip_sec_create_context__TLS_DSK, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
139 sip_sec_create_context__NONE, /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */
142 SIPE_DEBUG_INFO("sip_sec_create_context: type: %d, Single Sign-On: %s, protocol: %s",
143 type, sso ? "yes" : "no", http ? "HTTP" : "SIP");
145 context = (*(auth_to_hook[type]))(type);
146 if (context) {
148 context->type = type;
150 /* NOTE: mechanism must set private flags acquire_cred_func()! */
151 context->flags = 0;
153 /* set common flags */
154 if (sso)
155 context->flags |= SIP_SEC_FLAG_COMMON_SSO;
156 if (http)
157 context->flags |= SIP_SEC_FLAG_COMMON_HTTP;
159 if (!(*context->acquire_cred_func)(context, username, password)) {
160 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_create_context: failed to acquire credentials.");
161 (*context->destroy_context_func)(context);
162 context = NULL;
166 return(context);
169 gboolean
170 sip_sec_init_context_step(SipSecContext context,
171 const gchar *target,
172 const gchar *input_toked_base64,
173 gchar **output_toked_base64,
174 guint *expires)
176 gboolean ret = FALSE;
178 if (context) {
179 SipSecBuffer in_buff = {0, NULL};
180 SipSecBuffer out_buff = {0, NULL};
182 /* Not NULL for NTLM Type 2 or TLS-DSK */
183 if (input_toked_base64)
184 in_buff.value = g_base64_decode(input_toked_base64, &in_buff.length);
186 ret = (*context->init_context_func)(context, in_buff, &out_buff, target);
188 if (input_toked_base64)
189 g_free(in_buff.value);
191 if (ret) {
193 if (out_buff.value) {
194 if (out_buff.length > 0) {
195 *output_toked_base64 = g_base64_encode(out_buff.value, out_buff.length);
196 } else {
197 /* special string: caller takes ownership */
198 *output_toked_base64 = (gchar *) out_buff.value;
199 out_buff.value = NULL;
203 g_free(out_buff.value);
206 if (expires) {
207 *expires = context->expires;
211 return ret;
214 gboolean sip_sec_context_is_ready(SipSecContext context)
216 return(context && (context->flags & SIP_SEC_FLAG_COMMON_READY));
219 const gchar *sip_sec_context_name(SipSecContext context)
221 if (context)
222 return((*context->context_name_func)(context));
223 else
224 return(NULL);
227 guint sip_sec_context_type(SipSecContext context)
229 if (context)
230 return(context->type);
231 else
232 return(SIPE_AUTHENTICATION_TYPE_UNSET);
235 void sip_sec_destroy_context(SipSecContext context)
237 if (context) (*context->destroy_context_func)(context);
240 gchar *sip_sec_make_signature(SipSecContext context, const gchar *message)
242 SipSecBuffer signature;
243 gchar *signature_hex;
245 if (!(*context->make_signature_func)(context, message, &signature)) {
246 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
247 return NULL;
249 signature_hex = buff_to_hex_str(signature.value, signature.length);
250 g_free(signature.value);
251 return signature_hex;
254 gboolean sip_sec_verify_signature(SipSecContext context,
255 const gchar *message,
256 const gchar *signature_hex)
258 SipSecBuffer signature;
259 gboolean res;
261 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
262 message ? message : "", signature_hex ? signature_hex : "");
264 if (!message || !signature_hex)
265 return FALSE;
267 signature.length = hex_str_to_buff(signature_hex, &signature.value);
268 res = (*context->verify_signature_func)(context, message, signature);
269 g_free(signature.value);
270 return res;
273 /* Does authentication type require a password? */
274 gboolean sip_sec_requires_password(guint authentication,
275 gboolean sso)
277 /* Map authentication type to module initialization hook & name */
278 static sip_sec_password_func const auth_to_hook[] = {
279 sip_sec_password__NONE, /* SIPE_AUTHENTICATION_TYPE_UNSET */
280 sip_sec_password__Basic, /* SIPE_AUTHENTICATION_TYPE_BASIC */
281 sip_sec_password__NTLM, /* SIPE_AUTHENTICATION_TYPE_NTLM */
282 sip_sec_password__Kerberos, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
283 sip_sec_password__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
284 sip_sec_password__TLS_DSK, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
285 sip_sec_password__NONE, /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */
288 /* If Single-Sign On is disabled then a password is required */
289 if (!sso)
290 return(TRUE);
292 /* Check if authentation method supports Single-Sign On */
293 return((*(auth_to_hook[authentication]))());
296 /* Initialize & Destroy */
297 void sip_sec_init(void)
299 #if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)
300 sip_sec_init__ntlm();
301 #endif
304 void sip_sec_destroy(void)
306 #if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)
307 sip_sec_destroy__ntlm();
308 #endif
312 Local Variables:
313 mode: c
314 c-file-style: "bsd"
315 indent-tabs-mode: t
316 tab-width: 8
317 End: