Merge branch 'mob' of git+ssh://repo.or.cz/srv/git/siplcs into mob
[siplcs.git] / src / core / sip-sec.c
blob879d07bdc190dfdcb64653cfbc679ba033f3409d
1 /**
2 * @file sip-sec.c
4 * pidgin-sipe
6 * Copyright (C) 2010 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
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <time.h>
34 #include <glib.h>
36 #include "sipe-common.h"
37 #include "sip-sec.h"
38 #include "sipe-backend.h"
39 #include "sipe-utils.h"
41 #include "sip-sec-mech.h"
42 #include "sip-sec-ntlm.h"
43 #ifndef _WIN32
44 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
45 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
47 #ifdef HAVE_LIBKRB5
48 #include "sip-sec-krb5.h"
49 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
50 #else
51 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
52 #endif
54 #else /* _WIN32 */
55 #ifdef HAVE_LIBKRB5
56 #include "sip-sec-sspi.h"
57 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
58 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
59 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
60 #else /* HAVE_LIBKRB5 */
61 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
62 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
63 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
64 #endif /* HAVE_LIBKRB5 */
66 #endif /* _WIN32 */
68 /* Dummy initialization hook */
69 static SipSecContext
70 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type)
72 return(NULL);
75 /* sip_sec API methods */
76 SipSecContext
77 sip_sec_create_context(guint type,
78 const int sso,
79 int is_connection_based,
80 const char *domain,
81 const char *username,
82 const char *password)
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);
96 if (context) {
97 sip_uint32 ret;
99 context->sso = sso;
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 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context failed to acquire credentials.");
105 (*context->destroy_context_func)(context);
106 context = NULL;
110 return(context);
113 unsigned long
114 sip_sec_init_context_step(SipSecContext context,
115 const char *target,
116 const char *input_toked_base64,
117 char **output_toked_base64,
118 int *expires)
120 sip_uint32 ret = SIP_SEC_E_INTERNAL_ERROR;
122 if (context) {
123 SipSecBuffer in_buff = {0, NULL};
124 SipSecBuffer out_buff = {0, NULL};
125 char *tmp;
127 /* Not NULL for NTLM Type 2 */
128 if (input_toked_base64) {
129 in_buff.value = g_base64_decode(input_toked_base64, &in_buff.length);
131 tmp = sip_sec_ntlm_message_describe(in_buff);
132 if (tmp) {
133 SIPE_DEBUG_INFO("sip_sec_init_context_step: Challenge message is:\n%s", tmp);
135 g_free(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) {
145 if (out_buff.length > 0 && out_buff.value) {
146 *output_toked_base64 = g_base64_encode(out_buff.value, out_buff.length);
147 tmp = sip_sec_ntlm_message_describe(out_buff);
148 if (tmp) {
149 SIPE_DEBUG_INFO("sip_sec_init_context_step: Negotiate or Authenticate message is:\n%s", tmp);
151 g_free(tmp);
152 } else {
153 *output_toked_base64 = NULL;
156 g_free(out_buff.value);
159 if (expires) {
160 *expires = context->expires;
164 return ret;
167 char *
168 sip_sec_init_context(SipSecContext *context,
169 int *expires,
170 guint type,
171 const int sso,
172 const char *domain,
173 const char *username,
174 const char *password,
175 const char *target,
176 const char *input_toked_base64)
178 sip_uint32 ret;
179 char *output_toked_base64 = NULL;
180 int exp;
182 *context = sip_sec_create_context(type,
183 sso,
184 0, /* Connectionless for SIP */
185 domain,
186 username,
187 password);
188 if (!*context) {
189 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context: failed sip_sec_create_context()");
190 return NULL;
193 ret = sip_sec_init_context_step(*context,
194 target,
195 NULL,
196 &output_toked_base64,
197 &exp);
199 /* for NTLM type 3 */
200 if (ret == SIP_SEC_I_CONTINUE_NEEDED) {
201 g_free(output_toked_base64);
202 ret = sip_sec_init_context_step(*context,
203 target,
204 input_toked_base64,
205 &output_toked_base64,
206 &exp);
209 if (expires) {
210 *expires = exp;
213 return output_toked_base64;
216 void
217 sip_sec_destroy_context(SipSecContext context)
219 if (context) (*context->destroy_context_func)(context);
222 char * sip_sec_make_signature(SipSecContext context, const char *message)
224 SipSecBuffer signature;
225 char *signature_hex;
227 if(((*context->make_signature_func)(context, message, &signature)) != SIP_SEC_E_OK) {
228 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
229 return NULL;
231 signature_hex = buff_to_hex_str(signature.value, signature.length);
232 g_free(signature.value);
233 return signature_hex;
236 int sip_sec_verify_signature(SipSecContext context, const char *message, const char *signature_hex)
238 SipSecBuffer signature;
239 sip_uint32 res;
241 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
242 message ? message : "", signature_hex ? signature_hex : "");
244 if (!message || !signature_hex) return SIP_SEC_E_INTERNAL_ERROR;
246 signature.length = hex_str_to_buff(signature_hex, &signature.value);
247 res = (*context->verify_signature_func)(context, message, signature);
248 g_free(signature.value);
249 return res;
252 /* Initialize & Destroy */
253 void sip_sec_init(void)
255 sip_sec_init__ntlm();
258 void sip_sec_destroy(void)
260 sip_sec_destroy__ntlm();
264 Local Variables:
265 mode: c
266 c-file-style: "bsd"
267 indent-tabs-mode: t
268 tab-width: 8
269 End: