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 /* Dummy initialization hook */
64 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER SipSecAuthType type
)
69 /* sip_sec API methods */
71 sip_sec_create_context(SipSecContext
*context
,
74 int is_connection_based
,
81 /* Map authentication type to module initialization hook & name */
82 static sip_sec_create_context_func
const auth_to_hook
[] = {
83 sip_sec_create_context__NONE
, /* AUTH_TYPE_UNSET */
84 sip_sec_create_context__NONE
, /* AUTH_TYPE_DIGEST */
85 sip_sec_create_context__NTLM
, /* AUTH_TYPE_NTLM */
86 sip_sec_create_context__Kerberos
, /* AUTH_TYPE_KERBEROS */
87 sip_sec_create_context__Negotiate
, /* AUTH_TYPE_NEGOTIATE */
90 /* @TODO: Can *context != NULL actually happen? */
91 sip_sec_destroy_context(*context
);
93 *context
= (*(auth_to_hook
[type
]))(type
);
94 if (!*context
) return;
96 (*context
)->sso
= sso
;
97 (*context
)->is_connection_based
= is_connection_based
;
99 ret
= (*(*context
)->acquire_cred_func
)(*context
, domain
, username
, password
);
100 if (ret
!= SIP_SEC_E_OK
) {
101 purple_debug_info("sipe", "ERROR: sip_sec_init_context failed to acquire credentials.\n");
107 sip_sec_init_context_step(SipSecContext context
,
109 const char *input_toked_base64
,
110 char **output_toked_base64
,
113 SipSecBuffer in_buff
= {0, NULL
};
114 SipSecBuffer out_buff
= {0, NULL
};
118 /* Not NULL for NTLM Type 2 */
119 if (input_toked_base64
) {
120 in_buff
.value
= purple_base64_decode(input_toked_base64
, &(in_buff
.length
));
122 tmp
= sip_sec_ntlm_message_describe(in_buff
);
124 purple_debug_info("sipe", "sip_sec_init_context_step: Chalenge message is:\n%s", tmp
);
129 ret
= (*context
->init_context_func
)(context
, in_buff
, &out_buff
, target
);
131 if (input_toked_base64
)
132 free_bytes_buffer(&in_buff
);
134 if (ret
== SIP_SEC_E_OK
|| ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
135 *output_toked_base64
= purple_base64_encode(out_buff
.value
, out_buff
.length
);
137 if (out_buff
.length
> 0 && out_buff
.value
) {
138 tmp
= sip_sec_ntlm_message_describe(out_buff
);
140 purple_debug_info("sipe", "sip_sec_init_context_step: Negotiate or Authenticate message is:\n%s", tmp
);
145 free_bytes_buffer(&out_buff
);
149 *expires
= context
->expires
;
156 sip_sec_init_context(SipSecContext
*context
,
161 const char *username
,
162 const char *password
,
164 const char *input_toked_base64
)
167 char *output_toked_base64
= NULL
;
170 sip_sec_create_context(context
,
173 0, /* Connectionless for SIP */
178 if (!*context
) return NULL
;
180 ret
= sip_sec_init_context_step(*context
,
183 &output_toked_base64
,
186 /* for NTLM type 3 */
187 if (ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
188 g_free(output_toked_base64
);
189 ret
= sip_sec_init_context_step(*context
,
192 &output_toked_base64
,
200 return output_toked_base64
;
204 sip_sec_destroy_context(SipSecContext context
)
206 if (context
) (*context
->destroy_context_func
)(context
);
209 char * sip_sec_make_signature(SipSecContext context
, const char *message
)
211 SipSecBuffer signature
;
214 if(((*context
->make_signature_func
)(context
, message
, &signature
)) != SIP_SEC_E_OK
) {
215 purple_debug_info("sipe", "ERROR: sip_sec_make_signature failed. Unable to sign message!\n");
218 signature_hex
= bytes_to_hex_str(&signature
);
219 free_bytes_buffer(&signature
);
220 return signature_hex
;
223 int sip_sec_verify_signature(SipSecContext context
, const char *message
, const char *signature_hex
)
225 SipSecBuffer signature
;
228 purple_debug_info("sipe", "sip_sec_verify_signature: message is:%s signature to verify is:%s\n",
229 message
? message
: "", signature_hex
? signature_hex
: "");
231 if (!message
|| !signature_hex
) return SIP_SEC_E_INTERNAL_ERROR
;
233 hex_str_to_bytes(signature_hex
, &signature
);
234 res
= (*context
->verify_signature_func
)(context
, message
, signature
);
235 free_bytes_buffer(&signature
);
240 /* Utility Methods */
242 void hex_str_to_bytes(const char *hex_str
, SipSecBuffer
*bytes
)
248 bytes
->length
= strlen(hex_str
)/2;
249 bytes
->value
= g_malloc(bytes
->length
);
251 buff
= (guint8
*)bytes
->value
;
252 for (i
= 0; i
< bytes
->length
; i
++) {
253 two_digits
[0] = hex_str
[i
* 2];
254 two_digits
[1] = hex_str
[i
* 2 + 1];
255 two_digits
[2] = '\0';
256 buff
[i
] = (guint8
)strtoul(two_digits
, NULL
, 16);
260 void free_bytes_buffer(SipSecBuffer
*bytes
)
262 g_free(bytes
->value
);
267 char *bytes_to_hex_str(SipSecBuffer
*bytes
)
269 guint8
*buff
= (guint8
*)bytes
->value
;
270 char *res
= g_malloc(bytes
->length
* 2 + 1);
272 for (i
= 0, j
= 0; i
< bytes
->length
; i
++, j
+=2) {
273 sprintf(&res
[j
], "%02X", buff
[i
]);