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
36 #include "sipe-common.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
49 #define SIP_SEC_WINDOWS_SSPI 0
52 #ifdef HAVE_GSSAPI_GSSAPI_H
53 #include "sip-sec-gssapi.h"
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
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
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
83 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
84 #define sip_sec_password__Kerberos sip_sec_password__NONE
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
96 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
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 */
108 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type
)
113 /* Dummy SIP password hooks */
114 static gboolean
sip_sec_password__NONE(void)
116 /* Don't ask for a password */
120 /* sip_sec API methods */
122 sip_sec_create_context(guint type
,
125 const gchar
*username
,
126 const gchar
*password
)
128 SipSecContext context
= NULL
;
130 /* Map authentication type to module initialization hook & name */
131 static sip_sec_create_context_func
const auth_to_hook
[] = {
132 sip_sec_create_context__NONE
, /* SIPE_AUTHENTICATION_TYPE_UNSET */
133 sip_sec_create_context__Basic
, /* SIPE_AUTHENTICATION_TYPE_BASIC */
134 sip_sec_create_context__NTLM
, /* SIPE_AUTHENTICATION_TYPE_NTLM */
135 sip_sec_create_context__Kerberos
, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
136 sip_sec_create_context__Negotiate
, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
137 sip_sec_create_context__TLS_DSK
, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
138 sip_sec_create_context__NONE
, /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */
141 SIPE_DEBUG_INFO("sip_sec_create_context: type: %d, Single Sign-On: %s, protocol: %s",
142 type
, sso
? "yes" : "no", http
? "HTTP" : "SIP");
144 context
= (*(auth_to_hook
[type
]))(type
);
147 context
->type
= type
;
149 /* NOTE: mechanism must set private flags acquire_cred_func()! */
152 /* set common flags */
154 context
->flags
|= SIP_SEC_FLAG_COMMON_SSO
;
156 context
->flags
|= SIP_SEC_FLAG_COMMON_HTTP
;
158 if (!(*context
->acquire_cred_func
)(context
, username
, password
)) {
159 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_create_context: failed to acquire credentials.");
160 (*context
->destroy_context_func
)(context
);
169 sip_sec_init_context_step(SipSecContext context
,
171 const gchar
*input_toked_base64
,
172 gchar
**output_toked_base64
,
175 gboolean ret
= FALSE
;
178 SipSecBuffer in_buff
= {0, NULL
};
179 SipSecBuffer out_buff
= {0, NULL
};
181 /* Not NULL for NTLM Type 2 or TLS-DSK */
182 if (input_toked_base64
)
183 in_buff
.value
= g_base64_decode(input_toked_base64
, &in_buff
.length
);
185 ret
= (*context
->init_context_func
)(context
, in_buff
, &out_buff
, target
);
187 if (input_toked_base64
)
188 g_free(in_buff
.value
);
192 if (out_buff
.value
) {
193 if (out_buff
.length
> 0) {
194 *output_toked_base64
= g_base64_encode(out_buff
.value
, out_buff
.length
);
196 /* special string: caller takes ownership */
197 *output_toked_base64
= (gchar
*) out_buff
.value
;
198 out_buff
.value
= NULL
;
202 g_free(out_buff
.value
);
206 *expires
= context
->expires
;
213 gboolean
sip_sec_context_is_ready(SipSecContext context
)
215 return(context
&& (context
->flags
& SIP_SEC_FLAG_COMMON_READY
));
218 const gchar
*sip_sec_context_name(SipSecContext context
)
221 return((*context
->context_name_func
)(context
));
226 guint
sip_sec_context_type(SipSecContext context
)
229 return(context
->type
);
231 return(SIPE_AUTHENTICATION_TYPE_UNSET
);
234 void sip_sec_destroy_context(SipSecContext context
)
236 if (context
) (*context
->destroy_context_func
)(context
);
239 gchar
*sip_sec_make_signature(SipSecContext context
, const gchar
*message
)
241 SipSecBuffer signature
;
242 gchar
*signature_hex
;
244 if (!(*context
->make_signature_func
)(context
, message
, &signature
)) {
245 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
248 signature_hex
= buff_to_hex_str(signature
.value
, signature
.length
);
249 g_free(signature
.value
);
250 return signature_hex
;
253 gboolean
sip_sec_verify_signature(SipSecContext context
,
254 const gchar
*message
,
255 const gchar
*signature_hex
)
257 SipSecBuffer signature
;
260 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
261 message
? message
: "", signature_hex
? signature_hex
: "");
263 if (!message
|| !signature_hex
)
266 signature
.length
= hex_str_to_buff(signature_hex
, &signature
.value
);
267 res
= (*context
->verify_signature_func
)(context
, message
, signature
);
268 g_free(signature
.value
);
272 /* Does authentication type require a password? */
273 gboolean
sip_sec_requires_password(guint authentication
,
276 /* Map authentication type to module initialization hook & name */
277 static sip_sec_password_func
const auth_to_hook
[] = {
278 sip_sec_password__NONE
, /* SIPE_AUTHENTICATION_TYPE_UNSET */
279 sip_sec_password__Basic
, /* SIPE_AUTHENTICATION_TYPE_BASIC */
280 sip_sec_password__NTLM
, /* SIPE_AUTHENTICATION_TYPE_NTLM */
281 sip_sec_password__Kerberos
, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
282 sip_sec_password__Negotiate
, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
283 sip_sec_password__TLS_DSK
, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
284 sip_sec_password__NONE
, /* SIPE_AUTHENTICATION_TYPE_AUTOMATIC */
287 /* If Single-Sign On is disabled then a password is required */
291 /* Check if authentation method supports Single-Sign On */
292 return((*(auth_to_hook
[authentication
]))());
295 /* Initialize & Destroy */
296 void sip_sec_init(void)
298 #if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)
299 sip_sec_init__ntlm();
303 void sip_sec_destroy(void)
305 #if !defined(HAVE_GSSAPI_ONLY) && !defined(HAVE_SSPI)
306 sip_sec_destroy__ntlm();