6 * Copyright (C) 2009 pier11 <pier11@operamail.com>
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
29 /* #include "util.h" */
31 #include "sip-sec-mech.h"
33 #include "sip-sec-ntlm.h"
35 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
36 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
39 #include "sip-sec-krb5.h"
40 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
42 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
47 #include "sip-sec-sspi.h"
48 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
49 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
50 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
51 #else /* USE_KERBEROS */
52 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
53 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
54 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
55 #endif /* USE_KERBEROS */
59 gchar
*purple_base64_encode(const guchar
*data
, gsize len
);
60 guchar
*purple_base64_decode(const char *str
, gsize
*ret_len
);
62 /* @TODO: copy&paste stinks. Find a better solution! */
64 hex_str_to_buff(const char *hex_str
, guint8
**buff
);
66 buff_to_hex_str(const guint8
*buff
, const size_t buff_len
);
68 /* Dummy initialization hook */
70 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER SipSecAuthType type
)
75 /* sip_sec API methods */
77 sip_sec_create_context(SipSecAuthType type
,
79 int is_connection_based
,
84 SipSecContext context
= NULL
;
86 /* Map authentication type to module initialization hook & name */
87 static sip_sec_create_context_func
const auth_to_hook
[] = {
88 sip_sec_create_context__NONE
, /* AUTH_TYPE_UNSET */
89 sip_sec_create_context__NONE
, /* AUTH_TYPE_DIGEST */
90 sip_sec_create_context__NTLM
, /* AUTH_TYPE_NTLM */
91 sip_sec_create_context__Kerberos
, /* AUTH_TYPE_KERBEROS */
92 sip_sec_create_context__Negotiate
, /* AUTH_TYPE_NEGOTIATE */
95 context
= (*(auth_to_hook
[type
]))(type
);
100 context
->is_connection_based
= is_connection_based
;
102 ret
= (*context
->acquire_cred_func
)(context
, domain
, username
, password
);
103 if (ret
!= SIP_SEC_E_OK
) {
104 purple_debug_info("sipe", "ERROR: sip_sec_init_context failed to acquire credentials.\n");
105 (*context
->destroy_context_func
)(context
);
114 sip_sec_init_context_step(SipSecContext context
,
116 const char *input_toked_base64
,
117 char **output_toked_base64
,
120 sip_uint32 ret
= SIP_SEC_E_INTERNAL_ERROR
;
123 SipSecBuffer in_buff
= {0, NULL
};
124 SipSecBuffer out_buff
= {0, NULL
};
127 /* Not NULL for NTLM Type 2 */
128 if (input_toked_base64
) {
129 in_buff
.value
= purple_base64_decode(input_toked_base64
, &(in_buff
.length
));
131 tmp
= sip_sec_ntlm_message_describe(in_buff
);
133 purple_debug_info("sipe", "sip_sec_init_context_step: Challenge message is:\n%s", tmp
);
138 ret
= (*context
->init_context_func
)(context
, in_buff
, &out_buff
, target
);
140 if (input_toked_base64
)
141 g_free(in_buff
.value
);
143 if (ret
== SIP_SEC_E_OK
|| ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
144 *output_toked_base64
= purple_base64_encode(out_buff
.value
, out_buff
.length
);
146 if (out_buff
.length
> 0 && out_buff
.value
) {
147 tmp
= sip_sec_ntlm_message_describe(out_buff
);
149 purple_debug_info("sipe", "sip_sec_init_context_step: Negotiate or Authenticate message is:\n%s", tmp
);
154 g_free(out_buff
.value
);
158 *expires
= context
->expires
;
166 sip_sec_init_context(SipSecContext
*context
,
171 const char *username
,
172 const char *password
,
174 const char *input_toked_base64
)
177 char *output_toked_base64
= NULL
;
180 *context
= sip_sec_create_context(type
,
182 0, /* Connectionless for SIP */
186 if (!*context
) return NULL
;
188 ret
= sip_sec_init_context_step(*context
,
191 &output_toked_base64
,
194 /* for NTLM type 3 */
195 if (ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
196 g_free(output_toked_base64
);
197 ret
= sip_sec_init_context_step(*context
,
200 &output_toked_base64
,
208 return output_toked_base64
;
212 sip_sec_destroy_context(SipSecContext context
)
214 if (context
) (*context
->destroy_context_func
)(context
);
217 char * sip_sec_make_signature(SipSecContext context
, const char *message
)
219 SipSecBuffer signature
;
222 if(((*context
->make_signature_func
)(context
, message
, &signature
)) != SIP_SEC_E_OK
) {
223 purple_debug_info("sipe", "ERROR: sip_sec_make_signature failed. Unable to sign message!\n");
226 signature_hex
= buff_to_hex_str(signature
.value
, signature
.length
);
227 g_free(signature
.value
);
228 return signature_hex
;
231 int sip_sec_verify_signature(SipSecContext context
, const char *message
, const char *signature_hex
)
233 SipSecBuffer signature
;
236 purple_debug_info("sipe", "sip_sec_verify_signature: message is:%s signature to verify is:%s\n",
237 message
? message
: "", signature_hex
? signature_hex
: "");
239 if (!message
|| !signature_hex
) return SIP_SEC_E_INTERNAL_ERROR
;
241 signature
.length
= hex_str_to_buff(signature_hex
, &signature
.value
);
242 res
= (*context
->verify_signature_func
)(context
, message
, signature
);
243 g_free(signature
.value
);
247 /* Initialize & Destroy */
248 void sip_sec_init(void)
250 sip_sec_init__ntlm();
253 void sip_sec_destroy(void)
255 sip_sec_destroy__ntlm();