interface cleanup: decouple header files
[siplcs.git] / src / core / sip-sec.c
blob4a5f2d01b7494112932b6d57e41a9116bd87fcce
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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <time.h>
33 #include <glib.h>
35 #include "debug.h"
36 #include "util.h"
38 #include "sip-sec.h"
39 #include "sipe-core-api.h"
40 #include "sipe-utils.h"
42 #include "sip-sec-mech.h"
43 #include "sip-sec-ntlm.h"
44 #ifndef _WIN32
45 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
46 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
48 #ifdef HAVE_KERBEROS
49 #include "sip-sec-krb5.h"
50 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
51 #else
52 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
53 #endif
55 #else /* _WIN32 */
56 #ifdef HAVE_KERBEROS
57 #include "sip-sec-sspi.h"
58 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
59 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
60 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
61 #else /* HAVE_KERBEROS */
62 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
63 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
64 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
65 #endif /* HAVE_KERBEROS */
67 #endif /* _WIN32 */
69 /* Dummy initialization hook */
70 static SipSecContext
71 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER SipSecAuthType type)
73 return(NULL);
76 /* sip_sec API methods */
77 SipSecContext
78 sip_sec_create_context(SipSecAuthType type,
79 const int sso,
80 int is_connection_based,
81 const char *domain,
82 const char *username,
83 const char *password)
85 SipSecContext context = NULL;
87 /* Map authentication type to module initialization hook & name */
88 static sip_sec_create_context_func const auth_to_hook[] = {
89 sip_sec_create_context__NONE, /* AUTH_TYPE_UNSET */
90 sip_sec_create_context__NONE, /* AUTH_TYPE_DIGEST */
91 sip_sec_create_context__NTLM, /* AUTH_TYPE_NTLM */
92 sip_sec_create_context__Kerberos, /* AUTH_TYPE_KERBEROS */
93 sip_sec_create_context__Negotiate, /* AUTH_TYPE_NEGOTIATE */
96 context = (*(auth_to_hook[type]))(type);
97 if (context) {
98 sip_uint32 ret;
100 context->sso = sso;
101 context->is_connection_based = is_connection_based;
103 ret = (*context->acquire_cred_func)(context, domain, username, password);
104 if (ret != SIP_SEC_E_OK) {
105 purple_debug_info("sipe", "ERROR: sip_sec_init_context failed to acquire credentials.\n");
106 (*context->destroy_context_func)(context);
107 context = NULL;
111 return(context);
114 unsigned long
115 sip_sec_init_context_step(SipSecContext context,
116 const char *target,
117 const char *input_toked_base64,
118 char **output_toked_base64,
119 int *expires)
121 sip_uint32 ret = SIP_SEC_E_INTERNAL_ERROR;
123 if (context) {
124 SipSecBuffer in_buff = {0, NULL};
125 SipSecBuffer out_buff = {0, NULL};
126 char *tmp;
128 /* Not NULL for NTLM Type 2 */
129 if (input_toked_base64) {
130 in_buff.value = purple_base64_decode(input_toked_base64, &(in_buff.length));
132 tmp = sip_sec_ntlm_message_describe(in_buff);
133 if (tmp) {
134 purple_debug_info("sipe", "sip_sec_init_context_step: Challenge message is:\n%s", tmp);
136 g_free(tmp);
139 ret = (*context->init_context_func)(context, in_buff, &out_buff, target);
141 if (input_toked_base64)
142 g_free(in_buff.value);
144 if (ret == SIP_SEC_E_OK || ret == SIP_SEC_I_CONTINUE_NEEDED) {
145 *output_toked_base64 = purple_base64_encode(out_buff.value, out_buff.length);
147 if (out_buff.length > 0 && out_buff.value) {
148 tmp = sip_sec_ntlm_message_describe(out_buff);
149 if (tmp) {
150 purple_debug_info("sipe", "sip_sec_init_context_step: Negotiate or Authenticate message is:\n%s", tmp);
152 g_free(tmp);
155 g_free(out_buff.value);
158 if (expires) {
159 *expires = context->expires;
163 return ret;
166 char *
167 sip_sec_init_context(SipSecContext *context,
168 int *expires,
169 SipSecAuthType type,
170 const int sso,
171 const char *domain,
172 const char *username,
173 const char *password,
174 const char *target,
175 const char *input_toked_base64)
177 sip_uint32 ret;
178 char *output_toked_base64 = NULL;
179 int exp;
181 *context = sip_sec_create_context(type,
182 sso,
183 0, /* Connectionless for SIP */
184 domain,
185 username,
186 password);
187 if (!*context) {
188 purple_debug_info("sipe", "ERROR: sip_sec_init_context: failed sip_sec_create_context()\n");
189 return NULL;
192 ret = sip_sec_init_context_step(*context,
193 target,
194 NULL,
195 &output_toked_base64,
196 &exp);
198 /* for NTLM type 3 */
199 if (ret == SIP_SEC_I_CONTINUE_NEEDED) {
200 g_free(output_toked_base64);
201 ret = sip_sec_init_context_step(*context,
202 target,
203 input_toked_base64,
204 &output_toked_base64,
205 &exp);
208 if (expires) {
209 *expires = exp;
212 return output_toked_base64;
215 void
216 sip_sec_destroy_context(SipSecContext context)
218 if (context) (*context->destroy_context_func)(context);
221 char * sip_sec_make_signature(SipSecContext context, const char *message)
223 SipSecBuffer signature;
224 char *signature_hex;
226 if(((*context->make_signature_func)(context, message, &signature)) != SIP_SEC_E_OK) {
227 purple_debug_info("sipe", "ERROR: sip_sec_make_signature failed. Unable to sign message!\n");
228 return NULL;
230 signature_hex = buff_to_hex_str(signature.value, signature.length);
231 g_free(signature.value);
232 return signature_hex;
235 int sip_sec_verify_signature(SipSecContext context, const char *message, const char *signature_hex)
237 SipSecBuffer signature;
238 sip_uint32 res;
240 purple_debug_info("sipe", "sip_sec_verify_signature: message is:%s signature to verify is:%s\n",
241 message ? message : "", signature_hex ? signature_hex : "");
243 if (!message || !signature_hex) return SIP_SEC_E_INTERNAL_ERROR;
245 signature.length = hex_str_to_buff(signature_hex, &signature.value);
246 res = (*context->verify_signature_func)(context, message, signature);
247 g_free(signature.value);
248 return res;
251 /* Initialize & Destroy */
252 void sip_sec_init(void)
254 sip_sec_init__ntlm();
257 void sip_sec_destroy(void)
259 sip_sec_destroy__ntlm();
263 Local Variables:
264 mode: c
265 c-file-style: "bsd"
266 indent-tabs-mode: t
267 tab-width: 8
268 End: