2 * @file sip-sec-negotiate.c
6 * Copyright (C) 2013 SIPE Project <http://sipe.sourceforge.net/>
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 * Implementation for HTTP "WWW-Authenticate: Negotiate" scheme.
25 * It is a wrapper that will always try Kerberos first and fall back to NTLM.
30 #include "sipe-common.h"
32 #include "sip-sec-mech.h"
33 #include "sip-sec-krb5.h"
34 #include "sip-sec-negotiate.h"
35 #include "sip-sec-ntlm.h"
36 #include "sipe-backend.h"
38 /* Security context for Negotiate */
39 typedef struct _context_negotiate
{
40 struct sip_sec_context common
;
42 const gchar
*username
;
43 const gchar
*password
;
48 #define SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK 0x80000000
50 static void sip_sec_negotiate_drop_krb5(context_negotiate context
)
53 context
->krb5
->destroy_context_func(context
->krb5
);
57 static void sip_sec_negotiate_copy_flags(context_negotiate ctx
,
58 SipSecContext context
)
60 context
->flags
= ctx
->common
.flags
;
63 static void sip_sec_negotiate_copy_settings(context_negotiate ctx
,
64 SipSecContext context
)
66 if (context
->flags
& SIP_SEC_FLAG_COMMON_READY
)
67 ctx
->common
.flags
|= SIP_SEC_FLAG_COMMON_READY
;
68 ctx
->common
.expires
= context
->expires
;
71 static gboolean
sip_sec_negotiate_ntlm_fallback(context_negotiate context
)
73 if (context
->common
.flags
& SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK
) {
74 SIPE_DEBUG_ERROR_NOFORMAT("sip_sec_negotiate_ntlm_fallback: forbidden");
78 sip_sec_negotiate_drop_krb5(context
);
79 sip_sec_negotiate_copy_flags(context
, context
->ntlm
);
81 return(context
->ntlm
->acquire_cred_func(context
->ntlm
,
87 /* sip-sec-mech.h API implementation for Negotiate */
90 sip_sec_acquire_cred__negotiate(SipSecContext context
,
92 const gchar
*username
,
93 const gchar
*password
)
95 context_negotiate ctx
= (context_negotiate
) context
;
98 SIPE_DEBUG_INFO_NOFORMAT("sip_sec_acquire_cred__negotiate: entering");
100 ctx
->domain
= domain
;
101 ctx
->username
= username
;
102 ctx
->password
= password
;
105 sip_sec_negotiate_copy_flags(ctx
, context
);
106 ret
= context
->acquire_cred_func(context
,
111 /* Kerberos failed -> fall back to NTLM immediately */
112 SIPE_DEBUG_INFO_NOFORMAT("sip_sec_acquire_cred__negotiate: fallback to NTLM");
113 ret
= sip_sec_negotiate_ntlm_fallback(ctx
);
120 sip_sec_init_sec_context__negotiate(SipSecContext context
,
121 SipSecBuffer in_buff
,
122 SipSecBuffer
*out_buff
,
123 const gchar
*service_name
)
125 context_negotiate ctx
= (context_negotiate
) context
;
128 SIPE_DEBUG_INFO_NOFORMAT("sip_sec_init_sec_context__negotiate: entering");
130 /* Kerberos available? */
133 ret
= context
->init_context_func(context
,
139 /* Kerberos failed -> fall back to NTLM */
140 SIPE_DEBUG_INFO_NOFORMAT("sip_sec_init_sec_context__negotiate: fallback to NTLM");
141 ret
= sip_sec_negotiate_ntlm_fallback(ctx
);
145 ret
= context
->init_context_func(context
,
151 /* Kerberos succeeded -> disable fallback to NTLM */
152 ctx
->common
.flags
|= SIP_SEC_FLAG_NEGOTIATE_DISABLE_FALLBACK
;
155 /* No Kerberos available -> use NTLM */
158 ret
= context
->init_context_func(context
,
164 /* context points to the last used child context */
166 sip_sec_negotiate_copy_settings(ctx
, context
);
172 sip_sec_make_signature__negotiate(SIPE_UNUSED_PARAMETER SipSecContext context
,
173 SIPE_UNUSED_PARAMETER
const gchar
*message
,
174 SIPE_UNUSED_PARAMETER SipSecBuffer
*signature
)
176 /* No implementation needed, as Negotiate is not used for SIP */
181 sip_sec_verify_signature__negotiate(SIPE_UNUSED_PARAMETER SipSecContext context
,
182 SIPE_UNUSED_PARAMETER
const gchar
*message
,
183 SIPE_UNUSED_PARAMETER SipSecBuffer signature
)
185 /* No implementation needed, as Negotiate is not used for SIP */
190 sip_sec_destroy_sec_context__negotiate(SipSecContext context
)
192 context_negotiate ctx
= (context_negotiate
) context
;
195 ctx
->ntlm
->destroy_context_func(ctx
->ntlm
);
196 sip_sec_negotiate_drop_krb5(ctx
);
201 sip_sec_create_context__negotiate(guint type
)
203 context_negotiate context
= NULL
;
204 SipSecContext krb5
= sip_sec_create_context__krb5(type
);
207 SipSecContext ntlm
= sip_sec_create_context__ntlm(type
);
210 context
= g_malloc0(sizeof(struct _context_negotiate
));
213 context
->common
.acquire_cred_func
= sip_sec_acquire_cred__negotiate
;
214 context
->common
.init_context_func
= sip_sec_init_sec_context__negotiate
;
215 context
->common
.destroy_context_func
= sip_sec_destroy_sec_context__negotiate
;
216 context
->common
.make_signature_func
= sip_sec_make_signature__negotiate
;
217 context
->common
.verify_signature_func
= sip_sec_verify_signature__negotiate
;
218 context
->krb5
= krb5
;
219 context
->ntlm
= ntlm
;
221 ntlm
->destroy_context_func(ntlm
);
226 krb5
->destroy_context_func(krb5
);
230 return((SipSecContext
) context
);