buddy: add interface to iterate over buddies
[siplcs.git] / src / core / sip-sec.c
blobcf50dde88187f789d3f02f02e3fee7c18f9c1590
1 /**
2 * @file sip-sec.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2013 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-utils.h"
41 #include "sip-sec-mech.h"
43 /* SSPI is only supported on Windows platform */
44 #if defined(_WIN32) && defined(HAVE_SSPI)
45 #include "sip-sec-sspi.h"
46 #define SIP_SEC_WINDOWS_SSPI 1
47 #else
48 #define SIP_SEC_WINDOWS_SSPI 0
49 #endif
51 /* SIPE_AUTHENTICATION_TYPE_BASIC */
52 #include "sip-sec-basic.h"
53 #define sip_sec_create_context__Basic sip_sec_create_context__basic
54 /* Basic is only used for HTTP, not for SIP */
55 #define sip_sec_password__Basic sip_sec_password__NONE
57 /* SIPE_AUTHENTICATION_TYPE_NTLM */
58 #if SIP_SEC_WINDOWS_SSPI
59 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
60 #define sip_sec_password__NTLM sip_sec_password__sspi
61 #else
62 #include "sip-sec-ntlm.h"
63 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
64 #define sip_sec_password__NTLM sip_sec_password__ntlm
65 #endif
67 /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
68 #if SIP_SEC_WINDOWS_SSPI
69 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
70 #define sip_sec_password__Kerberos sip_sec_password__sspi
71 #elif defined(HAVE_LIBKRB5)
72 #include "sip-sec-krb5.h"
73 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
74 #define sip_sec_password__Kerberos sip_sec_password__krb5
75 #else
76 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
77 #define sip_sec_password__Kerberos sip_sec_password__NONE
78 #endif
80 /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
81 #if SIP_SEC_WINDOWS_SSPI
82 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
83 #elif defined(HAVE_LIBKRB5)
84 #include "sip-sec-negotiate.h"
85 #define sip_sec_create_context__Negotiate sip_sec_create_context__negotiate
86 #else
87 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
88 #endif
89 /* Negotiate is only used for HTTP, not for SIP */
90 #define sip_sec_password__Negotiate sip_sec_password__NONE
92 /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
93 #include "sip-sec-tls-dsk.h"
94 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
95 #define sip_sec_password__TLS_DSK sip_sec_password__tls_dsk
97 /* Dummy initialization hook */
98 static SipSecContext
99 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type)
101 return(NULL);
104 /* Dummy SIP password hook */
105 static gboolean sip_sec_password__NONE(void)
107 return(TRUE);
110 /* sip_sec API methods */
111 SipSecContext
112 sip_sec_create_context(guint type,
113 gboolean sso,
114 gboolean http,
115 const gchar *domain,
116 const gchar *username,
117 const gchar *password)
119 SipSecContext context = NULL;
121 /* Map authentication type to module initialization hook & name */
122 static sip_sec_create_context_func const auth_to_hook[] = {
123 sip_sec_create_context__NONE, /* SIPE_AUTHENTICATION_TYPE_UNSET */
124 sip_sec_create_context__Basic, /* SIPE_AUTHENTICATION_TYPE_BASIC */
125 sip_sec_create_context__NTLM, /* SIPE_AUTHENTICATION_TYPE_NTLM */
126 sip_sec_create_context__Kerberos, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
127 sip_sec_create_context__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
128 sip_sec_create_context__TLS_DSK, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
131 SIPE_DEBUG_INFO("sip_sec_create_context: type: %d, Single Sign-On: %s, protocol: %s",
132 type, sso ? "yes" : "no", http ? "HTTP" : "SIP");
134 context = (*(auth_to_hook[type]))(type);
135 if (context) {
137 /* NOTE: mechanism must set private flags acquire_cred_func()! */
138 context->flags = 0;
140 /* set common flags */
141 if (sso)
142 context->flags |= SIP_SEC_FLAG_COMMON_SSO;
143 if (http)
144 context->flags |= SIP_SEC_FLAG_COMMON_HTTP;
146 if (!(*context->acquire_cred_func)(context, domain, username, password)) {
147 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_create_context: failed to acquire credentials.");
148 (*context->destroy_context_func)(context);
149 context = NULL;
153 return(context);
156 gboolean
157 sip_sec_init_context_step(SipSecContext context,
158 const gchar *target,
159 const gchar *input_toked_base64,
160 gchar **output_toked_base64,
161 guint *expires)
163 gboolean ret = FALSE;
165 if (context) {
166 SipSecBuffer in_buff = {0, NULL};
167 SipSecBuffer out_buff = {0, NULL};
169 /* Not NULL for NTLM Type 2 or TLS-DSK */
170 if (input_toked_base64)
171 in_buff.value = g_base64_decode(input_toked_base64, &in_buff.length);
173 ret = (*context->init_context_func)(context, in_buff, &out_buff, target);
175 if (input_toked_base64)
176 g_free(in_buff.value);
178 if (ret) {
180 if (out_buff.value) {
181 if (out_buff.length > 0) {
182 *output_toked_base64 = g_base64_encode(out_buff.value, out_buff.length);
183 } else {
184 /* special string: caller takes ownership */
185 *output_toked_base64 = (gchar *) out_buff.value;
186 out_buff.value = NULL;
190 g_free(out_buff.value);
193 if (expires) {
194 *expires = context->expires;
198 return ret;
201 gboolean sip_sec_context_is_ready(SipSecContext context)
203 return(context && (context->flags & SIP_SEC_FLAG_COMMON_READY));
206 void
207 sip_sec_destroy_context(SipSecContext context)
209 if (context) (*context->destroy_context_func)(context);
212 gchar *sip_sec_make_signature(SipSecContext context, const gchar *message)
214 SipSecBuffer signature;
215 gchar *signature_hex;
217 if (!(*context->make_signature_func)(context, message, &signature)) {
218 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
219 return NULL;
221 signature_hex = buff_to_hex_str(signature.value, signature.length);
222 g_free(signature.value);
223 return signature_hex;
226 gboolean sip_sec_verify_signature(SipSecContext context,
227 const gchar *message,
228 const gchar *signature_hex)
230 SipSecBuffer signature;
231 gboolean res;
233 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
234 message ? message : "", signature_hex ? signature_hex : "");
236 if (!message || !signature_hex)
237 return FALSE;
239 signature.length = hex_str_to_buff(signature_hex, &signature.value);
240 res = (*context->verify_signature_func)(context, message, signature);
241 g_free(signature.value);
242 return res;
245 /* Does authentication type require a password? */
246 gboolean sip_sec_requires_password(guint authentication,
247 gboolean sso)
249 /* Map authentication type to module initialization hook & name */
250 static sip_sec_password_func const auth_to_hook[] = {
251 sip_sec_password__NONE, /* SIPE_AUTHENTICATION_TYPE_UNSET */
252 sip_sec_password__Basic, /* SIPE_AUTHENTICATION_TYPE_BASIC */
253 sip_sec_password__NTLM, /* SIPE_AUTHENTICATION_TYPE_NTLM */
254 sip_sec_password__Kerberos, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
255 sip_sec_password__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
256 sip_sec_password__TLS_DSK, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
259 /* If Single-Sign On is disabled then a password is required */
260 if (!sso)
261 return(TRUE);
263 /* Check if authentation method supports Single-Sign On */
264 return((*(auth_to_hook[authentication]))());
267 /* Initialize & Destroy */
268 void sip_sec_init(void)
270 #ifndef HAVE_SSPI
271 sip_sec_init__ntlm();
272 #endif
275 void sip_sec_destroy(void)
277 #ifndef HAVE_SSPI
278 sip_sec_destroy__ntlm();
279 #endif
283 Local Variables:
284 mode: c
285 c-file-style: "bsd"
286 indent-tabs-mode: t
287 tab-width: 8
288 End: