6 * Copyright (C) 2010-12 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-utils.h"
41 #include "sip-sec-mech.h"
43 #include "sip-sec-ntlm.h"
44 #include "sip-sec-tls-dsk.h"
45 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
46 #define sip_sec_password__NTLM sip_sec_password__ntlm
47 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
48 /* #define sip_sec_password__Negotiate: see below */
49 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
50 #define sip_sec_password__TLS_DSK sip_sec_password__tls_dsk
53 #include "sip-sec-krb5.h"
54 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
55 #define sip_sec_password__Kerberos sip_sec_password__krb5
57 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
58 #define sip_sec_password__Kerberos sip_sec_password__NONE
63 #include "sip-sec-sspi.h"
64 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
65 #define sip_sec_password__NTLM sip_sec_password__sspi
66 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
67 /* #define sip_sec_password__Negotiate: see below */
68 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
69 #define sip_sec_password__Kerberos sip_sec_password__sspi
70 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__sspi
71 #define sip_sec_password__TLS_DSK sip_sec_password__sspi
72 #else /* !HAVE_SSPI */
73 #include "sip-sec-ntlm.h"
74 #include "sip-sec-tls-dsk.h"
75 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
76 #define sip_sec_password__NTLM sip_sec_password__ntlm
77 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
78 /* #define sip_sec_password__Negotiate: see below */
79 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
80 #define sip_sec_password__Kerberos sip_sec_password__NONE
81 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
82 #define sip_sec_password__TLS_DSK sip_sec_password__tls_dsk
83 #endif /* HAVE_SSPI */
87 /* Dummy initialization hook */
89 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type
)
94 static gboolean
sip_sec_password__NONE(void)
99 /* sip_sec API methods */
101 sip_sec_create_context(guint type
,
103 int is_connection_based
,
105 const char *username
,
106 const char *password
)
108 SipSecContext context
= NULL
;
110 /* Map authentication type to module initialization hook & name */
111 static sip_sec_create_context_func
const auth_to_hook
[] = {
112 sip_sec_create_context__NONE
, /* SIPE_AUTHENTICATION_TYPE_UNSET */
113 sip_sec_create_context__NTLM
, /* SIPE_AUTHENTICATION_TYPE_NTLM */
114 sip_sec_create_context__Kerberos
, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
115 sip_sec_create_context__Negotiate
, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
116 sip_sec_create_context__TLS_DSK
, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
119 context
= (*(auth_to_hook
[type
]))(type
);
124 context
->is_connection_based
= is_connection_based
;
125 context
->is_ready
= TRUE
;
127 ret
= (*context
->acquire_cred_func
)(context
, domain
, username
, password
);
128 if (ret
!= SIP_SEC_E_OK
) {
129 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context failed to acquire credentials.");
130 (*context
->destroy_context_func
)(context
);
139 sip_sec_init_context_step(SipSecContext context
,
141 const char *input_toked_base64
,
142 char **output_toked_base64
,
145 sip_uint32 ret
= SIP_SEC_E_INTERNAL_ERROR
;
148 SipSecBuffer in_buff
= {0, NULL
};
149 SipSecBuffer out_buff
= {0, NULL
};
151 /* Not NULL for NTLM Type 2 or TLS-DSK */
152 if (input_toked_base64
)
153 in_buff
.value
= g_base64_decode(input_toked_base64
, &in_buff
.length
);
155 ret
= (*context
->init_context_func
)(context
, in_buff
, &out_buff
, target
);
157 if (input_toked_base64
)
158 g_free(in_buff
.value
);
160 if (ret
== SIP_SEC_E_OK
|| ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
162 if (out_buff
.length
> 0 && out_buff
.value
) {
163 *output_toked_base64
= g_base64_encode(out_buff
.value
, out_buff
.length
);
165 *output_toked_base64
= NULL
;
168 g_free(out_buff
.value
);
172 *expires
= context
->expires
;
180 sip_sec_init_context(SipSecContext
*context
,
185 const char *username
,
186 const char *password
,
188 const char *input_toked_base64
)
191 char *output_toked_base64
= NULL
;
194 *context
= sip_sec_create_context(type
,
196 0, /* Connectionless for SIP */
201 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context: failed sip_sec_create_context()");
205 ret
= sip_sec_init_context_step(*context
,
208 &output_toked_base64
,
211 /* for NTLM type 3 */
212 if (ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
213 g_free(output_toked_base64
);
214 ret
= sip_sec_init_context_step(*context
,
217 &output_toked_base64
,
225 return output_toked_base64
;
228 gboolean
sip_sec_context_is_ready(SipSecContext context
)
230 return(context
&& (context
->is_ready
!= 0));
234 sip_sec_destroy_context(SipSecContext context
)
236 if (context
) (*context
->destroy_context_func
)(context
);
239 char * sip_sec_make_signature(SipSecContext context
, const char *message
)
241 SipSecBuffer signature
;
244 if(((*context
->make_signature_func
)(context
, message
, &signature
)) != SIP_SEC_E_OK
) {
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 int sip_sec_verify_signature(SipSecContext context
, const char *message
, const char *signature_hex
)
255 SipSecBuffer signature
;
258 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
259 message
? message
: "", signature_hex
? signature_hex
: "");
261 if (!message
|| !signature_hex
) return SIP_SEC_E_INTERNAL_ERROR
;
263 signature
.length
= hex_str_to_buff(signature_hex
, &signature
.value
);
264 res
= (*context
->verify_signature_func
)(context
, message
, signature
);
265 g_free(signature
.value
);
269 /* Does authentication type require a password? */
270 gboolean
sip_sec_requires_password(guint authentication
,
273 /* Map authentication type to module initialization hook & name */
274 static sip_sec_password_func
const auth_to_hook
[] = {
275 sip_sec_password__NONE
, /* SIPE_AUTHENTICATION_TYPE_UNSET */
276 sip_sec_password__NTLM
, /* SIPE_AUTHENTICATION_TYPE_NTLM */
277 sip_sec_password__Kerberos
, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
278 /* Negotiate is only used internally so pasword requirement doesn't make sense */
279 sip_sec_password__NONE
, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
280 sip_sec_password__TLS_DSK
, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
283 /* If Single-Sign On is disabled then a password is required */
287 /* Check if authentation method supports Single-Sign On */
288 return((*(auth_to_hook
[authentication
]))());
291 /* Initialize & Destroy */
292 void sip_sec_init(void)
295 sip_sec_init__ntlm();
299 void sip_sec_destroy(void)
302 sip_sec_destroy__ntlm();