mingw: fixed Windows build
[siplcs.git] / src / core / sip-sec.c
blobcefde5db78718022498a03db8ba238a554b0d94d
1 /**
2 * @file sip-sec.c
4 * pidgin-sipe
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
24 #include <glib.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include "debug.h"
29 #include "sipe.h"
30 #include "sipe-core-api.h"
31 #include "sipe-utils.h"
32 #include "sip-sec-mech.h"
34 #include "sip-sec-ntlm.h"
35 #ifndef _WIN32
36 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
37 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
39 #ifdef USE_KERBEROS
40 #include "sip-sec-krb5.h"
41 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
42 #else
43 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
44 #endif
46 #else /* _WIN32 */
47 #ifdef USE_KERBEROS
48 #include "sip-sec-sspi.h"
49 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
50 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
51 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
52 #else /* USE_KERBEROS */
53 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
54 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
55 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
56 #endif /* USE_KERBEROS */
58 #endif /* _WIN32 */
60 gchar *purple_base64_encode(const guchar *data, gsize len);
61 guchar *purple_base64_decode(const char *str, gsize *ret_len);
63 /* Dummy initialization hook */
64 static SipSecContext
65 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER SipSecAuthType type)
67 return(NULL);
70 /* sip_sec API methods */
71 SipSecContext
72 sip_sec_create_context(SipSecAuthType type,
73 const int sso,
74 int is_connection_based,
75 const char *domain,
76 const char *username,
77 const char *password)
79 SipSecContext context = NULL;
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 context = (*(auth_to_hook[type]))(type);
91 if (context) {
92 sip_uint32 ret;
94 context->sso = sso;
95 context->is_connection_based = is_connection_based;
97 ret = (*context->acquire_cred_func)(context, domain, username, password);
98 if (ret != SIP_SEC_E_OK) {
99 purple_debug_info("sipe", "ERROR: sip_sec_init_context failed to acquire credentials.\n");
100 (*context->destroy_context_func)(context);
101 context = NULL;
105 return(context);
108 unsigned long
109 sip_sec_init_context_step(SipSecContext context,
110 const char *target,
111 const char *input_toked_base64,
112 char **output_toked_base64,
113 int *expires)
115 sip_uint32 ret = SIP_SEC_E_INTERNAL_ERROR;
117 if (context) {
118 SipSecBuffer in_buff = {0, NULL};
119 SipSecBuffer out_buff = {0, NULL};
120 char *tmp;
122 /* Not NULL for NTLM Type 2 */
123 if (input_toked_base64) {
124 in_buff.value = purple_base64_decode(input_toked_base64, &(in_buff.length));
126 tmp = sip_sec_ntlm_message_describe(in_buff);
127 if (tmp) {
128 purple_debug_info("sipe", "sip_sec_init_context_step: Challenge message is:\n%s", tmp);
130 g_free(tmp);
133 ret = (*context->init_context_func)(context, in_buff, &out_buff, target);
135 if (input_toked_base64)
136 g_free(in_buff.value);
138 if (ret == SIP_SEC_E_OK || ret == SIP_SEC_I_CONTINUE_NEEDED) {
139 *output_toked_base64 = purple_base64_encode(out_buff.value, out_buff.length);
141 if (out_buff.length > 0 && out_buff.value) {
142 tmp = sip_sec_ntlm_message_describe(out_buff);
143 if (tmp) {
144 purple_debug_info("sipe", "sip_sec_init_context_step: Negotiate or Authenticate message is:\n%s", tmp);
146 g_free(tmp);
149 g_free(out_buff.value);
152 if (expires) {
153 *expires = context->expires;
157 return ret;
160 char *
161 sip_sec_init_context(SipSecContext *context,
162 int *expires,
163 SipSecAuthType type,
164 const int sso,
165 const char *domain,
166 const char *username,
167 const char *password,
168 const char *target,
169 const char *input_toked_base64)
171 sip_uint32 ret;
172 char *output_toked_base64 = NULL;
173 int exp;
175 *context = sip_sec_create_context(type,
176 sso,
177 0, /* Connectionless for SIP */
178 domain,
179 username,
180 password);
181 if (!*context) return NULL;
183 ret = sip_sec_init_context_step(*context,
184 target,
185 NULL,
186 &output_toked_base64,
187 &exp);
189 /* for NTLM type 3 */
190 if (ret == SIP_SEC_I_CONTINUE_NEEDED) {
191 g_free(output_toked_base64);
192 ret = sip_sec_init_context_step(*context,
193 target,
194 input_toked_base64,
195 &output_toked_base64,
196 &exp);
199 if (expires) {
200 *expires = exp;
203 return output_toked_base64;
206 void
207 sip_sec_destroy_context(SipSecContext context)
209 if (context) (*context->destroy_context_func)(context);
212 char * sip_sec_make_signature(SipSecContext context, const char *message)
214 SipSecBuffer signature;
215 char *signature_hex;
217 if(((*context->make_signature_func)(context, message, &signature)) != SIP_SEC_E_OK) {
218 purple_debug_info("sipe", "ERROR: sip_sec_make_signature failed. Unable to sign message!\n");
219 return NULL;
221 signature_hex = buff_to_hex_str(signature.value, signature.length);
222 g_free(signature.value);
223 return signature_hex;
226 int sip_sec_verify_signature(SipSecContext context, const char *message, const char *signature_hex)
228 SipSecBuffer signature;
229 sip_uint32 res;
231 purple_debug_info("sipe", "sip_sec_verify_signature: message is:%s signature to verify is:%s\n",
232 message ? message : "", signature_hex ? signature_hex : "");
234 if (!message || !signature_hex) return SIP_SEC_E_INTERNAL_ERROR;
236 signature.length = hex_str_to_buff(signature_hex, &signature.value);
237 res = (*context->verify_signature_func)(context, message, signature);
238 g_free(signature.value);
239 return res;
242 /* Initialize & Destroy */
243 void sip_sec_init(void)
245 sip_sec_init__ntlm();
248 void sip_sec_destroy(void)
250 sip_sec_destroy__ntlm();
254 Local Variables:
255 mode: c
256 c-file-style: "bsd"
257 indent-tabs-mode: t
258 tab-width: 8
259 End: