core: move SIP transport auth type to public API
[siplcs.git] / src / core / sip-sec.c
blob362e77bbd78a768bd1af5035ca1261271e04b227
1 /**
2 * @file sip-sec.c
4 * pidgin-sipe
6 * Copyright (C) 2010-12 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 #ifndef _WIN32
43 #include "sip-sec-ntlm.h"
44 #include "sip-sec-tls-dsk.h"
45 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
46 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
47 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
49 #ifdef HAVE_LIBKRB5
50 #include "sip-sec-krb5.h"
51 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
52 #else
53 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
54 #endif
56 #else /* _WIN32 */
57 #ifdef HAVE_SSPI
58 #include "sip-sec-sspi.h"
59 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
60 #define sip_sec_create_context__Negotiate sip_sec_create_context__sspi
61 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
62 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__sspi
63 #else /* !HAVE_SSPI */
64 #include "sip-sec-ntlm.h"
65 #include "sip-sec-tls-dsk.h"
66 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
67 #define sip_sec_create_context__Negotiate sip_sec_create_context__NONE
68 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
69 #define sip_sec_create_context__TLS_DSK sip_sec_create_context__tls_dsk
70 #endif /* HAVE_SSPI */
72 #endif /* _WIN32 */
74 /* Dummy initialization hook */
75 static SipSecContext
76 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER guint type)
78 return(NULL);
81 /* sip_sec API methods */
82 SipSecContext
83 sip_sec_create_context(guint type,
84 const int sso,
85 int is_connection_based,
86 const char *domain,
87 const char *username,
88 const char *password)
90 SipSecContext context = NULL;
92 /* Map authentication type to module initialization hook & name */
93 static sip_sec_create_context_func const auth_to_hook[] = {
94 sip_sec_create_context__NONE, /* SIPE_AUTHENTICATION_TYPE_UNSET */
95 sip_sec_create_context__NTLM, /* SIPE_AUTHENTICATION_TYPE_NTLM */
96 sip_sec_create_context__Kerberos, /* SIPE_AUTHENTICATION_TYPE_KERBEROS */
97 sip_sec_create_context__Negotiate, /* SIPE_AUTHENTICATION_TYPE_NEGOTIATE */
98 sip_sec_create_context__TLS_DSK, /* SIPE_AUTHENTICATION_TYPE_TLS_DSK */
101 context = (*(auth_to_hook[type]))(type);
102 if (context) {
103 sip_uint32 ret;
105 context->sso = sso;
106 context->is_connection_based = is_connection_based;
107 context->is_ready = TRUE;
109 ret = (*context->acquire_cred_func)(context, domain, username, password);
110 if (ret != SIP_SEC_E_OK) {
111 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context failed to acquire credentials.");
112 (*context->destroy_context_func)(context);
113 context = NULL;
117 return(context);
120 unsigned long
121 sip_sec_init_context_step(SipSecContext context,
122 const char *target,
123 const char *input_toked_base64,
124 char **output_toked_base64,
125 int *expires)
127 sip_uint32 ret = SIP_SEC_E_INTERNAL_ERROR;
129 if (context) {
130 SipSecBuffer in_buff = {0, NULL};
131 SipSecBuffer out_buff = {0, NULL};
133 /* Not NULL for NTLM Type 2 or TLS-DSK */
134 if (input_toked_base64)
135 in_buff.value = g_base64_decode(input_toked_base64, &in_buff.length);
137 ret = (*context->init_context_func)(context, in_buff, &out_buff, target);
139 if (input_toked_base64)
140 g_free(in_buff.value);
142 if (ret == SIP_SEC_E_OK || ret == SIP_SEC_I_CONTINUE_NEEDED) {
144 if (out_buff.length > 0 && out_buff.value) {
145 *output_toked_base64 = g_base64_encode(out_buff.value, out_buff.length);
146 } else {
147 *output_toked_base64 = NULL;
150 g_free(out_buff.value);
153 if (expires) {
154 *expires = context->expires;
158 return ret;
161 char *
162 sip_sec_init_context(SipSecContext *context,
163 int *expires,
164 guint type,
165 const int sso,
166 const char *domain,
167 const char *username,
168 const char *password,
169 const char *target,
170 const char *input_toked_base64)
172 sip_uint32 ret;
173 char *output_toked_base64 = NULL;
174 int exp;
176 *context = sip_sec_create_context(type,
177 sso,
178 0, /* Connectionless for SIP */
179 domain,
180 username,
181 password);
182 if (!*context) {
183 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context: failed sip_sec_create_context()");
184 return NULL;
187 ret = sip_sec_init_context_step(*context,
188 target,
189 NULL,
190 &output_toked_base64,
191 &exp);
193 /* for NTLM type 3 */
194 if (ret == SIP_SEC_I_CONTINUE_NEEDED) {
195 g_free(output_toked_base64);
196 ret = sip_sec_init_context_step(*context,
197 target,
198 input_toked_base64,
199 &output_toked_base64,
200 &exp);
203 if (expires) {
204 *expires = exp;
207 return output_toked_base64;
210 gboolean sip_sec_context_is_ready(SipSecContext context)
212 return(context && (context->is_ready != 0));
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 SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
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 SIPE_DEBUG_INFO("sip_sec_verify_signature: message is:%s signature to verify is:%s",
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 #ifndef HAVE_SSPI
255 sip_sec_init__ntlm();
256 #endif
259 void sip_sec_destroy(void)
261 #ifndef HAVE_SSPI
262 sip_sec_destroy__ntlm();
263 #endif
267 Local Variables:
268 mode: c
269 c-file-style: "bsd"
270 indent-tabs-mode: t
271 tab-width: 8
272 End: