1 From df22702d72d30843193d98589fee090f2fe63201 Mon Sep 17 00:00:00 2001
2 From: Pete Fotheringham <pete.fotheringham@codethink.co.uk>
3 Date: Thu, 29 Dec 2011 09:12:51 +0000
4 Subject: [PATCH] Move moonshot files up
8 acinclude.m4 | 364 ++++++++++
10 build-aux/compile | 144 ++++
13 mech_eap.spec.in | 62 ++
14 mech_eap/.gitignore | 32 +
15 mech_eap/AUTHORS | 6 +
16 mech_eap/COPYING | 3 +
17 mech_eap/LICENSE | 31 +
18 mech_eap/Makefile.am | 189 ++++++
20 mech_eap/README | 147 ++++
21 mech_eap/README.samba4 | 52 ++
23 mech_eap/accept_sec_context.c | 1072 +++++++++++++++++++++++++++++
24 mech_eap/acquire_cred.c | 52 ++
25 mech_eap/acquire_cred_with_password.c | 67 ++
26 mech_eap/add_cred.c | 87 +++
27 mech_eap/add_cred_with_password.c | 93 +++
28 mech_eap/authdata_plugin.h | 331 +++++++++
29 mech_eap/authorize_localname.c | 54 ++
30 mech_eap/canonicalize_name.c | 64 ++
31 mech_eap/compare_name.c | 46 ++
32 mech_eap/context_time.c | 69 ++
33 mech_eap/delete_name_attribute.c | 60 ++
34 mech_eap/delete_sec_context.c | 81 +++
35 mech_eap/dictionary.ukerna | 20 +
36 mech_eap/display_name.c | 48 ++
37 mech_eap/display_name_ext.c | 51 ++
38 mech_eap/display_status.c | 203 ++++++
39 mech_eap/duplicate_name.c | 60 ++
40 mech_eap/eap_mech.c | 219 ++++++
41 mech_eap/exchange_meta_data.c | 82 +++
42 mech_eap/export_name.c | 60 ++
43 mech_eap/export_name_composite.c | 62 ++
44 mech_eap/export_sec_context.c | 246 +++++++
45 mech_eap/get_mic.c | 89 +++
46 mech_eap/get_name_attribute.c | 67 ++
47 mech_eap/gssapiP_eap.h | 410 +++++++++++
48 mech_eap/gssapi_eap.h | 90 +++
49 mech_eap/gsseap_err.et | 162 +++++
50 mech_eap/import_name.c | 47 ++
51 mech_eap/import_sec_context.c | 374 ++++++++++
52 mech_eap/indicate_mechs.c | 44 ++
53 mech_eap/init_sec_context.c | 1097 ++++++++++++++++++++++++++++++
54 mech_eap/inquire_attrs_for_mech.c | 137 ++++
55 mech_eap/inquire_context.c | 116 ++++
56 mech_eap/inquire_cred.c | 61 ++
57 mech_eap/inquire_cred_by_mech.c | 76 +++
58 mech_eap/inquire_cred_by_oid.c | 83 +++
59 mech_eap/inquire_mech_for_saslname.c | 84 +++
60 mech_eap/inquire_mechs_for_name.c | 69 ++
61 mech_eap/inquire_name.c | 75 ++
62 mech_eap/inquire_names_for_mech.c | 77 +++
63 mech_eap/inquire_saslname_for_mech.c | 51 ++
64 mech_eap/inquire_sec_context_by_oid.c | 248 +++++++
65 mech_eap/install-sh | 520 ++++++++++++++
66 mech_eap/map_name_to_any.c | 58 ++
68 mech_eap/mech_eap-noacceptor.exports | 55 ++
69 mech_eap/mech_eap.exports | 63 ++
70 mech_eap/mech_invoke.c | 44 ++
71 mech_eap/process_context_token.c | 71 ++
72 mech_eap/pseudo_random.c | 195 ++++++
73 mech_eap/query_mechanism_info.c | 67 ++
74 mech_eap/query_meta_data.c | 116 ++++
75 mech_eap/radius_ad.exports | 1 +
76 mech_eap/radsec.conf | 12 +
77 mech_eap/radsec_err.et | 38 +
78 mech_eap/release_any_name_mapping.c | 59 ++
79 mech_eap/release_cred.c | 44 ++
80 mech_eap/release_name.c | 44 ++
81 mech_eap/release_oid.c | 44 ++
82 mech_eap/set_cred_option.c | 208 ++++++
83 mech_eap/set_name_attribute.c | 60 ++
84 mech_eap/set_sec_context_option.c | 87 +++
85 mech_eap/store_cred.c | 83 +++
86 mech_eap/unwrap.c | 85 +++
87 mech_eap/unwrap_iov.c | 572 ++++++++++++++++
88 mech_eap/util.h | 1032 ++++++++++++++++++++++++++++
89 mech_eap/util_adshim.c | 242 +++++++
90 mech_eap/util_attr.cpp | 1191 ++++++++++++++++++++++++++++++++
91 mech_eap/util_attr.h | 389 +++++++++++
92 mech_eap/util_base64.c | 161 +++++
93 mech_eap/util_base64.h | 58 ++
94 mech_eap/util_buffer.c | 103 +++
95 mech_eap/util_cksum.c | 242 +++++++
96 mech_eap/util_context.c | 377 +++++++++++
97 mech_eap/util_cred.c | 756 +++++++++++++++++++++
98 mech_eap/util_crypt.c | 397 +++++++++++
99 mech_eap/util_json.cpp | 513 ++++++++++++++
100 mech_eap/util_json.h | 182 +++++
101 mech_eap/util_krb.c | 632 +++++++++++++++++
102 mech_eap/util_lucid.c | 183 +++++
103 mech_eap/util_mech.c | 380 +++++++++++
104 mech_eap/util_moonshot.c | 238 +++++++
105 mech_eap/util_name.c | 789 ++++++++++++++++++++++
106 mech_eap/util_oid.c | 206 ++++++
107 mech_eap/util_ordering.c | 302 +++++++++
108 mech_eap/util_radius.cpp | 899 +++++++++++++++++++++++++
109 mech_eap/util_radius.h | 183 +++++
110 mech_eap/util_reauth.c | 1196 +++++++++++++++++++++++++++++++++
111 mech_eap/util_reauth.h | 151 +++++
112 mech_eap/util_saml.cpp | 775 +++++++++++++++++++++
113 mech_eap/util_saml.h | 176 +++++
114 mech_eap/util_shib.cpp | 555 +++++++++++++++
115 mech_eap/util_shib.h | 122 ++++
116 mech_eap/util_sm.c | 372 ++++++++++
117 mech_eap/util_tld.c | 167 +++++
118 mech_eap/util_token.c | 493 ++++++++++++++
119 mech_eap/verify_mic.c | 71 ++
120 mech_eap/wrap.c | 137 ++++
121 mech_eap/wrap_iov.c | 379 +++++++++++
122 mech_eap/wrap_iov_length.c | 234 +++++++
123 mech_eap/wrap_size_limit.c | 97 +++
124 117 files changed, 24690 insertions(+), 0 deletions(-)
125 create mode 100644 Makefile.am
126 create mode 100644 acinclude.m4
127 create mode 100755 autogen.sh
128 create mode 100755 build-aux/compile
129 create mode 100644 configure.ac
130 create mode 100644 m4/minuso.m4
131 create mode 100644 mech_eap.spec.in
132 create mode 100644 mech_eap/.gitignore
133 create mode 100644 mech_eap/AUTHORS
134 create mode 100644 mech_eap/COPYING
135 create mode 100644 mech_eap/LICENSE
136 create mode 100644 mech_eap/Makefile.am
137 create mode 100644 mech_eap/NEWS
138 create mode 100644 mech_eap/NOTES
139 create mode 100644 mech_eap/README
140 create mode 100644 mech_eap/README.samba4
141 create mode 100644 mech_eap/TODO
142 create mode 100644 mech_eap/accept_sec_context.c
143 create mode 100644 mech_eap/acquire_cred.c
144 create mode 100644 mech_eap/acquire_cred_with_password.c
145 create mode 100644 mech_eap/add_cred.c
146 create mode 100644 mech_eap/add_cred_with_password.c
147 create mode 100644 mech_eap/authdata_plugin.h
148 create mode 100644 mech_eap/authorize_localname.c
149 create mode 100644 mech_eap/canonicalize_name.c
150 create mode 100644 mech_eap/compare_name.c
151 create mode 100644 mech_eap/context_time.c
152 create mode 100644 mech_eap/delete_name_attribute.c
153 create mode 100644 mech_eap/delete_sec_context.c
154 create mode 100644 mech_eap/dictionary.ukerna
155 create mode 100644 mech_eap/display_name.c
156 create mode 100644 mech_eap/display_name_ext.c
157 create mode 100644 mech_eap/display_status.c
158 create mode 100644 mech_eap/duplicate_name.c
159 create mode 100644 mech_eap/eap_mech.c
160 create mode 100644 mech_eap/exchange_meta_data.c
161 create mode 100644 mech_eap/export_name.c
162 create mode 100644 mech_eap/export_name_composite.c
163 create mode 100644 mech_eap/export_sec_context.c
164 create mode 100644 mech_eap/get_mic.c
165 create mode 100644 mech_eap/get_name_attribute.c
166 create mode 100644 mech_eap/gssapiP_eap.h
167 create mode 100644 mech_eap/gssapi_eap.h
168 create mode 100644 mech_eap/gsseap_err.et
169 create mode 100644 mech_eap/import_name.c
170 create mode 100644 mech_eap/import_sec_context.c
171 create mode 100644 mech_eap/indicate_mechs.c
172 create mode 100644 mech_eap/init_sec_context.c
173 create mode 100644 mech_eap/inquire_attrs_for_mech.c
174 create mode 100644 mech_eap/inquire_context.c
175 create mode 100644 mech_eap/inquire_cred.c
176 create mode 100644 mech_eap/inquire_cred_by_mech.c
177 create mode 100644 mech_eap/inquire_cred_by_oid.c
178 create mode 100644 mech_eap/inquire_mech_for_saslname.c
179 create mode 100644 mech_eap/inquire_mechs_for_name.c
180 create mode 100644 mech_eap/inquire_name.c
181 create mode 100644 mech_eap/inquire_names_for_mech.c
182 create mode 100644 mech_eap/inquire_saslname_for_mech.c
183 create mode 100644 mech_eap/inquire_sec_context_by_oid.c
184 create mode 100755 mech_eap/install-sh
185 create mode 100644 mech_eap/map_name_to_any.c
186 create mode 100644 mech_eap/mech
187 create mode 100644 mech_eap/mech_eap-noacceptor.exports
188 create mode 100644 mech_eap/mech_eap.exports
189 create mode 100644 mech_eap/mech_invoke.c
190 create mode 100644 mech_eap/process_context_token.c
191 create mode 100644 mech_eap/pseudo_random.c
192 create mode 100644 mech_eap/query_mechanism_info.c
193 create mode 100644 mech_eap/query_meta_data.c
194 create mode 100644 mech_eap/radius_ad.exports
195 create mode 100644 mech_eap/radsec.conf
196 create mode 100644 mech_eap/radsec_err.et
197 create mode 100644 mech_eap/release_any_name_mapping.c
198 create mode 100644 mech_eap/release_cred.c
199 create mode 100644 mech_eap/release_name.c
200 create mode 100644 mech_eap/release_oid.c
201 create mode 100644 mech_eap/set_cred_option.c
202 create mode 100644 mech_eap/set_name_attribute.c
203 create mode 100644 mech_eap/set_sec_context_option.c
204 create mode 100644 mech_eap/store_cred.c
205 create mode 100644 mech_eap/unwrap.c
206 create mode 100644 mech_eap/unwrap_iov.c
207 create mode 100644 mech_eap/util.h
208 create mode 100644 mech_eap/util_adshim.c
209 create mode 100644 mech_eap/util_attr.cpp
210 create mode 100644 mech_eap/util_attr.h
211 create mode 100644 mech_eap/util_base64.c
212 create mode 100644 mech_eap/util_base64.h
213 create mode 100644 mech_eap/util_buffer.c
214 create mode 100644 mech_eap/util_cksum.c
215 create mode 100644 mech_eap/util_context.c
216 create mode 100644 mech_eap/util_cred.c
217 create mode 100644 mech_eap/util_crypt.c
218 create mode 100644 mech_eap/util_json.cpp
219 create mode 100644 mech_eap/util_json.h
220 create mode 100644 mech_eap/util_krb.c
221 create mode 100644 mech_eap/util_lucid.c
222 create mode 100644 mech_eap/util_mech.c
223 create mode 100644 mech_eap/util_moonshot.c
224 create mode 100644 mech_eap/util_name.c
225 create mode 100644 mech_eap/util_oid.c
226 create mode 100644 mech_eap/util_ordering.c
227 create mode 100644 mech_eap/util_radius.cpp
228 create mode 100644 mech_eap/util_radius.h
229 create mode 100644 mech_eap/util_reauth.c
230 create mode 100644 mech_eap/util_reauth.h
231 create mode 100644 mech_eap/util_saml.cpp
232 create mode 100644 mech_eap/util_saml.h
233 create mode 100644 mech_eap/util_shib.cpp
234 create mode 100644 mech_eap/util_shib.h
235 create mode 100644 mech_eap/util_sm.c
236 create mode 100644 mech_eap/util_tld.c
237 create mode 100644 mech_eap/util_token.c
238 create mode 100644 mech_eap/verify_mic.c
239 create mode 100644 mech_eap/wrap.c
240 create mode 100644 mech_eap/wrap_iov.c
241 create mode 100644 mech_eap/wrap_iov_length.c
242 create mode 100644 mech_eap/wrap_size_limit.c
244 diff --git a/Makefile.am b/Makefile.am
246 index 0000000..f9690bd
250 +AUTOMAKE_OPTIONS = foreign
251 +ACLOCAL_AMFLAGS = -I m4
253 +EXTRA_DIST = mech_eap.spec
254 diff --git a/acinclude.m4 b/acinclude.m4
256 index 0000000..6f43261
260 +dnl Based on the one from the Boinc project by Reinhard
262 +AC_DEFUN([AX_CHECK_WINDOWS],
263 +[AC_MSG_CHECKING(for windows)
265 +AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
266 +AC_MSG_RESULT($target_windows)
267 +AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
270 +AC_DEFUN([AX_CHECK_KRB5],
271 +[AC_MSG_CHECKING(for GSS-API and Kerberos implementation)
275 + AC_HELP_STRING([--with-krb5],
276 + [Use krb5 (in specified installation directory)]),
277 + [check_krb5_dir="$withval"],
279 +for dir in $check_krb5_dir $prefix /usr/local /usr ; do
281 + if test -x "$dir/bin/krb5-config"; then
283 + if test "x$target_windows" = "xyes"; then
284 + KRB5_CFLAGS=-I"$check_krb5_dir/include";
285 + KRB5_LDFLAGS="-L$check_krb5_dir/lib/";
286 + KRB5_LIBS="-lkrb5_32 -lgssapi32";
287 + COMPILE_ET="$check_krb5_dir/bin/compile_et";
288 + AC_MSG_RESULT([yes])
290 + KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
291 + KRB5_LDFLAGS="-L$dir/lib";
292 + KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`
293 +AC_MSG_RESULT([yes])
294 + AC_PATH_PROG(COMPILE_ET, [compile_et], [compile_et], [$dir/bin$PATH_SEPARATOr])
299 +if test x_$found_krb5 != x_yes; then
300 + AC_MSG_RESULT($found_krb5)
302 +----------------------------------------------------------------------
303 + Cannot find GSS-API/Kerberos libraries.
305 + Please install MIT or Heimdal or specify installation directory with
307 +----------------------------------------------------------------------
310 + printf "Kerberos found in $krb5dir\n";
311 + AC_SUBST(KRB5_CFLAGS)
312 + AC_SUBST(KRB5_LDFLAGS)
313 + AC_SUBST(KRB5_LIBS)
314 + AC_SUBST(COMPILE_ET)
315 + AC_CHECK_LIB(krb5, GSS_C_NT_COMPOSITE_EXPORT, [AC_DEFINE_UNQUOTED([HAVE_GSS_C_NT_COMPOSITE_EXPORT], 1, [Define if GSS-API library supports recent naming extensions draft])], [], "$KRB5_LIBS")
316 + AC_CHECK_LIB(krb5, gss_inquire_attrs_for_mech, [AC_DEFINE_UNQUOTED([HAVE_GSS_INQUIRE_ATTRS_FOR_MECH], 1, [Define if GSS-API library supports RFC 5587])], [], "$KRB5_LIBS")
317 + AC_CHECK_LIB(krb5, gss_krb5_import_cred, [AC_DEFINE_UNQUOTED([HAVE_GSS_KRB5_IMPORT_CRED], 1, [Define if GSS-API library supports gss_krb5_import_cred])], [], "$KRB5_LIBS")
318 + AC_CHECK_LIB(krb5, heimdal_version, [AC_DEFINE_UNQUOTED([HAVE_HEIMDAL_VERSION], 1, [Define if building against Heimdal Kerberos implementation]), heimdal=yes], [heimdal=no], "$KRB5_LIBS")
319 + AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
323 +AC_DEFUN([AX_CHECK_EAP],
324 +[AC_MSG_CHECKING(for EAP implementation)
328 + AC_HELP_STRING([--with-eap],
329 + [Use eap (in specified installation directory)]),
330 + [check_eap_dir="$withval"],
332 +for dir in $check_eap_dir $prefix /usr /usr/local ../libeap ; do
334 + if test -f "$dir/src/eap_peer/eap.h"; then
336 + EAP_DIR="${eapdir}"
337 + EAP_CFLAGS="-I$eapdir/src/common -I$eapdir/src -I$eapdir/src/utils";
341 +AC_MSG_RESULT($found_eap)
342 +if test x_$found_eap != x_yes; then
344 +----------------------------------------------------------------------
345 + Cannot find EAP libraries.
347 + Please install wpa_supplicant or specify installation directory with
349 +----------------------------------------------------------------------
352 + printf "EAP found in $eapdir\n";
353 + EAP_CFLAGS="$EAP_CFLAGS \
367 +-DEAP_SERVER_IDENTITY \
372 +-DEAP_SERVER_MSCHAPV2 \
378 +-DEAP_SERVER_GPSK_SHA256 \
380 + EAP_LIBS="-leap -lutils -lcrypto -ltls";
381 + EAP_LDFLAGS="-L$eapdir/eap_example -L$eapdir/src/utils -L$eapdir/src/crypto -L$eapdir/src/tls";
382 + AC_SUBST(EAP_CFLAGS)
383 + AC_SUBST(EAP_LDFLAGS)
388 +AC_DEFUN([AX_CHECK_SHIBSP],
389 +[AC_MSG_CHECKING(for Shibboleth implementation)
393 + AC_HELP_STRING([--with-shibsp],
394 + [Use shibspboleth (in specified installation directory)]),
395 + [check_shibsp_dir="$withval"],
396 + [check_shibsp_dir=])
397 +for dir in $check_shibsp_dir $prefix /usr /usr/local ; do
399 + if test -f "$dir/include/shibsp/SPConfig.h"; then
400 + found_shibsp="yes";
401 + SHIBSP_DIR="${shibspdir}"
402 + SHIBSP_CXXFLAGS="-I$shibspdir/include";
406 +AC_MSG_RESULT($found_shibsp)
407 +if test x_$found_shibsp != x_yes; then
409 +----------------------------------------------------------------------
410 + Cannot find Shibboleth libraries.
412 + Please install Shibboleth or specify installation directory with
413 + --with-shibsp=(dir).
414 +----------------------------------------------------------------------
417 + printf "Shibboleth found in $shibspdir\n";
418 + SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
419 + SHIBSP_LDFLAGS="-L$shibspdir/lib";
420 + AC_SUBST(SHIBSP_CXXFLAGS)
421 + AC_SUBST(SHIBSP_LDFLAGS)
422 + AC_SUBST(SHIBSP_LIBS)
423 + AC_DEFINE_UNQUOTED([HAVE_SHIBSP], 1, [Define is Shibboleth SP is available])
427 +AC_DEFUN([AX_CHECK_SHIBRESOLVER],
428 +[AC_MSG_CHECKING(for Shibboleth resolver implementation)
430 +found_shibresolver="no"
431 +AC_ARG_WITH(shibresolver,
432 + AC_HELP_STRING([--with-shibresolver],
433 + [Use Shibboleth resolver (in specified installation directory)]),
434 + [check_shibresolver_dir="$withval"],
435 + [check_shibresolver_dir=])
436 +if test x_$check_shibresolver_dir != x_no; then
437 +for dir in $check_shibresolver_dir $prefix /usr /usr/local ; do
438 + shibresolverdir="$dir"
439 + if test -f "$dir/include/shibresolver/resolver.h"; then
440 + found_shibresolver="yes";
441 + SHIBRESOLVER_DIR="${shibresolverdir}"
442 + SHIBRESOLVER_CXXFLAGS="-I$shibresolverdir/include";
447 +AC_MSG_RESULT($found_shibresolver)
448 +if test x_$check_shibresolver_dir != x_no; then
449 +if test x_$found_shibresolver != x_yes; then
451 +----------------------------------------------------------------------
452 + Cannot find Shibboleth resolver libraries, building without
453 + Shibboleth support.
455 + Please install Shibboleth or specify installation directory with
456 + --with-shibresolver=(dir).
457 +----------------------------------------------------------------------
460 + printf "Shibboleth resolver found in $shibresolverdir\n";
461 + SHIBRESOLVER_LIBS="-lshibresolver";
462 + SHIBRESOLVER_LDFLAGS="-L$shibresolverdir/lib";
463 + AC_SUBST(SHIBRESOLVER_CXXFLAGS)
464 + AC_SUBST(SHIBRESOLVER_LDFLAGS)
465 + AC_SUBST(SHIBRESOLVER_LIBS)
466 + AC_DEFINE_UNQUOTED([HAVE_SHIBRESOLVER], 1, [Define is Shibboleth resolver is available])
471 +AC_DEFUN([AX_CHECK_OPENSAML],
472 +[AC_MSG_CHECKING(for OpenSAML implementation)
475 +AC_ARG_WITH(opensaml,
476 + AC_HELP_STRING([--with-opensaml],
477 + [Use OpenSAML (in specified installation directory)]),
478 + [check_opensaml_dir="$withval"],
479 + [check_opensaml_dir=])
480 +if test x_$check_opensaml_dir != x_no; then
481 +for dir in $check_opensaml_dir $prefix /usr /usr/local ; do
483 + if test -f "$dir/include/saml/Assertion.h"; then
484 + found_opensaml="yes";
485 + OPENSAML_DIR="${opensamldir}"
486 + OPENSAML_CXXFLAGS="-I$opensamldir/include";
491 +AC_MSG_RESULT($found_opensaml)
492 +if test x_$check_opensaml_dir != x_no; then
493 +if test x_$found_opensaml != x_yes; then
495 +----------------------------------------------------------------------
496 + Cannot find OpenSAML libraries, building without OpenSAML support.
498 + Please install OpenSAML or specify installation directory with
499 + --with-opensaml=(dir).
500 +----------------------------------------------------------------------
503 + printf "OpenSAML found in $opensamldir\n";
504 + OPENSAML_LIBS="-lsaml -lxml-security-c -lxmltooling -lxerces-c";
505 + OPENSAML_LDFLAGS="-L$opensamldir/lib";
506 + AC_SUBST(OPENSAML_CXXFLAGS)
507 + AC_SUBST(OPENSAML_LDFLAGS)
508 + AC_SUBST(OPENSAML_LIBS)
509 + AC_DEFINE_UNQUOTED([HAVE_OPENSAML], 1, [Define is OpenSAML is available])
514 +AC_DEFUN([AX_CHECK_RADSEC],
515 +[AC_MSG_CHECKING(for radsec)
519 + AC_HELP_STRING([--with-radsec],
520 + [Use radsec (in specified installation directory)]),
521 + [check_radsec_dir="$withval"],
522 + [check_radsec_dir=])
523 +for dir in $check_radsec_dir $prefix /usr /usr/local ; do
525 + if test -f "$dir/include/radsec/radsec.h"; then
526 + found_radsec="yes";
527 + RADSEC_DIR="${radsecdir}"
528 + RADSEC_CFLAGS="-I$radsecdir/include";
532 +AC_MSG_RESULT($found_radsec)
533 +if test x_$found_radsec != x_yes; then
535 +----------------------------------------------------------------------
536 + Cannot find radsec libraries.
538 + Please install libradsec or specify installation directory with
539 + --with-radsec=(dir).
540 +----------------------------------------------------------------------
543 + printf "radsec found in $radsecdir\n";
544 + RADSEC_LIBS="-lradsec";
545 + RADSEC_LDFLAGS="-L$radsecdir/lib";
546 + AC_SUBST(RADSEC_CFLAGS)
547 + AC_SUBST(RADSEC_LDFLAGS)
548 + AC_SUBST(RADSEC_LIBS)
552 +AC_DEFUN([AX_CHECK_JANSSON],
553 +[AC_MSG_CHECKING(for jansson)
556 +AC_ARG_WITH(jansson,
557 + AC_HELP_STRING([--with-jansson],
558 + [Use jansson (in specified installation directory)]),
559 + [check_jansson_dir="$withval"],
560 + [check_jansson_dir=])
561 +for dir in $check_jansson_dir $prefix /usr /usr/local ; do
563 + if test -f "$dir/include/jansson.h"; then
564 + found_jansson="yes";
565 + JANSSON_DIR="${janssondir}"
566 + JANSSON_CFLAGS="-I$janssondir/include";
570 +AC_MSG_RESULT($found_jansson)
571 +if test x_$found_jansson != x_yes; then
573 +----------------------------------------------------------------------
574 + Cannot find jansson libraries.
576 + Please install libjansson or specify installation directory with
577 + --with-jansson=(dir).
578 +----------------------------------------------------------------------
581 + printf "jansson found in $janssondir\n";
582 + JANSSON_LIBS="-ljansson";
583 + JANSSON_LDFLAGS="-L$janssondir/lib";
584 + AC_SUBST(JANSSON_CFLAGS)
585 + AC_SUBST(JANSSON_LDFLAGS)
586 + AC_SUBST(JANSSON_LIBS)
590 +AC_DEFUN([AX_CHECK_LIBMOONSHOT],
591 +[AC_MSG_CHECKING(for Moonshot identity selector implementation)
594 +LIBMOONSHOT_LDFLAGS=
596 +found_libmoonshot="no"
597 +AC_ARG_WITH(libmoonshot,
598 + AC_HELP_STRING([--with-libmoonshot],
599 + [Use libmoonshot (in specified installation directory)]),
600 + [check_libmoonshot_dir="$withval"],
601 + [check_libmoonshot_dir=])
602 +for dir in $check_libmoonshot_dir $prefix /usr /usr/local ; do
603 + libmoonshotdir="$dir"
604 + if test -f "$dir/include/libmoonshot.h"; then
605 + found_libmoonshot="yes";
606 + LIBMOONSHOT_DIR="${libmoonshotdir}"
607 + LIBMOONSHOT_CFLAGS="-I$libmoonshotdir/include";
611 +AC_MSG_RESULT($found_libmoonshot)
612 +if test x_$found_libmoonshot = x_yes; then
613 + printf "libmoonshot found in $libmoonshotdir\n";
614 + LIBMOONSHOT_LIBS="-lmoonshot";
615 + LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
616 + AC_CHECK_LIB(moonshot, moonshot_get_identity, [AC_DEFINE_UNQUOTED([HAVE_MOONSHOT_GET_IDENTITY], 1, [Define if Moonshot identity selector is available])], [], "$LIBMOONSHOT_LIBS")
618 + AC_SUBST(LIBMOONSHOT_CFLAGS)
619 + AC_SUBST(LIBMOONSHOT_LDFLAGS)
620 + AC_SUBST(LIBMOONSHOT_LIBS)
621 + AM_CONDITIONAL(LIBMOONSHOT, test "x$found_libmoonshot" != "xno")
624 diff --git a/autogen.sh b/autogen.sh
626 index 0000000..13432d0
632 +# Regenerate autotools files.
635 +PATH=/usr/local/bin:$PATH
637 +if [ -x "`which autoreconf 2>/dev/null`" ] ; then
638 + exec autoreconf -ivf
641 +aclocal -I . -I m4 && \
643 + libtoolize --automake -c && \
645 + automake --add-missing --copy
646 diff --git a/build-aux/compile b/build-aux/compile
648 index 0000000..5360806
650 +++ b/build-aux/compile
653 +# Wrapper for compilers which do not understand `-c -o'.
655 +scriptversion=2009-10-06.20; # UTC
657 +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software
659 +# Written by Tom Tromey <tromey@cygnus.com>.
661 +# This program is free software; you can redistribute it and/or modify
662 +# it under the terms of the GNU General Public License as published by
663 +# the Free Software Foundation; either version 2, or (at your option)
664 +# any later version.
666 +# This program is distributed in the hope that it will be useful,
667 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
668 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
669 +# GNU General Public License for more details.
671 +# You should have received a copy of the GNU General Public License
672 +# along with this program; if not, write to the Free Software
673 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
675 +# As a special exception to the GNU General Public License, if you
676 +# distribute this file as part of a program that contains a
677 +# configuration script generated by Autoconf, you may include it under
678 +# the same distribution terms that you use for the rest of that program.
680 +# This file is maintained in Automake, please report
681 +# bugs to <bug-automake@gnu.org> or send patches to
682 +# <automake-patches@gnu.org>.
686 + echo "$0: No command. Try \`$0 --help' for more information." 1>&2
691 +Usage: compile [--help] [--version] PROGRAM [ARGS]
693 +Wrapper for compilers which do not understand `-c -o'.
694 +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
695 +arguments, and rename the output as expected.
697 +If you are trying to build a whole package this is not the
698 +right script to run: please start by reading the file `INSTALL'.
700 +Report bugs to <bug-automake@gnu.org>.
705 + echo "compile $scriptversion"
716 + if test -n "$eat"; then
721 + # configure might choose to run compile as `compile cc -o foo foo.c'.
722 + # So we strip `-o arg' only if arg is an object.
748 +if test -z "$ofile" || test -z "$cfile"; then
749 + # If no `-o' option was seen then we might have been invoked from a
750 + # pattern rule where we don't need one. That is ok -- this is a
751 + # normal compilation that the losing compiler can handle. If no
752 + # `.c' file was seen then we are probably linking. That is also
757 +# Name of file we expect compiler to create.
758 +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
760 +# Create the lock directory.
761 +# Note: use `[/\\:.-]' here to ensure that we don't use the same name
762 +# that we are using for the .o file. Also, base the name on the expected
763 +# object file name, since that is what matters with a parallel build.
764 +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
766 + if mkdir "$lockdir" >/dev/null 2>&1; then
771 +# FIXME: race condition here if user kills between mkdir and trap.
772 +trap "rmdir '$lockdir'; exit 1" 1 2 15
778 +if test -f "$cofile"; then
779 + test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
780 +elif test -f "${cofile}bj"; then
781 + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
788 +# mode: shell-script
790 +# eval: (add-hook 'write-file-hooks 'time-stamp)
791 +# time-stamp-start: "scriptversion="
792 +# time-stamp-format: "%:y-%02m-%02d.%02H"
793 +# time-stamp-time-zone: "UTC"
794 +# time-stamp-end: "; # UTC"
796 diff --git a/configure.ac b/configure.ac
798 index 0000000..ba23c32
803 +AC_INIT([mech_eap], [0.1], [bugs@project-moonshot.org])
804 +AC_CONFIG_MACRO_DIR([m4])
805 +AC_CONFIG_AUX_DIR([build-aux])
807 +dnl AM_INIT_AUTOMAKE([silent-rules])
808 +AC_USE_SYSTEM_EXTENSIONS
811 +AM_MAINTAINER_MODE()
813 +LT_INIT([dlopen disable-static win32-dll])
817 +AC_CONFIG_HEADERS([config.h])
818 +AC_CHECK_HEADERS(stdarg.h stdio.h stdint.h sys/param.h)
819 +AC_REPLACE_FUNCS(vasprintf)
821 +dnl Check if we're on Solaris and set CFLAGS accordingly
822 +dnl AC_CANONICAL_TARGET
823 +dnl case "${target_os}" in
825 +dnl TARGET_CFLAGS="-DSYS_SOLARIS9 -D_POSIX_PTHREAD_SEMANTICS"
826 +dnl if test "$GCC" != yes ; then
827 +dnl TARGET_CFLAGS="$TARGET_CFLAGS -mt"
829 +dnl TARGET_CFLAGS="$TARGET_CFLAGS -pthreads"
831 +dnl TARGET_LDFLAGS="-lpthread -lsocket -lnsl"
834 +dnl TARGET_CFLAGS="-Wall -pedantic -pthread"
835 +dnl TARGET_LDFLAGS=""
839 +AC_ARG_ENABLE(reauth,
840 + [ --enable-reauth whether to enable fast reauthentication protocol: yes/no; default no ],
841 + [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
844 + echo "--enable-reauth argument must be yes or no"
849 +if test "x$reauth" = "xyes" ; then
850 + echo "Fast reauthentication protocol enabled"
851 + TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_REAUTH"
853 +AM_CONDITIONAL(GSSEAP_ENABLE_REAUTH, test "x$reauth" != "xno")
856 +AC_ARG_ENABLE(acceptor,
857 + [ --enable-acceptor whether to enable acceptor codepaths: yes/no; default yes ],
858 + [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
859 + acceptor=$enableval
861 + echo "--enable-acceptor argument must be yes or no"
866 +if test "x$acceptor" = "xyes" ; then
867 + echo "acceptor enabled"
868 + TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_ACCEPTOR"
870 +AM_CONDITIONAL(GSSEAP_ENABLE_ACCEPTOR, test "x$acceptor" != "xno")
872 +AC_SUBST(TARGET_CFLAGS)
873 +AC_SUBST(TARGET_LDFLAGS)
877 +AM_CONDITIONAL(OPENSAML, test "x_$check_opensaml_dir" != "x_no")
879 +AX_CHECK_SHIBRESOLVER
880 +AM_CONDITIONAL(SHIBRESOLVER, test "x_$check_shibresolver_dir" != "x_no")
881 +if test x_$found_shibresolver = x_yes; then
885 +if test "x$acceptor" = "xyes" ; then
890 +AX_CHECK_LIBMOONSHOT
891 +AC_CONFIG_FILES([Makefile mech_eap/Makefile
894 diff --git a/m4/minuso.m4 b/m4/minuso.m4
896 index 0000000..d8b1620
901 +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
902 +# Free Software Foundation, Inc.
904 +# This file is free software; the Free Software Foundation
905 +# gives unlimited permission to copy and/or distribute it,
906 +# with or without modifications, as long as this notice is preserved.
912 +# Like AC_PROG_CC_C_O, but changed for automake.
913 +AC_DEFUN([AM_PROG_CC_C_O],
914 +[AC_REQUIRE([AC_PROG_CC_C_O])dnl
915 +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
916 +AC_REQUIRE_AUX_FILE([compile])dnl
917 +# FIXME: we rely on the cache variable name because
918 +# there is no other way.
920 +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
921 +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
922 +if test "$am_t" != yes; then
923 + # Losing compiler, so override with the script.
924 + # FIXME: It is wrong to rewrite CC.
925 + # But if we don't then we get into trouble of one sort or another.
926 + # A longer-term fix would be to have automake use am__CC in this case,
927 + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
928 + CC="$am_aux_dir/compile $CC"
930 +dnl Make sure AC_PROG_CC is never called again, or it will override our
932 +m4_define([AC_PROG_CC],
933 + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
935 diff --git a/mech_eap.spec.in b/mech_eap.spec.in
937 index 0000000..90ac6cf
939 +++ b/mech_eap.spec.in
941 +%global _moonshot_krb5 %{!?_moonshot_krb5:krb5-devel}%{?_moonshot_krb5}
942 +Name: moonshot-gss-eap
945 +Summary: Moonshot GSS-API Mechanism
947 +Group: Security Tools
949 +URL: http://www.project-moonshot.org/
950 +Source0: mech_eap-%{version}.tar.gz
951 +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
953 +BuildRequires: %{_moonshot_krb5} >= 1.9.1
954 +BuildRequires: moonshot-ui-devel
955 +BuildRequires: jansson-devel
956 +Requires: moonshot-ui
957 +BuildRequires: libradsec-devel
958 +BuildRequires: shibboleth-devel >= 2.5
959 +BuildRequires: libshibresolver-devel
964 +Project Moonshot provides federated access management.
968 +%setup -q -n mech_eap-%{version}
972 + export LDFLAGS='-L/usr/%{_lib}/freeradius -Wl,--rpath=/usr/%{_lib}/freeradius'
973 +%configure --with-libmoonshot=%{_prefix} --with-krb5=%{_prefix} --disable-reauth
974 +make %{?_smp_mflags}
978 +rm -rf $RPM_BUILD_ROOT
979 +make install DESTDIR=$RPM_BUILD_ROOT
983 +rm -rf $RPM_BUILD_ROOT
987 +%defattr(-,root,root,-)
988 +%doc mech_eap/README
989 +%doc mech_eap/LICENSE
990 +%doc mech_eap/AUTHORS
991 +%{_libdir}/gss/mech_eap.so
992 +%exclude %{_libdir}/gss/mech_eap.la
993 +%{_includedir}/gssapi/*.h
994 +#%exclude %{_libdir}/krb5/plugins/authdata/*la
995 +#%{_libdir}/krb5/plugins/authdata/*.so
1000 +* Wed Sep 28 2011 <hartmans@moonbuildcentos.dev.ja.net> - @VERSION@-2
1001 +- Add radius_ad plugin
1003 diff --git a/mech_eap/.gitignore b/mech_eap/.gitignore
1004 new file mode 100644
1005 index 0000000..06a3924
1007 +++ b/mech_eap/.gitignore
1041 diff --git a/mech_eap/AUTHORS b/mech_eap/AUTHORS
1042 new file mode 100644
1043 index 0000000..3007a4b
1045 +++ b/mech_eap/AUTHORS
1047 +The initial implementation of mech_eap was written by PADL Software
1048 +under contract to JANET(UK).
1051 +Luke Howard <lukeh@padl.com>
1053 diff --git a/mech_eap/COPYING b/mech_eap/COPYING
1054 new file mode 100644
1055 index 0000000..7554e77
1057 +++ b/mech_eap/COPYING
1059 +Copyright (c) 2011, JANET(UK)
1061 +See the LICENSE file for licensing terms.
1062 diff --git a/mech_eap/LICENSE b/mech_eap/LICENSE
1063 new file mode 100644
1064 index 0000000..1b03a95
1066 +++ b/mech_eap/LICENSE
1069 + * Copyright (c) 2011, JANET(UK)
1070 + * All rights reserved.
1072 + * Redistribution and use in source and binary forms, with or without
1073 + * modification, are permitted provided that the following conditions
1076 + * 1. Redistributions of source code must retain the above copyright
1077 + * notice, this list of conditions and the following disclaimer.
1079 + * 2. Redistributions in binary form must reproduce the above copyright
1080 + * notice, this list of conditions and the following disclaimer in the
1081 + * documentation and/or other materials provided with the distribution.
1083 + * 3. Neither the name of JANET(UK) nor the names of its contributors
1084 + * may be used to endorse or promote products derived from this software
1085 + * without specific prior written permission.
1087 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1088 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1089 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1090 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1091 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1092 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1093 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1094 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1095 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1096 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1099 diff --git a/mech_eap/Makefile.am b/mech_eap/Makefile.am
1100 new file mode 100644
1101 index 0000000..23de6af
1103 +++ b/mech_eap/Makefile.am
1105 +AUTOMAKE_OPTIONS = foreign
1107 +EXTRA_DIST = gsseap_err.et radsec_err.et \
1108 + mech_eap.exports mech_eap-noacceptor.exports radius_ad.exports \
1112 +gssincludedir = $(includedir)/gssapi
1113 +gssinclude_HEADERS = gssapi_eap.h
1115 +EAP_CFLAGS = -I$(srcdir)/../libeap/src -I$(srcdir)/../libeap/src/common -I$(srcdir)/../libeap/src/eap_common \
1116 + -I$(srcdir)/../libeap/src/utils
1118 +if GSSEAP_ENABLE_ACCEPTOR
1119 +GSSEAP_EXPORTS = mech_eap.exports
1121 +GSSEAP_EXPORTS = mech_eap-noacceptor.exports
1124 +gssdir = $(libdir)/gss
1125 +gss_LTLIBRARIES = mech_eap.la
1128 +EAP_CFLAGS += -DCONFIG_WIN32_DEFAULTS -DUSE_INTERNAL_CRYPTO
1129 +OS_LIBS = -lshell32 -ladvapi32 -lws2_32 -lcomerr32
1130 +mech_eap_la_CFLAGS = -Zi
1131 +mech_eap_la_CXXFLAGS = -Zi
1133 +EAP_CFLAGS += -DEAP_TLS -DEAP_PEAP -DEAP_TTLS -DEAP_MD5 -DEAP_MSCHAPv2 -DEAP_GTC -DEAP_OTP -DEAP_LEAP -DEAP_PSK -DEAP_PAX -DEAP_SAKE -DEAP_GPSK -DEAP_GPSK_SHA256 -DEAP_SERVER_IDENTITY -DEAP_SERVER_TLS -DEAP_SERVER_PEAP -DEAP_SERVER_TTLS -DEAP_SERVER_MD5 -DEAP_SERVER_MSCHAPV2 -DEAP_SERVER_GTC -DEAP_SERVER_PSK -DEAP_SERVER_PAX -DEAP_SERVER_SAKE -DEAP_SERVER_GPSK -DEAP_SERVER_GPSK_SHA256 -DIEEE8021X_EAPOL
1135 +mech_eap_la_CFLAGS = -Werror -Wall -Wunused-parameter
1136 +mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter
1138 +mech_eap_la_DEPENDENCIES = $(GSSEAP_EXPORTS)
1140 +mech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\" -DDATAROOTDIR=\"${datarootdir}\"
1141 +mech_eap_la_CFLAGS += \
1142 + @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
1143 +mech_eap_la_CXXFLAGS += \
1144 + @KRB5_CFLAGS@ @RADSEC_CFLAGS@ \
1145 + @OPENSAML_CXXFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ \
1146 + @TARGET_CFLAGS@ $(EAP_CFLAGS)
1147 +mech_eap_la_LDFLAGS = -avoid-version -module \
1148 + -export-symbols $(GSSEAP_EXPORTS) -no-undefined \
1149 + @KRB5_LDFLAGS@ @RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
1151 +mech_eap_la_LDFLAGS += -debug
1154 +mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
1155 + @OPENSAML_LIBS@ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@
1156 +mech_eap_la_SOURCES = \
1158 + acquire_cred_with_password.c \
1160 + add_cred_with_password.c \
1161 + authorize_localname.c \
1162 + canonicalize_name.c \
1165 + delete_sec_context.c \
1167 + display_name_ext.c \
1168 + display_status.c \
1169 + duplicate_name.c \
1171 + exchange_meta_data.c \
1173 + export_sec_context.c \
1177 + import_sec_context.c \
1178 + indicate_mechs.c \
1179 + init_sec_context.c \
1180 + inquire_attrs_for_mech.c \
1181 + inquire_context.c \
1183 + inquire_cred_by_mech.c \
1184 + inquire_cred_by_oid.c \
1185 + inquire_mech_for_saslname.c \
1186 + inquire_mechs_for_name.c \
1187 + inquire_names_for_mech.c \
1188 + inquire_saslname_for_mech.c \
1189 + inquire_sec_context_by_oid.c \
1190 + process_context_token.c \
1192 + query_mechanism_info.c \
1193 + query_meta_data.c \
1198 + set_cred_option.c \
1199 + set_sec_context_option.c \
1220 + wrap_iov_length.c \
1221 + wrap_size_limit.c \
1233 +mech_eap_la_SOURCES += util_moonshot.c
1234 +mech_eap_la_CFLAGS += @LIBMOONSHOT_CFLAGS@
1235 +mech_eap_la_LDFLAGS += @LIBMOONSHOT_LDFLAGS@
1236 +mech_eap_la_LIBADD += @LIBMOONSHOT_LIBS@
1240 +if GSSEAP_ENABLE_ACCEPTOR
1242 +mech_eap_la_SOURCES += \
1243 + accept_sec_context.c \
1244 + delete_name_attribute.c \
1245 + export_name_composite.c \
1246 + get_name_attribute.c \
1248 + map_name_to_any.c \
1249 + release_any_name_mapping.c \
1250 + set_name_attribute.c \
1257 +mech_eap_la_SOURCES += util_saml.cpp
1261 +mech_eap_la_SOURCES += util_shib.cpp
1266 +BUILT_SOURCES = gsseap_err.c radsec_err.c gsseap_err.h radsec_err.h
1268 +if GSSEAP_ENABLE_REAUTH
1269 +mech_eap_la_SOURCES += util_reauth.c
1272 +krb5pluginsdir = $(libdir)/krb5/plugins/authdata
1273 +krb5plugins_LTLIBRARIES = radius_ad.la
1275 +radius_ad_la_CFLAGS = -Werror -Wall -Wunused-parameter \
1276 + @KRB5_CFLAGS@ $(EAP_CFLAGS) @RADSEC_CFLAGS@ @TARGET_CFLAGS@
1277 +radius_ad_la_LDFLAGS = -avoid-version -module \
1278 + -export-symbols radius_ad.exports -no-undefined
1279 +radius_ad_la_LIBADD = @KRB5_LIBS@
1280 +radius_ad_la_SOURCES = util_adshim.c authdata_plugin.h
1284 +gsseap_err.h gsseap_err.c: gsseap_err.et
1287 +radsec_err.h radsec_err.c: radsec_err.et
1290 +radsec_err.c: radsec_err.h
1293 + rm -f gsseap_err.[ch] radsec_err.[ch]
1294 diff --git a/mech_eap/NEWS b/mech_eap/NEWS
1295 new file mode 100644
1296 index 0000000..e69de29
1297 diff --git a/mech_eap/NOTES b/mech_eap/NOTES
1298 new file mode 100644
1299 index 0000000..849ce4e
1301 +++ b/mech_eap/NOTES
1303 +- gss_xxx routines acquire lock, gssXxx don't
1307 +If you do want to update with a rebase, deletethe branch from the
1308 +server first then push the rebased branch
1310 +to delete a branch from a server git push origin :branch_to_del
1312 diff --git a/mech_eap/README b/mech_eap/README
1313 new file mode 100644
1314 index 0000000..3cb2d50
1316 +++ b/mech_eap/README
1321 +This is an implementation of the GSS EAP mechanism, as described in
1322 +draft-ietf-abfab-gss-eap-01.txt.
1327 +In order to build this, a recent Kerberos implementation (MIT or
1328 +Heimdal), Shibboleth, and EAP libraries are required, along with
1329 +all of their dependencies.
1331 +Note: not all SPIs are supported by the Heimdal mechanism glue,
1332 +so not all features will be available.
1340 +When installing, be sure to edit $prefix/etc/gss/mech to register
1341 +the EAP mechanisms. A sample configuration file is in this directory.
1342 +You may need to specify an absolute path.
1344 +RADIUS client library
1345 +---------------------
1347 +Make sure your RADIUS library is configured to talk to the server of
1348 +your choice: see the example radsec.conf in this directory. If you
1349 +want to use TCP or TLS, you'll need to run radsecproxy in front of
1350 +your RADIUS server.
1355 +These instructions apply to FreeRADIUS only, which is downloadable
1356 +from http://freeradius.org/. After configure, make, install, do the
1359 +On the RADIUS server side, you need to install dictionary.ukerna to
1360 +$prefix/etc/raddb and include it from the main dictionary file, by
1363 + $INCLUDE dictionary.ukerna
1365 +to $prefix/etc/raddb/dictionary. Make sure these files are world-
1366 +readable; they weren't in my installation.
1368 +Edit $prefix/etc/raddb/users to add your test user and password:
1370 + bob@PROJECT-MOONSHOT.ORG Cleartext-Password := secret
1372 +Add an entry for your acceptor to $prefix/etc/raddb/clients.conf:
1375 + ipaddr = 127.0.0.1
1376 + secret = testing123
1377 + require_message_authenticator = yes
1380 +Edit $prefix/etc/raddb/eap.conf and set:
1384 + default_eap_type = ttls
1389 + private_key_file = ...
1390 + certificate_file = ...
1393 + default_eap_type = mschapv2
1394 + copy_request_to_tunnel = no
1395 + use_tunneled_reply = no
1396 + virtual_server = "inner-tunnel"
1401 +to enable EAP-TTLS.
1403 +If you want the acceptor be able to identify the user, the RADIUS
1404 +server needs to echo back the EAP username from the inner tunnel;
1405 +for privacy, mech_eap only sends the realm in the EAP Identity
1406 +response. To configure this with FreeRADIUS, add:
1408 + update outer.reply {
1409 + User-Name = "%{request:User-Name}"
1412 +If you want to add a SAML assertion, do this with "update reply"
1413 +in $prefix/etc/raddb/sites-available/default:
1416 + SAML-AAA-Assertion = '<saml:Assertion ...'
1417 + SAML-AAA-Assertion += '...'
1420 +You'll need to split it into multiple lines because of the RADIUS
1421 +attribute size limit.
1426 +You can then test the MIT or Cyrus GSS and SASL example programs.
1427 +Sample usage is given below. Substitute <user>, <pass> and <host>
1428 +appropriately (<host> is the name of the host running the server,
1429 +not the RADIUS server).
1431 +% gss-client -port 5555 -spnego -mech "{1 3 6 1 4 1 5322 22 1 18}" \
1432 + -user <user>@<realm> -pass <pass> <host> host@<host> \
1434 +% gss-server -port 5555 -export host@<host>
1436 +Note: for SASL you will be prompted for a username and password.
1438 +% client -C -p 5556 -s host -m EAP-AES128 <host>
1439 +% server -c -p 5556 -s host -h <host>
1441 +To test fast reauthentication support, add the following to
1446 + reauth_use_ccache = TRUE
1449 +This will store a Kerberos ticket for a GSS-EAP authenticated user
1450 +in a credentials cache, which can then be used for re-authentication
1451 +to the same acceptor. You must have a valid keytab configured.
1453 +In this testing phase of Moonshot, it's also possible to store a
1454 +default identity and credential in a file. The format consists of
1455 +the string representation of the initiator identity and the password,
1456 +separated by newlines. The default location of this file is
1457 +.gss_eap_id in the user's home directory, however the GSSEAP_IDENTITY
1458 +environment variable can be used to set an alternate location.
1460 +You can also set a default realm in [appdefaults]; the Kerberos
1461 +default realm is never used by mech_eap (or at least, that is the
1462 +intention), so if unspecified you must always qualify names. It should
1463 +generally not be necessary to specify this.
1465 diff --git a/mech_eap/README.samba4 b/mech_eap/README.samba4
1466 new file mode 100644
1467 index 0000000..d0a94d1
1469 +++ b/mech_eap/README.samba4
1471 +Notes on using Moonshot with Samba4. Replace paths as appropriate.
1476 +* Download Samba4 and apply patches for mechanism agnosticism which are
1477 + available at http://www.padl.com/~lukeh/samba/
1478 +* Join Samba as a member server or domain controller (only tested former)
1479 +* Extract local service principal key to keytab (currently there do not
1480 + appear to be tools to do this, but you can get the cleartext password
1481 + from /usr/local/samba/private/secrets.ldb)
1486 +* Add a mapping from the PAC RADIUS attribute to urn:mspac: in the file
1487 + /usr/local/etc/shibboleth/attribute-map.xml:
1489 + <GSSAPIAttribute name="urn:ietf:params:gss-eap:radius-avp urn:x-radius:1679163525"
1490 + id="urn:mspac:" binary="true"/>
1495 +Install the rlm_mspac module and configure per below.
1497 +* Install dictionary.ukerna so MS-Windows-Auth-Data is defined
1498 +* Create /usr/local/etc/raddb/modules/mspac with the following:
1501 + keytab = /etc/krb5.keytab
1502 + spn = host/host.fqdn@KERBEROS.REALM
1505 +* Add mspac to instantiate stanza in radiusd.conf
1506 +* Add mspac to post-auth stanza in sites-enabled/inner-tunnel
1508 +You will need to have a TGT for the host service principal before starting
1509 +radiusd. It's easiest to do this with kinit -k.
1514 +The Samba server doesn't require any specific command line arguments, although
1515 +on OS X it was necessary to start it with -M single to function under gdb.
1517 +For the client, the GSS EAP mechanism can be specified on the command line:
1519 +smbclient --password samba --mechanism 1.3.6.1.4.1.5322.22.1.18 '\\host\share'".
1521 +There is no Moonshot SSPI implementation as yet, so it is not possible to test
1522 +with a Windows client.
1523 diff --git a/mech_eap/TODO b/mech_eap/TODO
1524 new file mode 100644
1525 index 0000000..0111459
1529 +- integration with initiator-side EAP channel bindings
1530 +- investigate initiator-side credential locking
1531 +- always intern OIDs so they never need to be freed
1532 +- handle many-to-many Shibboleth attribute mappings; need to encode both attribute and value index into more
1533 +- add --with-xerces option
1534 +- proper acquire_cred_ext implementation pending specification
1535 diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c
1536 new file mode 100644
1537 index 0000000..b089bae
1539 +++ b/mech_eap/accept_sec_context.c
1542 + * Copyright (c) 2011, JANET(UK)
1543 + * All rights reserved.
1545 + * Redistribution and use in source and binary forms, with or without
1546 + * modification, are permitted provided that the following conditions
1549 + * 1. Redistributions of source code must retain the above copyright
1550 + * notice, this list of conditions and the following disclaimer.
1552 + * 2. Redistributions in binary form must reproduce the above copyright
1553 + * notice, this list of conditions and the following disclaimer in the
1554 + * documentation and/or other materials provided with the distribution.
1556 + * 3. Neither the name of JANET(UK) nor the names of its contributors
1557 + * may be used to endorse or promote products derived from this software
1558 + * without specific prior written permission.
1560 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1561 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1562 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1563 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1564 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1565 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1566 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1567 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1568 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1569 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1574 + * Establish a security context on the acceptor (server). These functions
1575 + * wrap around libradsec and (thus) talk to a RADIUS server or proxy.
1578 +#include "gssapiP_eap.h"
1580 +#ifdef GSSEAP_ENABLE_REAUTH
1582 +eapGssSmAcceptGssReauth(OM_uint32 *minor,
1583 + gss_cred_id_t cred,
1585 + gss_name_t target,
1587 + OM_uint32 reqFlags,
1588 + OM_uint32 timeReq,
1589 + gss_channel_bindings_t chanBindings,
1590 + gss_buffer_t inputToken,
1591 + gss_buffer_t outputToken,
1592 + OM_uint32 *smFlags);
1596 + * Mark an acceptor context as ready for cryptographic operations
1599 +acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
1601 + OM_uint32 major, tmpMinor;
1603 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
1605 + /* Cache encryption type derived from selected mechanism OID */
1606 + major = gssEapOidToEnctype(minor, ctx->mechanismUsed,
1607 + &ctx->encryptionType);
1608 + if (GSS_ERROR(major))
1611 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
1613 + major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps,
1614 + PW_USER_NAME, 0, &vp);
1615 + if (major == GSS_S_COMPLETE && vp->length) {
1616 + nameBuf.length = vp->length;
1617 + nameBuf.value = vp->vp_strvalue;
1619 + ctx->gssFlags |= GSS_C_ANON_FLAG;
1622 + major = gssEapImportName(minor, &nameBuf,
1623 + (ctx->gssFlags & GSS_C_ANON_FLAG) ?
1624 + GSS_C_NT_ANONYMOUS : GSS_C_NT_USER_NAME,
1625 + ctx->mechanismUsed,
1626 + &ctx->initiatorName);
1627 + if (GSS_ERROR(major))
1630 + major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps,
1631 + PW_MS_MPPE_SEND_KEY, VENDORPEC_MS, &vp);
1632 + if (GSS_ERROR(major)) {
1633 + *minor = GSSEAP_KEY_UNAVAILABLE;
1634 + return GSS_S_UNAVAILABLE;
1637 + major = gssEapDeriveRfc3961Key(minor,
1640 + ctx->encryptionType,
1641 + &ctx->rfc3961Key);
1642 + if (GSS_ERROR(major))
1645 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
1646 + &ctx->checksumType);
1647 + if (GSS_ERROR(major))
1650 + major = sequenceInit(minor,
1651 + &ctx->seqState, ctx->recvSeq,
1652 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
1653 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
1655 + if (GSS_ERROR(major))
1658 + major = gssEapCreateAttrContext(minor, cred, ctx,
1659 + &ctx->initiatorName->attrCtx,
1660 + &ctx->expiryTime);
1661 + if (GSS_ERROR(major))
1664 + if (ctx->expiryTime != 0 && ctx->expiryTime < time(NULL)) {
1665 + *minor = GSSEAP_CRED_EXPIRED;
1666 + return GSS_S_CREDENTIALS_EXPIRED;
1670 + return GSS_S_COMPLETE;
1674 +eapGssSmAcceptAcceptorName(OM_uint32 *minor,
1675 + gss_cred_id_t cred GSSEAP_UNUSED,
1677 + gss_name_t target GSSEAP_UNUSED,
1678 + gss_OID mech GSSEAP_UNUSED,
1679 + OM_uint32 reqFlags GSSEAP_UNUSED,
1680 + OM_uint32 timeReq GSSEAP_UNUSED,
1681 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1682 + gss_buffer_t inputToken GSSEAP_UNUSED,
1683 + gss_buffer_t outputToken,
1684 + OM_uint32 *smFlags GSSEAP_UNUSED)
1688 + /* XXX TODO import and validate name from inputToken */
1690 + if (ctx->acceptorName != GSS_C_NO_NAME) {
1691 + /* Send desired target name to acceptor */
1692 + major = gssEapDisplayName(minor, ctx->acceptorName,
1693 + outputToken, NULL);
1694 + if (GSS_ERROR(major))
1698 + return GSS_S_CONTINUE_NEEDED;
1701 +#ifdef GSSEAP_DEBUG
1703 +eapGssSmAcceptVendorInfo(OM_uint32 *minor,
1704 + gss_cred_id_t cred GSSEAP_UNUSED,
1705 + gss_ctx_id_t ctx GSSEAP_UNUSED,
1706 + gss_name_t target GSSEAP_UNUSED,
1707 + gss_OID mech GSSEAP_UNUSED,
1708 + OM_uint32 reqFlags GSSEAP_UNUSED,
1709 + OM_uint32 timeReq GSSEAP_UNUSED,
1710 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1711 + gss_buffer_t inputToken,
1712 + gss_buffer_t outputToken GSSEAP_UNUSED,
1713 + OM_uint32 *smFlags GSSEAP_UNUSED)
1715 + fprintf(stderr, "GSS-EAP: vendor: %.*s\n",
1716 + (int)inputToken->length, (char *)inputToken->value);
1719 + return GSS_S_CONTINUE_NEEDED;
1725 + * Emit a identity EAP request to force the initiator (peer) to identify
1729 +eapGssSmAcceptIdentity(OM_uint32 *minor,
1730 + gss_cred_id_t cred,
1732 + gss_name_t target GSSEAP_UNUSED,
1733 + gss_OID mech GSSEAP_UNUSED,
1734 + OM_uint32 reqFlags GSSEAP_UNUSED,
1735 + OM_uint32 timeReq GSSEAP_UNUSED,
1736 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1737 + gss_buffer_t inputToken,
1738 + gss_buffer_t outputToken,
1739 + OM_uint32 *smFlags)
1742 + struct wpabuf *reqData;
1743 + gss_buffer_desc pktBuffer;
1745 + if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
1746 + *minor = GSSEAP_CRED_MECH_MISMATCH;
1747 + return GSS_S_BAD_MECH;
1750 + if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
1751 + *minor = GSSEAP_WRONG_SIZE;
1752 + return GSS_S_DEFECTIVE_TOKEN;
1755 + reqData = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 0,
1756 + EAP_CODE_REQUEST, 0);
1757 + if (reqData == NULL) {
1759 + return GSS_S_FAILURE;
1762 + pktBuffer.length = wpabuf_len(reqData);
1763 + pktBuffer.value = (void *)wpabuf_head(reqData);
1765 + major = duplicateBuffer(minor, &pktBuffer, outputToken);
1766 + if (GSS_ERROR(major))
1769 + wpabuf_free(reqData);
1771 + GSSEAP_SM_TRANSITION_NEXT(ctx);
1774 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
1776 + return GSS_S_CONTINUE_NEEDED;
1780 + * Returns TRUE if the input token contains an EAP identity response.
1783 +isIdentityResponseP(gss_buffer_t inputToken)
1785 + struct wpabuf respData;
1787 + wpabuf_set(&respData, inputToken->value, inputToken->length);
1789 + return (eap_get_type(&respData) == EAP_TYPE_IDENTITY);
1793 + * Save the asserted initiator identity from the EAP identity response.
1796 +importInitiatorIdentity(OM_uint32 *minor,
1798 + gss_buffer_t inputToken)
1800 + OM_uint32 tmpMinor;
1801 + struct wpabuf respData;
1802 + const unsigned char *pos;
1804 + gss_buffer_desc nameBuf;
1806 + wpabuf_set(&respData, inputToken->value, inputToken->length);
1808 + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
1810 + if (pos == NULL) {
1811 + *minor = GSSEAP_PEER_BAD_MESSAGE;
1812 + return GSS_S_DEFECTIVE_TOKEN;
1815 + nameBuf.value = (void *)pos;
1816 + nameBuf.length = len;
1818 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
1820 + return gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
1821 + ctx->mechanismUsed, &ctx->initiatorName);
1825 + * Pass the asserted initiator identity to the authentication server.
1828 +setInitiatorIdentity(OM_uint32 *minor,
1832 + OM_uint32 major, tmpMinor;
1833 + gss_buffer_desc nameBuf;
1836 + * We should have got an EAP identity response, but if we didn't, then
1837 + * we will just avoid sending User-Name. Note that radsecproxy requires
1838 + * User-Name to be sent on every request (presumably so it can remain
1841 + if (ctx->initiatorName != GSS_C_NO_NAME) {
1842 + major = gssEapDisplayName(minor, ctx->initiatorName, &nameBuf, NULL);
1843 + if (GSS_ERROR(major))
1846 + major = gssEapRadiusAddAvp(minor, vps, PW_USER_NAME, 0, &nameBuf);
1847 + if (GSS_ERROR(major))
1850 + gss_release_buffer(&tmpMinor, &nameBuf);
1854 + return GSS_S_COMPLETE;
1858 + * Pass the asserted acceptor identity to the authentication server.
1861 +setAcceptorIdentity(OM_uint32 *minor,
1866 + gss_buffer_desc nameBuf;
1867 + krb5_context krbContext = NULL;
1868 + krb5_principal krbPrinc;
1869 + struct rs_context *rc = ctx->acceptorCtx.radContext;
1871 + GSSEAP_ASSERT(rc != NULL);
1873 + if (ctx->acceptorName == GSS_C_NO_NAME) {
1875 + return GSS_S_COMPLETE;
1878 + if ((ctx->acceptorName->flags & NAME_FLAG_SERVICE) == 0) {
1879 + *minor = GSSEAP_BAD_SERVICE_NAME;
1880 + return GSS_S_BAD_NAME;
1883 + GSSEAP_KRB_INIT(&krbContext);
1885 + krbPrinc = ctx->acceptorName->krbPrincipal;
1886 + GSSEAP_ASSERT(krbPrinc != NULL);
1887 + GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 2);
1889 + /* Acceptor-Service-Name */
1890 + krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf);
1892 + major = gssEapRadiusAddAvp(minor, vps,
1893 + PW_GSS_ACCEPTOR_SERVICE_NAME,
1896 + if (GSS_ERROR(major))
1899 + /* Acceptor-Host-Name */
1900 + krbPrincComponentToGssBuffer(krbPrinc, 1, &nameBuf);
1902 + major = gssEapRadiusAddAvp(minor, vps,
1903 + PW_GSS_ACCEPTOR_HOST_NAME,
1906 + if (GSS_ERROR(major))
1909 + if (KRB_PRINC_LENGTH(krbPrinc) > 2) {
1910 + /* Acceptor-Service-Specific */
1911 + krb5_principal_data ssiPrinc = *krbPrinc;
1914 + KRB_PRINC_LENGTH(&ssiPrinc) -= 2;
1915 + KRB_PRINC_NAME(&ssiPrinc) += 2;
1917 + *minor = krb5_unparse_name_flags(krbContext, &ssiPrinc,
1918 + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &ssi);
1920 + return GSS_S_FAILURE;
1922 + nameBuf.value = ssi;
1923 + nameBuf.length = strlen(ssi);
1925 + major = gssEapRadiusAddAvp(minor, vps,
1926 + PW_GSS_ACCEPTOR_SERVICE_SPECIFIC,
1930 + if (GSS_ERROR(major)) {
1931 + krb5_free_unparsed_name(krbContext, ssi);
1934 + krb5_free_unparsed_name(krbContext, ssi);
1937 + krbPrincRealmToGssBuffer(krbPrinc, &nameBuf);
1938 + if (nameBuf.length != 0) {
1939 + /* Acceptor-Realm-Name */
1940 + major = gssEapRadiusAddAvp(minor, vps,
1941 + PW_GSS_ACCEPTOR_REALM_NAME,
1944 + if (GSS_ERROR(major))
1949 + return GSS_S_COMPLETE;
1953 + * Allocate a RadSec handle
1956 +createRadiusHandle(OM_uint32 *minor,
1957 + gss_cred_id_t cred,
1960 + struct gss_eap_acceptor_ctx *actx = &ctx->acceptorCtx;
1961 + struct rs_error *err;
1962 + const char *configStanza = "gss-eap";
1965 + GSSEAP_ASSERT(actx->radContext == NULL);
1966 + GSSEAP_ASSERT(actx->radConn == NULL);
1967 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
1969 + major = gssEapCreateRadiusContext(minor, cred, &actx->radContext);
1970 + if (GSS_ERROR(major))
1973 + if (cred->radiusConfigStanza.value != NULL)
1974 + configStanza = (const char *)cred->radiusConfigStanza.value;
1976 + if (rs_conn_create(actx->radContext, &actx->radConn, configStanza) != 0) {
1977 + err = rs_err_conn_pop(actx->radConn);
1978 + return gssEapRadiusMapError(minor, err);
1981 + if (actx->radServer != NULL) {
1982 + if (rs_conn_select_peer(actx->radConn, actx->radServer) != 0) {
1983 + err = rs_err_conn_pop(actx->radConn);
1984 + return gssEapRadiusMapError(minor, err);
1989 + return GSS_S_COMPLETE;
1993 + * Process a EAP response from the initiator.
1996 +eapGssSmAcceptAuthenticate(OM_uint32 *minor,
1997 + gss_cred_id_t cred,
1999 + gss_name_t target GSSEAP_UNUSED,
2000 + gss_OID mech GSSEAP_UNUSED,
2001 + OM_uint32 reqFlags GSSEAP_UNUSED,
2002 + OM_uint32 timeReq GSSEAP_UNUSED,
2003 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2004 + gss_buffer_t inputToken,
2005 + gss_buffer_t outputToken,
2006 + OM_uint32 *smFlags)
2008 + OM_uint32 major, tmpMinor;
2009 + struct rs_connection *rconn;
2010 + struct rs_request *request = NULL;
2011 + struct rs_packet *req = NULL, *resp = NULL;
2012 + struct radius_packet *frreq, *frresp;
2014 + if (ctx->acceptorCtx.radContext == NULL) {
2015 + /* May be NULL from an imported partial context */
2016 + major = createRadiusHandle(minor, cred, ctx);
2017 + if (GSS_ERROR(major))
2021 + if (isIdentityResponseP(inputToken)) {
2022 + major = importInitiatorIdentity(minor, ctx, inputToken);
2023 + if (GSS_ERROR(major))
2027 + rconn = ctx->acceptorCtx.radConn;
2029 + if (rs_packet_create_authn_request(rconn, &req, NULL, NULL) != 0) {
2030 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2033 + frreq = rs_packet_frpkt(req);
2035 + major = setInitiatorIdentity(minor, ctx, &frreq->vps);
2036 + if (GSS_ERROR(major))
2039 + major = setAcceptorIdentity(minor, ctx, &frreq->vps);
2040 + if (GSS_ERROR(major))
2043 + major = gssEapRadiusAddAvp(minor, &frreq->vps,
2044 + PW_EAP_MESSAGE, 0, inputToken);
2045 + if (GSS_ERROR(major))
2048 + if (ctx->acceptorCtx.state.length != 0) {
2049 + major = gssEapRadiusAddAvp(minor, &frreq->vps, PW_STATE, 0,
2050 + &ctx->acceptorCtx.state);
2051 + if (GSS_ERROR(major))
2054 + gss_release_buffer(&tmpMinor, &ctx->acceptorCtx.state);
2057 + if (rs_request_create(rconn, &request) != 0) {
2058 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2062 + rs_request_add_reqpkt(request, req);
2065 + if (rs_request_send(request, &resp) != 0) {
2066 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2070 + GSSEAP_ASSERT(resp != NULL);
2072 + frresp = rs_packet_frpkt(resp);
2073 + switch (frresp->code) {
2074 + case PW_ACCESS_CHALLENGE:
2075 + case PW_AUTHENTICATION_ACK:
2077 + case PW_AUTHENTICATION_REJECT:
2078 + *minor = GSSEAP_RADIUS_AUTH_FAILURE;
2079 + major = GSS_S_DEFECTIVE_CREDENTIAL;
2083 + *minor = GSSEAP_UNKNOWN_RADIUS_CODE;
2084 + major = GSS_S_FAILURE;
2089 + major = gssEapRadiusGetAvp(minor, frresp->vps, PW_EAP_MESSAGE, 0,
2090 + outputToken, TRUE);
2091 + if (major == GSS_S_UNAVAILABLE && frresp->code == PW_ACCESS_CHALLENGE) {
2092 + *minor = GSSEAP_MISSING_EAP_REQUEST;
2093 + major = GSS_S_DEFECTIVE_TOKEN;
2095 + } else if (GSS_ERROR(major))
2098 + if (frresp->code == PW_ACCESS_CHALLENGE) {
2099 + major = gssEapRadiusGetAvp(minor, frresp->vps, PW_STATE, 0,
2100 + &ctx->acceptorCtx.state, TRUE);
2101 + if (GSS_ERROR(major) && *minor != GSSEAP_NO_SUCH_ATTR)
2104 + ctx->acceptorCtx.vps = frresp->vps;
2105 + frresp->vps = NULL;
2107 + major = acceptReadyEap(minor, ctx, cred);
2108 + if (GSS_ERROR(major))
2111 + GSSEAP_SM_TRANSITION_NEXT(ctx);
2114 + major = GSS_S_CONTINUE_NEEDED;
2116 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
2119 + if (request != NULL)
2120 + rs_request_destroy(request);
2122 + rs_packet_destroy(req);
2124 + rs_packet_destroy(resp);
2125 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIATOR_EXTS) {
2126 + GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
2128 + rs_conn_destroy(ctx->acceptorCtx.radConn);
2129 + ctx->acceptorCtx.radConn = NULL;
2136 +eapGssSmAcceptGssFlags(OM_uint32 *minor,
2137 + gss_cred_id_t cred GSSEAP_UNUSED,
2139 + gss_name_t target GSSEAP_UNUSED,
2140 + gss_OID mech GSSEAP_UNUSED,
2141 + OM_uint32 reqFlags GSSEAP_UNUSED,
2142 + OM_uint32 timeReq GSSEAP_UNUSED,
2143 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2144 + gss_buffer_t inputToken,
2145 + gss_buffer_t outputToken GSSEAP_UNUSED,
2146 + OM_uint32 *smFlags GSSEAP_UNUSED)
2149 + OM_uint32 initiatorGssFlags;
2151 + GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
2153 + if (inputToken->length < 4) {
2154 + *minor = GSSEAP_TOK_TRUNC;
2155 + return GSS_S_DEFECTIVE_TOKEN;
2158 + /* allow flags to grow for future expansion */
2159 + p = (unsigned char *)inputToken->value + inputToken->length - 4;
2161 + initiatorGssFlags = load_uint32_be(p);
2162 + initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
2164 + ctx->gssFlags |= initiatorGssFlags;
2166 + return GSS_S_CONTINUE_NEEDED;
2170 +eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
2171 + gss_cred_id_t cred GSSEAP_UNUSED,
2173 + gss_name_t target GSSEAP_UNUSED,
2174 + gss_OID mech GSSEAP_UNUSED,
2175 + OM_uint32 reqFlags GSSEAP_UNUSED,
2176 + OM_uint32 timeReq GSSEAP_UNUSED,
2177 + gss_channel_bindings_t chanBindings,
2178 + gss_buffer_t inputToken,
2179 + gss_buffer_t outputToken GSSEAP_UNUSED,
2180 + OM_uint32 *smFlags GSSEAP_UNUSED)
2183 + gss_iov_buffer_desc iov[2];
2185 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
2186 + iov[0].buffer.length = 0;
2187 + iov[0].buffer.value = NULL;
2189 + iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED;
2191 + /* XXX necessary because decrypted in place and we verify it later */
2192 + major = duplicateBuffer(minor, inputToken, &iov[1].buffer);
2193 + if (GSS_ERROR(major))
2196 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
2197 + iov, 2, TOK_TYPE_WRAP);
2198 + if (GSS_ERROR(major)) {
2199 + gssEapReleaseIov(iov, 2);
2203 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
2204 + !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
2205 + major = GSS_S_BAD_BINDINGS;
2206 + *minor = GSSEAP_BINDINGS_MISMATCH;
2208 + major = GSS_S_CONTINUE_NEEDED;
2212 + gssEapReleaseIov(iov, 2);
2218 +eapGssSmAcceptInitiatorMIC(OM_uint32 *minor,
2219 + gss_cred_id_t cred GSSEAP_UNUSED,
2221 + gss_name_t target GSSEAP_UNUSED,
2222 + gss_OID mech GSSEAP_UNUSED,
2223 + OM_uint32 reqFlags GSSEAP_UNUSED,
2224 + OM_uint32 timeReq GSSEAP_UNUSED,
2225 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2226 + gss_buffer_t inputToken,
2227 + gss_buffer_t outputToken GSSEAP_UNUSED,
2228 + OM_uint32 *smFlags GSSEAP_UNUSED)
2232 + major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
2233 + if (GSS_ERROR(major))
2236 + GSSEAP_SM_TRANSITION_NEXT(ctx);
2239 + return GSS_S_CONTINUE_NEEDED;
2242 +#ifdef GSSEAP_ENABLE_REAUTH
2244 +eapGssSmAcceptReauthCreds(OM_uint32 *minor,
2245 + gss_cred_id_t cred,
2247 + gss_name_t target GSSEAP_UNUSED,
2248 + gss_OID mech GSSEAP_UNUSED,
2249 + OM_uint32 reqFlags GSSEAP_UNUSED,
2250 + OM_uint32 timeReq GSSEAP_UNUSED,
2251 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2252 + gss_buffer_t inputToken GSSEAP_UNUSED,
2253 + gss_buffer_t outputToken,
2254 + OM_uint32 *smFlags GSSEAP_UNUSED)
2259 + * If we're built with fast reauthentication enabled, then
2260 + * fabricate a ticket from the initiator to ourselves.
2262 + major = gssEapMakeReauthCreds(minor, ctx, cred, outputToken);
2263 + if (major == GSS_S_UNAVAILABLE)
2264 + major = GSS_S_COMPLETE;
2265 + if (major == GSS_S_COMPLETE)
2266 + major = GSS_S_CONTINUE_NEEDED;
2273 +eapGssSmAcceptAcceptorMIC(OM_uint32 *minor,
2274 + gss_cred_id_t cred GSSEAP_UNUSED,
2276 + gss_name_t target GSSEAP_UNUSED,
2277 + gss_OID mech GSSEAP_UNUSED,
2278 + OM_uint32 reqFlags GSSEAP_UNUSED,
2279 + OM_uint32 timeReq GSSEAP_UNUSED,
2280 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2281 + gss_buffer_t inputToken GSSEAP_UNUSED,
2282 + gss_buffer_t outputToken,
2283 + OM_uint32 *smFlags)
2287 + major = gssEapMakeTokenMIC(minor, ctx, outputToken);
2288 + if (GSS_ERROR(major))
2291 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
2294 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
2296 + return GSS_S_COMPLETE;
2299 +static struct gss_eap_sm eapGssAcceptorSm[] = {
2301 + ITOK_TYPE_ACCEPTOR_NAME_REQ,
2302 + ITOK_TYPE_ACCEPTOR_NAME_RESP,
2303 + GSSEAP_STATE_INITIAL,
2305 + eapGssSmAcceptAcceptorName
2307 +#ifdef GSSEAP_DEBUG
2309 + ITOK_TYPE_VENDOR_INFO,
2311 + GSSEAP_STATE_INITIAL,
2313 + eapGssSmAcceptVendorInfo,
2316 +#ifdef GSSEAP_ENABLE_REAUTH
2318 + ITOK_TYPE_REAUTH_REQ,
2319 + ITOK_TYPE_REAUTH_RESP,
2320 + GSSEAP_STATE_INITIAL,
2322 + eapGssSmAcceptGssReauth,
2327 + ITOK_TYPE_EAP_REQ,
2328 + GSSEAP_STATE_INITIAL,
2329 + SM_ITOK_FLAG_REQUIRED,
2330 + eapGssSmAcceptIdentity,
2333 + ITOK_TYPE_EAP_RESP,
2334 + ITOK_TYPE_EAP_REQ,
2335 + GSSEAP_STATE_AUTHENTICATE,
2336 + SM_ITOK_FLAG_REQUIRED,
2337 + eapGssSmAcceptAuthenticate
2340 + ITOK_TYPE_GSS_FLAGS,
2342 + GSSEAP_STATE_INITIATOR_EXTS,
2344 + eapGssSmAcceptGssFlags
2347 + ITOK_TYPE_GSS_CHANNEL_BINDINGS,
2349 + GSSEAP_STATE_INITIATOR_EXTS,
2350 + SM_ITOK_FLAG_REQUIRED,
2351 + eapGssSmAcceptGssChannelBindings,
2354 + ITOK_TYPE_INITIATOR_MIC,
2356 + GSSEAP_STATE_INITIATOR_EXTS,
2357 + SM_ITOK_FLAG_REQUIRED,
2358 + eapGssSmAcceptInitiatorMIC,
2360 +#ifdef GSSEAP_ENABLE_REAUTH
2363 + ITOK_TYPE_REAUTH_CREDS,
2364 + GSSEAP_STATE_ACCEPTOR_EXTS,
2366 + eapGssSmAcceptReauthCreds,
2371 + ITOK_TYPE_ACCEPTOR_MIC,
2372 + GSSEAP_STATE_ACCEPTOR_EXTS,
2374 + eapGssSmAcceptAcceptorMIC
2379 +gssEapAcceptSecContext(OM_uint32 *minor,
2381 + gss_cred_id_t cred,
2382 + gss_buffer_t input_token,
2383 + gss_channel_bindings_t input_chan_bindings,
2384 + gss_name_t *src_name,
2385 + gss_OID *mech_type,
2386 + gss_buffer_t output_token,
2387 + OM_uint32 *ret_flags,
2388 + OM_uint32 *time_rec,
2389 + gss_cred_id_t *delegated_cred_handle)
2391 + OM_uint32 major, tmpMinor;
2393 + if (cred == GSS_C_NO_CREDENTIAL) {
2394 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
2395 + major = gssEapAcquireCred(minor,
2403 + if (GSS_ERROR(major))
2411 + * Previously we acquired the credential mutex here, but it should not be
2412 + * necessary as the acceptor does not access any mutable elements of the
2413 + * credential handle.
2417 + * Calling gssEapInquireCred() forces the default acceptor credential name
2420 + major = gssEapInquireCred(minor, cred, &ctx->acceptorName, NULL, NULL, NULL);
2421 + if (GSS_ERROR(major))
2424 + major = gssEapSmStep(minor,
2431 + input_chan_bindings,
2435 + sizeof(eapGssAcceptorSm) / sizeof(eapGssAcceptorSm[0]));
2436 + if (GSS_ERROR(major))
2439 + if (mech_type != NULL) {
2440 + OM_uint32 tmpMajor;
2442 + tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, mech_type);
2443 + if (GSS_ERROR(tmpMajor)) {
2445 + *minor = tmpMinor;
2449 + if (ret_flags != NULL)
2450 + *ret_flags = ctx->gssFlags;
2451 + if (delegated_cred_handle != NULL)
2452 + *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
2454 + if (major == GSS_S_COMPLETE) {
2455 + if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
2456 + major = gssEapDuplicateName(&tmpMinor, ctx->initiatorName, src_name);
2457 + if (GSS_ERROR(major))
2460 + if (time_rec != NULL) {
2461 + major = gssEapContextTime(&tmpMinor, ctx, time_rec);
2462 + if (GSS_ERROR(major))
2467 + GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
2473 +#ifdef GSSEAP_ENABLE_REAUTH
2475 +acceptReadyKrb(OM_uint32 *minor,
2477 + gss_cred_id_t cred,
2478 + const gss_name_t initiator,
2479 + const gss_OID mech,
2480 + OM_uint32 timeRec)
2484 + major = gssEapGlueToMechName(minor, ctx, initiator, &ctx->initiatorName);
2485 + if (GSS_ERROR(major))
2488 + major = gssEapReauthComplete(minor, ctx, cred, mech, timeRec);
2489 + if (GSS_ERROR(major))
2493 + return GSS_S_COMPLETE;
2497 +eapGssSmAcceptGssReauth(OM_uint32 *minor,
2498 + gss_cred_id_t cred,
2500 + gss_name_t target GSSEAP_UNUSED,
2502 + OM_uint32 reqFlags GSSEAP_UNUSED,
2503 + OM_uint32 timeReq GSSEAP_UNUSED,
2504 + gss_channel_bindings_t chanBindings,
2505 + gss_buffer_t inputToken,
2506 + gss_buffer_t outputToken,
2507 + OM_uint32 *smFlags)
2509 + OM_uint32 major, tmpMinor;
2510 + gss_name_t krbInitiator = GSS_C_NO_NAME;
2511 + OM_uint32 gssFlags, timeRec = GSS_C_INDEFINITE;
2514 + * If we're built with fast reauthentication support, it's valid
2515 + * for an initiator to send a GSS reauthentication token as its
2516 + * initial context token, causing us to short-circuit the state
2517 + * machine and process Kerberos GSS messages instead.
2520 + ctx->flags |= CTX_FLAG_KRB_REAUTH;
2522 + major = gssAcceptSecContext(minor,
2533 + if (major == GSS_S_COMPLETE) {
2534 + major = acceptReadyKrb(minor, ctx, cred,
2535 + krbInitiator, mech, timeRec);
2536 + if (major == GSS_S_COMPLETE) {
2537 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
2539 + ctx->gssFlags = gssFlags;
2540 + } else if (GSS_ERROR(major) &&
2541 + (*smFlags & SM_FLAG_INPUT_TOKEN_CRITICAL) == 0) {
2542 + /* pretend reauthentication attempt never happened */
2543 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
2544 + ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
2545 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
2546 + major = GSS_S_CONTINUE_NEEDED;
2549 + gssReleaseName(&tmpMinor, &krbInitiator);
2553 +#endif /* GSSEAP_ENABLE_REAUTH */
2555 +OM_uint32 GSSAPI_CALLCONV
2556 +gss_accept_sec_context(OM_uint32 *minor,
2557 + gss_ctx_id_t *context_handle,
2558 + gss_cred_id_t cred,
2559 + gss_buffer_t input_token,
2560 + gss_channel_bindings_t input_chan_bindings,
2561 + gss_name_t *src_name,
2562 + gss_OID *mech_type,
2563 + gss_buffer_t output_token,
2564 + OM_uint32 *ret_flags,
2565 + OM_uint32 *time_rec,
2566 + gss_cred_id_t *delegated_cred_handle)
2568 + OM_uint32 major, tmpMinor;
2569 + gss_ctx_id_t ctx = *context_handle;
2573 + output_token->length = 0;
2574 + output_token->value = NULL;
2576 + if (src_name != NULL)
2577 + *src_name = GSS_C_NO_NAME;
2579 + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
2580 + *minor = GSSEAP_TOK_TRUNC;
2581 + return GSS_S_DEFECTIVE_TOKEN;
2584 + if (ctx == GSS_C_NO_CONTEXT) {
2585 + major = gssEapAllocContext(minor, &ctx);
2586 + if (GSS_ERROR(major))
2589 + *context_handle = ctx;
2592 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
2594 + major = gssEapAcceptSecContext(minor,
2598 + input_chan_bindings,
2604 + delegated_cred_handle);
2606 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
2608 + if (GSS_ERROR(major))
2609 + gssEapReleaseContext(&tmpMinor, context_handle);
2613 diff --git a/mech_eap/acquire_cred.c b/mech_eap/acquire_cred.c
2614 new file mode 100644
2615 index 0000000..ae2648e
2617 +++ b/mech_eap/acquire_cred.c
2620 + * Copyright (c) 2011, JANET(UK)
2621 + * All rights reserved.
2623 + * Redistribution and use in source and binary forms, with or without
2624 + * modification, are permitted provided that the following conditions
2627 + * 1. Redistributions of source code must retain the above copyright
2628 + * notice, this list of conditions and the following disclaimer.
2630 + * 2. Redistributions in binary form must reproduce the above copyright
2631 + * notice, this list of conditions and the following disclaimer in the
2632 + * documentation and/or other materials provided with the distribution.
2634 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2635 + * may be used to endorse or promote products derived from this software
2636 + * without specific prior written permission.
2638 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2639 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2640 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2641 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2642 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2643 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2644 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2645 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2646 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2647 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2652 + * Wrapper for acquiring a credential handle.
2655 +#include "gssapiP_eap.h"
2657 +OM_uint32 GSSAPI_CALLCONV
2658 +gss_acquire_cred(OM_uint32 *minor,
2659 + gss_name_t desired_name,
2660 + OM_uint32 time_req,
2661 + gss_OID_set desired_mechs,
2662 + gss_cred_usage_t cred_usage,
2663 + gss_cred_id_t *output_cred_handle,
2664 + gss_OID_set *actual_mechs,
2665 + OM_uint32 *time_rec)
2667 + return gssEapAcquireCred(minor, desired_name,
2668 + time_req, desired_mechs, cred_usage,
2669 + output_cred_handle, actual_mechs, time_rec);
2671 diff --git a/mech_eap/acquire_cred_with_password.c b/mech_eap/acquire_cred_with_password.c
2672 new file mode 100644
2673 index 0000000..8e08358
2675 +++ b/mech_eap/acquire_cred_with_password.c
2678 + * Copyright (c) 2011, JANET(UK)
2679 + * All rights reserved.
2681 + * Redistribution and use in source and binary forms, with or without
2682 + * modification, are permitted provided that the following conditions
2685 + * 1. Redistributions of source code must retain the above copyright
2686 + * notice, this list of conditions and the following disclaimer.
2688 + * 2. Redistributions in binary form must reproduce the above copyright
2689 + * notice, this list of conditions and the following disclaimer in the
2690 + * documentation and/or other materials provided with the distribution.
2692 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2693 + * may be used to endorse or promote products derived from this software
2694 + * without specific prior written permission.
2696 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2697 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2698 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2699 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2700 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2701 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2702 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2703 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2704 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2705 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2710 + * Wrapper for acquiring a credential handle using a password.
2713 +#include "gssapiP_eap.h"
2715 +OM_uint32 GSSAPI_CALLCONV
2716 +gssspi_acquire_cred_with_password(OM_uint32 *minor,
2717 + const gss_name_t desired_name,
2718 + const gss_buffer_t password,
2719 + OM_uint32 time_req,
2720 + const gss_OID_set desired_mechs,
2721 + gss_cred_usage_t cred_usage,
2722 + gss_cred_id_t *output_cred_handle,
2723 + gss_OID_set *actual_mechs,
2724 + OM_uint32 *time_rec)
2726 + OM_uint32 major, tmpMinor;
2728 + major = gssEapAcquireCred(minor, desired_name,
2729 + time_req, desired_mechs, cred_usage,
2730 + output_cred_handle, actual_mechs, time_rec);
2731 + if (GSS_ERROR(major))
2734 + major = gssEapSetCredPassword(minor, *output_cred_handle, password);
2735 + if (GSS_ERROR(major))
2739 + if (GSS_ERROR(major))
2740 + gssEapReleaseCred(&tmpMinor, output_cred_handle);
2744 diff --git a/mech_eap/add_cred.c b/mech_eap/add_cred.c
2745 new file mode 100644
2746 index 0000000..64d97c0
2748 +++ b/mech_eap/add_cred.c
2751 + * Copyright (c) 2011, JANET(UK)
2752 + * All rights reserved.
2754 + * Redistribution and use in source and binary forms, with or without
2755 + * modification, are permitted provided that the following conditions
2758 + * 1. Redistributions of source code must retain the above copyright
2759 + * notice, this list of conditions and the following disclaimer.
2761 + * 2. Redistributions in binary form must reproduce the above copyright
2762 + * notice, this list of conditions and the following disclaimer in the
2763 + * documentation and/or other materials provided with the distribution.
2765 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2766 + * may be used to endorse or promote products derived from this software
2767 + * without specific prior written permission.
2769 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2770 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2771 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2772 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2773 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2774 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2775 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2776 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2777 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2778 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2783 + * Wrapper for acquiring a credential handle.
2786 +#include "gssapiP_eap.h"
2789 + * Note that this shouldn't really be required to be implemented by anything
2790 + * apart from the mechanism glue layer. However, Heimdal does call into the
2793 +OM_uint32 GSSAPI_CALLCONV
2794 +gss_add_cred(OM_uint32 *minor,
2795 + gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
2796 + gss_name_t desired_name,
2797 + gss_OID desired_mech,
2798 + gss_cred_usage_t cred_usage,
2799 + OM_uint32 initiator_time_req,
2800 + OM_uint32 acceptor_time_req,
2801 + gss_cred_id_t *output_cred_handle,
2802 + gss_OID_set *actual_mechs,
2803 + OM_uint32 *initiator_time_rec,
2804 + OM_uint32 *acceptor_time_rec)
2807 + OM_uint32 time_req, time_rec = 0;
2808 + gss_OID_set_desc mechs;
2811 + *output_cred_handle = GSS_C_NO_CREDENTIAL;
2813 + if (cred_usage == GSS_C_ACCEPT)
2814 + time_req = acceptor_time_req;
2816 + time_req = initiator_time_req;
2819 + mechs.elements = desired_mech;
2821 + major = gssEapAcquireCred(minor,
2826 + output_cred_handle,
2830 + if (initiator_time_rec != NULL)
2831 + *initiator_time_rec = time_rec;
2832 + if (acceptor_time_rec != NULL)
2833 + *acceptor_time_rec = time_rec;
2837 diff --git a/mech_eap/add_cred_with_password.c b/mech_eap/add_cred_with_password.c
2838 new file mode 100644
2839 index 0000000..b982f0d
2841 +++ b/mech_eap/add_cred_with_password.c
2844 + * Copyright (c) 2011, JANET(UK)
2845 + * All rights reserved.
2847 + * Redistribution and use in source and binary forms, with or without
2848 + * modification, are permitted provided that the following conditions
2851 + * 1. Redistributions of source code must retain the above copyright
2852 + * notice, this list of conditions and the following disclaimer.
2854 + * 2. Redistributions in binary form must reproduce the above copyright
2855 + * notice, this list of conditions and the following disclaimer in the
2856 + * documentation and/or other materials provided with the distribution.
2858 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2859 + * may be used to endorse or promote products derived from this software
2860 + * without specific prior written permission.
2862 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2863 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2864 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2865 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2866 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2867 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2868 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2869 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2870 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2871 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2876 + * Wrapper for acquiring a credential handle using a password.
2879 +#include "gssapiP_eap.h"
2881 +OM_uint32 GSSAPI_CALLCONV
2882 +gss_add_cred_with_password(OM_uint32 *minor,
2883 + const gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
2884 + const gss_name_t desired_name,
2885 + const gss_OID desired_mech,
2886 + const gss_buffer_t password,
2887 + gss_cred_usage_t cred_usage,
2888 + OM_uint32 initiator_time_req,
2889 + OM_uint32 acceptor_time_req,
2890 + gss_cred_id_t *output_cred_handle,
2891 + gss_OID_set *actual_mechs,
2892 + OM_uint32 *initiator_time_rec,
2893 + OM_uint32 *acceptor_time_rec)
2895 + OM_uint32 major, tmpMinor;
2896 + OM_uint32 time_req, time_rec = 0;
2897 + gss_OID_set_desc mechs;
2900 + *output_cred_handle = GSS_C_NO_CREDENTIAL;
2902 + if (cred_usage == GSS_C_ACCEPT)
2903 + time_req = acceptor_time_req;
2905 + time_req = initiator_time_req;
2908 + mechs.elements = desired_mech;
2910 + major = gssEapAcquireCred(minor,
2915 + output_cred_handle,
2918 + if (GSS_ERROR(major))
2921 + major = gssEapSetCredPassword(minor, *output_cred_handle, password);
2922 + if (GSS_ERROR(major))
2925 + if (initiator_time_rec != NULL)
2926 + *initiator_time_rec = time_rec;
2927 + if (acceptor_time_rec != NULL)
2928 + *acceptor_time_rec = time_rec;
2931 + if (GSS_ERROR(major))
2932 + gssEapReleaseCred(&tmpMinor, output_cred_handle);
2936 diff --git a/mech_eap/authdata_plugin.h b/mech_eap/authdata_plugin.h
2937 new file mode 100644
2938 index 0000000..32bff2f
2940 +++ b/mech_eap/authdata_plugin.h
2942 +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2944 + * krb5/authdata_plugin.h
2946 + * Copyright (C) 2007 Apple Inc. All Rights Reserved.
2948 + * Export of this software from the United States of America may
2949 + * require a specific license from the United States Government.
2950 + * It is the responsibility of any person or organization contemplating
2951 + * export to obtain such a license before exporting.
2953 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
2954 + * distribute this software and its documentation for any purpose and
2955 + * without fee is hereby granted, provided that the above copyright
2956 + * notice appear in all copies and that both that copyright notice and
2957 + * this permission notice appear in supporting documentation, and that
2958 + * the name of M.I.T. not be used in advertising or publicity pertaining
2959 + * to distribution of the software without specific, written prior
2960 + * permission. Furthermore if you modify this software you must label
2961 + * your software as modified software and not distribute it in such a
2962 + * fashion that it might be confused with the original M.I.T. software.
2963 + * M.I.T. makes no representations about the suitability of
2964 + * this software for any purpose. It is provided "as is" without express
2965 + * or implied warranty.
2967 + * AuthorizationData plugin definitions for Kerberos 5.
2971 + * This is considered an INTERNAL interface at this time.
2973 + * Some work is needed before exporting it:
2975 + * + Documentation.
2977 + * + Test cases (preferably automated testing under "make check").
2978 + * + Hook into TGS exchange too; will change API.
2979 + * + Examine memory management issues, especially for Windows; may
2982 + * Other changes that would be nice to have, but not necessarily
2983 + * before making this interface public:
2985 + * + Library support for AD-IF-RELEVANT and similar wrappers. (We can
2986 + * make the plugin construct them if it wants them.)
2987 + * + KDC could combine/optimize wrapped AD elements provided by
2988 + * multiple plugins, e.g., two IF-RELEVANT sequences could be
2989 + * merged. (The preauth plugin API also has this bug, we're going
2990 + * to need a general fix.)
2993 +#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED
2994 +#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED
2995 +#include <krb5/krb5.h>
2998 + * While arguments of these types are passed-in, for the most part a
2999 + * authorization data module can treat them as opaque. If we need
3000 + * keying data, we can ask for it directly.
3002 +struct _krb5_db_entry_new;
3005 + * The function table / structure which an authdata server module must export as
3006 + * "authdata_server_0". NOTE: replace "0" with "1" for the type and
3007 + * variable names if this gets picked up by upstream. If the interfaces work
3008 + * correctly, future versions of the table will add either more callbacks or
3009 + * more arguments to callbacks, and in both cases we'll be able to wrap the v0
3012 +/* extern krb5plugin_authdata_ftable_v0 authdata_server_0; */
3013 +typedef struct krb5plugin_authdata_server_ftable_v0 {
3014 + /* Not-usually-visible name. */
3018 + * Per-plugin initialization/cleanup. The init function is called
3019 + * by the KDC when the plugin is loaded, and the fini function is
3020 + * called before the plugin is unloaded. Both are optional.
3022 + krb5_error_code (*init_proc)(krb5_context, void **);
3023 + void (*fini_proc)(krb5_context, void *);
3025 + * Actual authorization data handling function. If this field
3026 + * holds a null pointer, this mechanism will be skipped, and the
3027 + * init/fini functions will not be run.
3029 + * This function should only modify the field
3030 + * enc_tkt_reply->authorization_data. All other values should be
3031 + * considered inputs only. And, it should *modify* the field, not
3032 + * overwrite it and assume that there are no other authdata
3035 + * Memory management: authorization_data is a malloc-allocated,
3036 + * null-terminated sequence of malloc-allocated pointers to
3037 + * authorization data structures. This plugin code currently
3038 + * assumes the libraries, KDC, and plugin all use the same malloc
3039 + * pool, which may be a problem if/when we get the KDC code
3040 + * running on Windows.
3042 + * If this function returns a non-zero error code, a message
3043 + * is logged, but no other action is taken. Other authdata
3044 + * plugins will be called, and a response will be sent to the
3045 + * client (barring other problems).
3047 + krb5_error_code (*authdata_proc)(krb5_context,
3048 + struct _krb5_db_entry_new *client,
3049 + krb5_data *req_pkt,
3050 + krb5_kdc_req *request,
3051 + krb5_enc_tkt_part *enc_tkt_reply);
3052 +} krb5plugin_server_authdata_ftable_v0;
3054 +typedef krb5plugin_server_authdata_ftable_v0 krb5plugin_authdata_ftable_v0;
3056 +typedef struct krb5plugin_authdata_server_ftable_v2 {
3057 + /* Not-usually-visible name. */
3061 + * Per-plugin initialization/cleanup. The init function is called
3062 + * by the KDC when the plugin is loaded, and the fini function is
3063 + * called before the plugin is unloaded. Both are optional.
3065 + krb5_error_code (*init_proc)(krb5_context, void **);
3066 + void (*fini_proc)(krb5_context, void *);
3068 + * Actual authorization data handling function. If this field
3069 + * holds a null pointer, this mechanism will be skipped, and the
3070 + * init/fini functions will not be run.
3072 + * This function should only modify the field
3073 + * enc_tkt_reply->authorization_data. All other values should be
3074 + * considered inputs only. And, it should *modify* the field, not
3075 + * overwrite it and assume that there are no other authdata
3078 + * Memory management: authorization_data is a malloc-allocated,
3079 + * null-terminated sequence of malloc-allocated pointers to
3080 + * authorization data structures. This plugin code currently
3081 + * assumes the libraries, KDC, and plugin all use the same malloc
3082 + * pool, which may be a problem if/when we get the KDC code
3083 + * running on Windows.
3085 + * If this function returns a non-zero error code, a message
3086 + * is logged, but no other action is taken. Other authdata
3087 + * plugins will be called, and a response will be sent to the
3088 + * client (barring other problems).
3090 + krb5_error_code (*authdata_proc)(krb5_context,
3091 + unsigned int flags,
3092 + struct _krb5_db_entry_new *client,
3093 + struct _krb5_db_entry_new *server,
3094 + struct _krb5_db_entry_new *tgs,
3095 + krb5_keyblock *client_key,
3096 + krb5_keyblock *server_key,
3097 + krb5_keyblock *tgs_key,
3098 + krb5_data *req_pkt,
3099 + krb5_kdc_req *request,
3100 + krb5_const_principal for_user_princ,
3101 + krb5_enc_tkt_part *enc_tkt_request,
3102 + krb5_enc_tkt_part *enc_tkt_reply);
3103 +} krb5plugin_authdata_server_ftable_v2;
3105 +typedef krb5plugin_authdata_server_ftable_v2 krb5plugin_authdata_ftable_v2;
3107 +typedef krb5_error_code
3108 +(*authdata_client_plugin_init_proc)(krb5_context context,
3109 + void **plugin_context);
3111 +#define AD_USAGE_AS_REQ 0x01
3112 +#define AD_USAGE_TGS_REQ 0x02
3113 +#define AD_USAGE_AP_REQ 0x04
3114 +#define AD_USAGE_KDC_ISSUED 0x08
3115 +#define AD_USAGE_MASK 0x0F
3116 +#define AD_INFORMATIONAL 0x10
3118 +struct _krb5_authdata_context;
3121 +(*authdata_client_plugin_flags_proc)(krb5_context kcontext,
3122 + void *plugin_context,
3123 + krb5_authdatatype ad_type,
3124 + krb5_flags *flags);
3127 +(*authdata_client_plugin_fini_proc)(krb5_context kcontext,
3128 + void *plugin_context);
3130 +typedef krb5_error_code
3131 +(*authdata_client_request_init_proc)(krb5_context kcontext,
3132 + struct _krb5_authdata_context *context,
3133 + void *plugin_context,
3134 + void **request_context);
3137 +(*authdata_client_request_fini_proc)(krb5_context kcontext,
3138 + struct _krb5_authdata_context *context,
3139 + void *plugin_context,
3140 + void *request_context);
3142 +typedef krb5_error_code
3143 +(*authdata_client_import_authdata_proc)(krb5_context kcontext,
3144 + struct _krb5_authdata_context *context,
3145 + void *plugin_context,
3146 + void *request_context,
3147 + krb5_authdata **authdata,
3148 + krb5_boolean kdc_issued_flag,
3149 + krb5_const_principal issuer);
3151 +typedef krb5_error_code
3152 +(*authdata_client_export_authdata_proc)(krb5_context kcontext,
3153 + struct _krb5_authdata_context *context,
3154 + void *plugin_context,
3155 + void *request_context,
3157 + krb5_authdata ***authdata);
3159 +typedef krb5_error_code
3160 +(*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
3161 + struct _krb5_authdata_context *context,
3162 + void *plugin_context,
3163 + void *request_context,
3164 + krb5_data **attrs);
3166 +typedef krb5_error_code
3167 +(*authdata_client_get_attribute_proc)(krb5_context kcontext,
3168 + struct _krb5_authdata_context *context,
3169 + void *plugin_context,
3170 + void *request_context,
3171 + const krb5_data *attribute,
3172 + krb5_boolean *authenticated,
3173 + krb5_boolean *complete,
3175 + krb5_data *display_value,
3178 +typedef krb5_error_code
3179 +(*authdata_client_set_attribute_proc)(krb5_context kcontext,
3180 + struct _krb5_authdata_context *context,
3181 + void *plugin_context,
3182 + void *request_context,
3183 + krb5_boolean complete,
3184 + const krb5_data *attribute,
3185 + const krb5_data *value);
3187 +typedef krb5_error_code
3188 +(*authdata_client_delete_attribute_proc)(krb5_context kcontext,
3189 + struct _krb5_authdata_context *context,
3190 + void *plugin_context,
3191 + void *request_context,
3192 + const krb5_data *attribute);
3194 +typedef krb5_error_code
3195 +(*authdata_client_export_internal_proc)(krb5_context kcontext,
3196 + struct _krb5_authdata_context *context,
3197 + void *plugin_context,
3198 + void *request_context,
3199 + krb5_boolean restrict_authenticated,
3203 +(*authdata_client_free_internal_proc)(krb5_context kcontext,
3204 + struct _krb5_authdata_context *context,
3205 + void *plugin_context,
3206 + void *request_context,
3209 +typedef krb5_error_code
3210 +(*authdata_client_verify_proc)(krb5_context kcontext,
3211 + struct _krb5_authdata_context *context,
3212 + void *plugin_context,
3213 + void *request_context,
3214 + const krb5_auth_context *auth_context,
3215 + const krb5_keyblock *key,
3216 + const krb5_ap_req *req);
3218 +typedef krb5_error_code
3219 +(*authdata_client_size_proc)(krb5_context kcontext,
3220 + struct _krb5_authdata_context *context,
3221 + void *plugin_context,
3222 + void *request_context,
3225 +typedef krb5_error_code
3226 +(*authdata_client_externalize_proc)(krb5_context kcontext,
3227 + struct _krb5_authdata_context *context,
3228 + void *plugin_context,
3229 + void *request_context,
3230 + krb5_octet **buffer,
3231 + size_t *lenremain);
3233 +typedef krb5_error_code
3234 +(*authdata_client_internalize_proc)(krb5_context kcontext,
3235 + struct _krb5_authdata_context *context,
3236 + void *plugin_context,
3237 + void *request_context,
3238 + krb5_octet **buffer,
3239 + size_t *lenremain);
3241 +typedef krb5_error_code
3242 +(*authdata_client_copy_proc)(krb5_context kcontext,
3243 + struct _krb5_authdata_context *context,
3244 + void *plugin_context,
3245 + void *request_context,
3246 + void *dst_plugin_context,
3247 + void *dst_request_context);
3249 +typedef struct krb5plugin_authdata_client_ftable_v0 {
3251 + krb5_authdatatype *ad_type_list;
3252 + authdata_client_plugin_init_proc init;
3253 + authdata_client_plugin_fini_proc fini;
3254 + authdata_client_plugin_flags_proc flags;
3255 + authdata_client_request_init_proc request_init;
3256 + authdata_client_request_fini_proc request_fini;
3257 + authdata_client_get_attribute_types_proc get_attribute_types;
3258 + authdata_client_get_attribute_proc get_attribute;
3259 + authdata_client_set_attribute_proc set_attribute;
3260 + authdata_client_delete_attribute_proc delete_attribute;
3261 + authdata_client_export_authdata_proc export_authdata;
3262 + authdata_client_import_authdata_proc import_authdata;
3263 + authdata_client_export_internal_proc export_internal;
3264 + authdata_client_free_internal_proc free_internal;
3265 + authdata_client_verify_proc verify;
3266 + authdata_client_size_proc size;
3267 + authdata_client_externalize_proc externalize;
3268 + authdata_client_internalize_proc internalize;
3269 + authdata_client_copy_proc copy; /* optional */
3270 +} krb5plugin_authdata_client_ftable_v0;
3272 +#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
3273 diff --git a/mech_eap/authorize_localname.c b/mech_eap/authorize_localname.c
3274 new file mode 100644
3275 index 0000000..0037e2b
3277 +++ b/mech_eap/authorize_localname.c
3280 + * Copyright (c) 2011, JANET(UK)
3281 + * All rights reserved.
3283 + * Redistribution and use in source and binary forms, with or without
3284 + * modification, are permitted provided that the following conditions
3287 + * 1. Redistributions of source code must retain the above copyright
3288 + * notice, this list of conditions and the following disclaimer.
3290 + * 2. Redistributions in binary form must reproduce the above copyright
3291 + * notice, this list of conditions and the following disclaimer in the
3292 + * documentation and/or other materials provided with the distribution.
3294 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3295 + * may be used to endorse or promote products derived from this software
3296 + * without specific prior written permission.
3298 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3299 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3300 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3301 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3302 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3303 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3304 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3305 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3306 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3307 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3312 + * Local authorization services.
3315 +#include "gssapiP_eap.h"
3317 +OM_uint32 GSSAPI_CALLCONV
3318 +gssspi_authorize_localname(OM_uint32 *minor,
3319 + const gss_name_t name GSSEAP_UNUSED,
3320 + gss_const_buffer_t local_user GSSEAP_UNUSED,
3321 + gss_const_OID local_nametype GSSEAP_UNUSED)
3324 + * The MIT mechglue will fallback to comparing names in the absence
3325 + * of a mechanism implementation of gss_userok. To avoid this and
3326 + * force the mechglue to use attribute-based authorization, always
3327 + * return access denied here.
3331 + return GSS_S_UNAUTHORIZED;
3333 diff --git a/mech_eap/canonicalize_name.c b/mech_eap/canonicalize_name.c
3334 new file mode 100644
3335 index 0000000..5e66798
3337 +++ b/mech_eap/canonicalize_name.c
3340 + * Copyright (c) 2011, JANET(UK)
3341 + * All rights reserved.
3343 + * Redistribution and use in source and binary forms, with or without
3344 + * modification, are permitted provided that the following conditions
3347 + * 1. Redistributions of source code must retain the above copyright
3348 + * notice, this list of conditions and the following disclaimer.
3350 + * 2. Redistributions in binary form must reproduce the above copyright
3351 + * notice, this list of conditions and the following disclaimer in the
3352 + * documentation and/or other materials provided with the distribution.
3354 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3355 + * may be used to endorse or promote products derived from this software
3356 + * without specific prior written permission.
3358 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3359 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3360 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3361 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3362 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3363 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3364 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3365 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3366 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3367 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3372 + * Function for canonicalizing a name; presently just duplicates it.
3375 +#include "gssapiP_eap.h"
3377 +OM_uint32 GSSAPI_CALLCONV
3378 +gss_canonicalize_name(OM_uint32 *minor,
3379 + const gss_name_t input_name,
3380 + const gss_OID mech_type,
3381 + gss_name_t *output_name)
3387 + if (!gssEapIsMechanismOid(mech_type))
3388 + return GSS_S_BAD_MECH;
3390 + if (input_name == GSS_C_NO_NAME) {
3392 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
3395 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
3397 + major = gssEapCanonicalizeName(minor, input_name, mech_type, output_name);
3399 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
3403 diff --git a/mech_eap/compare_name.c b/mech_eap/compare_name.c
3404 new file mode 100644
3405 index 0000000..edadf3e
3407 +++ b/mech_eap/compare_name.c
3410 + * Copyright (c) 2011, JANET(UK)
3411 + * All rights reserved.
3413 + * Redistribution and use in source and binary forms, with or without
3414 + * modification, are permitted provided that the following conditions
3417 + * 1. Redistributions of source code must retain the above copyright
3418 + * notice, this list of conditions and the following disclaimer.
3420 + * 2. Redistributions in binary form must reproduce the above copyright
3421 + * notice, this list of conditions and the following disclaimer in the
3422 + * documentation and/or other materials provided with the distribution.
3424 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3425 + * may be used to endorse or promote products derived from this software
3426 + * without specific prior written permission.
3428 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3429 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3430 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3431 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3432 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3433 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3434 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3435 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3436 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3437 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3442 + * Compare two names.
3445 +#include "gssapiP_eap.h"
3447 +OM_uint32 GSSAPI_CALLCONV
3448 +gss_compare_name(OM_uint32 *minor,
3453 + return gssEapCompareName(minor, name1, name2, name_equal);
3455 diff --git a/mech_eap/context_time.c b/mech_eap/context_time.c
3456 new file mode 100644
3457 index 0000000..ae47d6c
3459 +++ b/mech_eap/context_time.c
3462 + * Copyright (c) 2011, JANET(UK)
3463 + * All rights reserved.
3465 + * Redistribution and use in source and binary forms, with or without
3466 + * modification, are permitted provided that the following conditions
3469 + * 1. Redistributions of source code must retain the above copyright
3470 + * notice, this list of conditions and the following disclaimer.
3472 + * 2. Redistributions in binary form must reproduce the above copyright
3473 + * notice, this list of conditions and the following disclaimer in the
3474 + * documentation and/or other materials provided with the distribution.
3476 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3477 + * may be used to endorse or promote products derived from this software
3478 + * without specific prior written permission.
3480 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3481 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3482 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3483 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3484 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3485 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3486 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3487 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3488 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3489 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3494 + * Determine remaining lifetime of a context handle.
3497 +#include "gssapiP_eap.h"
3499 +OM_uint32 GSSAPI_CALLCONV
3500 +gss_context_time(OM_uint32 *minor,
3502 + OM_uint32 *time_rec)
3506 + if (ctx == GSS_C_NO_CONTEXT) {
3508 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
3513 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
3515 + if (!CTX_IS_ESTABLISHED(ctx)) {
3516 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
3517 + major = GSS_S_NO_CONTEXT;
3521 + major = gssEapContextTime(minor, ctx, time_rec);
3522 + if (GSS_ERROR(major))
3526 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3530 diff --git a/mech_eap/delete_name_attribute.c b/mech_eap/delete_name_attribute.c
3531 new file mode 100644
3532 index 0000000..fe0ff8f
3534 +++ b/mech_eap/delete_name_attribute.c
3537 + * Copyright (c) 2011, JANET(UK)
3538 + * All rights reserved.
3540 + * Redistribution and use in source and binary forms, with or without
3541 + * modification, are permitted provided that the following conditions
3544 + * 1. Redistributions of source code must retain the above copyright
3545 + * notice, this list of conditions and the following disclaimer.
3547 + * 2. Redistributions in binary form must reproduce the above copyright
3548 + * notice, this list of conditions and the following disclaimer in the
3549 + * documentation and/or other materials provided with the distribution.
3551 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3552 + * may be used to endorse or promote products derived from this software
3553 + * without specific prior written permission.
3555 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3556 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3557 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3558 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3559 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3560 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3561 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3562 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3563 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3564 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3569 + * Wrapper for removing a name attribute.
3572 +#include "gssapiP_eap.h"
3574 +OM_uint32 GSSAPI_CALLCONV
3575 +gss_delete_name_attribute(OM_uint32 *minor,
3577 + gss_buffer_t attr)
3583 + if (name == GSS_C_NO_NAME) {
3585 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
3588 + GSSEAP_MUTEX_LOCK(&name->mutex);
3590 + major = gssEapDeleteNameAttribute(minor, name, attr);
3592 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
3596 diff --git a/mech_eap/delete_sec_context.c b/mech_eap/delete_sec_context.c
3597 new file mode 100644
3598 index 0000000..7913e45
3600 +++ b/mech_eap/delete_sec_context.c
3603 + * Copyright (c) 2011, JANET(UK)
3604 + * All rights reserved.
3606 + * Redistribution and use in source and binary forms, with or without
3607 + * modification, are permitted provided that the following conditions
3610 + * 1. Redistributions of source code must retain the above copyright
3611 + * notice, this list of conditions and the following disclaimer.
3613 + * 2. Redistributions in binary form must reproduce the above copyright
3614 + * notice, this list of conditions and the following disclaimer in the
3615 + * documentation and/or other materials provided with the distribution.
3617 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3618 + * may be used to endorse or promote products derived from this software
3619 + * without specific prior written permission.
3621 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3622 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3623 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3624 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3625 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3627 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3628 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3629 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3630 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3635 + * Release a context handle.
3638 +#include "gssapiP_eap.h"
3640 +OM_uint32 GSSAPI_CALLCONV
3641 +gss_delete_sec_context(OM_uint32 *minor,
3642 + gss_ctx_id_t *context_handle,
3643 + gss_buffer_t output_token)
3646 + gss_ctx_id_t ctx = *context_handle;
3650 + if (output_token != GSS_C_NO_BUFFER) {
3651 + output_token->length = 0;
3652 + output_token->value = NULL;
3655 + if (ctx == GSS_C_NO_CONTEXT)
3656 + return GSS_S_COMPLETE;
3658 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
3660 + if (output_token != GSS_C_NO_BUFFER) {
3661 + gss_iov_buffer_desc iov[2];
3663 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
3664 + iov[0].buffer.value = NULL;
3665 + iov[0].buffer.length = 0;
3667 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
3668 + iov[1].buffer.value = NULL;
3669 + iov[1].buffer.length = 0;
3671 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
3672 + iov, 2, TOK_TYPE_DELETE_CONTEXT);
3673 + if (GSS_ERROR(major)) {
3674 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3679 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3681 + return gssEapReleaseContext(minor, context_handle);
3683 diff --git a/mech_eap/dictionary.ukerna b/mech_eap/dictionary.ukerna
3684 new file mode 100644
3685 index 0000000..0e35d43
3687 +++ b/mech_eap/dictionary.ukerna
3696 +VENDOR UKERNA 25622
3698 +BEGIN-VENDOR UKERNA
3700 +ATTRIBUTE GSS-Acceptor-Service-Name 128 string
3701 +ATTRIBUTE GSS-Acceptor-Host-Name 129 string
3702 +ATTRIBUTE GSS-Acceptor-Service-Specific 130 string
3703 +ATTRIBUTE GSS-Acceptor-Realm-Name 131 string
3704 +ATTRIBUTE SAML-AAA-Assertion 132 string
3705 +ATTRIBUTE MS-Windows-Auth-Data 133 octets
3706 +ATTRIBUTE MS-Windows-Group-Sid 134 string
3709 diff --git a/mech_eap/display_name.c b/mech_eap/display_name.c
3710 new file mode 100644
3711 index 0000000..2d87e66
3713 +++ b/mech_eap/display_name.c
3716 + * Copyright (c) 2011, JANET(UK)
3717 + * All rights reserved.
3719 + * Redistribution and use in source and binary forms, with or without
3720 + * modification, are permitted provided that the following conditions
3723 + * 1. Redistributions of source code must retain the above copyright
3724 + * notice, this list of conditions and the following disclaimer.
3726 + * 2. Redistributions in binary form must reproduce the above copyright
3727 + * notice, this list of conditions and the following disclaimer in the
3728 + * documentation and/or other materials provided with the distribution.
3730 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3731 + * may be used to endorse or promote products derived from this software
3732 + * without specific prior written permission.
3734 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3735 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3736 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3737 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3738 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3739 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3740 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3741 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3742 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3743 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3748 + * Wrapper for "displaying" (returning string representation of) a name.
3751 +#include "gssapiP_eap.h"
3753 +OM_uint32 GSSAPI_CALLCONV
3754 +gss_display_name(OM_uint32 *minor,
3756 + gss_buffer_t output_name_buffer,
3757 + gss_OID *output_name_type)
3759 + /* Lock not required as long as attributes are not used */
3760 + return gssEapDisplayName(minor, name, output_name_buffer,
3761 + output_name_type);
3763 diff --git a/mech_eap/display_name_ext.c b/mech_eap/display_name_ext.c
3764 new file mode 100644
3765 index 0000000..d6791d4
3767 +++ b/mech_eap/display_name_ext.c
3770 + * Copyright (c) 2011, JANET(UK)
3771 + * All rights reserved.
3773 + * Redistribution and use in source and binary forms, with or without
3774 + * modification, are permitted provided that the following conditions
3777 + * 1. Redistributions of source code must retain the above copyright
3778 + * notice, this list of conditions and the following disclaimer.
3780 + * 2. Redistributions in binary form must reproduce the above copyright
3781 + * notice, this list of conditions and the following disclaimer in the
3782 + * documentation and/or other materials provided with the distribution.
3784 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3785 + * may be used to endorse or promote products derived from this software
3786 + * without specific prior written permission.
3788 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3789 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3790 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3791 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3792 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3793 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3794 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3795 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3796 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3797 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3802 + * Parameterized version of gss_display_name(), currently unimplemented.
3805 +#include "gssapiP_eap.h"
3807 +OM_uint32 GSSAPI_CALLCONV
3808 +gss_display_name_ext(OM_uint32 *minor,
3809 + gss_name_t name GSSEAP_UNUSED,
3810 + gss_OID display_as_name_type GSSEAP_UNUSED,
3811 + gss_buffer_t display_name)
3815 + display_name->length = 0;
3816 + display_name->value = NULL;
3818 + return GSS_S_UNAVAILABLE;
3820 diff --git a/mech_eap/display_status.c b/mech_eap/display_status.c
3821 new file mode 100644
3822 index 0000000..fc0d1ab
3824 +++ b/mech_eap/display_status.c
3827 + * Copyright (c) 2011, JANET(UK)
3828 + * All rights reserved.
3830 + * Redistribution and use in source and binary forms, with or without
3831 + * modification, are permitted provided that the following conditions
3834 + * 1. Redistributions of source code must retain the above copyright
3835 + * notice, this list of conditions and the following disclaimer.
3837 + * 2. Redistributions in binary form must reproduce the above copyright
3838 + * notice, this list of conditions and the following disclaimer in the
3839 + * documentation and/or other materials provided with the distribution.
3841 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3842 + * may be used to endorse or promote products derived from this software
3843 + * without specific prior written permission.
3845 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3846 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3847 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3848 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3849 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3850 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3851 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3852 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3853 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3854 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3859 + * Function for converting mechanism error codes to strings.
3862 +#include "gssapiP_eap.h"
3864 +struct gss_eap_status_info {
3867 + struct gss_eap_status_info *next;
3871 +gssEapDestroyStatusInfo(struct gss_eap_status_info *p)
3873 + struct gss_eap_status_info *next;
3875 + for (; p != NULL; p = next) {
3877 + GSSEAP_FREE(p->message);
3883 + * Associate a message with a mechanism (minor) status code. This function
3884 + * takes ownership of the message regardless of success. The message must
3885 + * be explicitly cleared, if required, so it is suggested that a specific
3886 + * minor code is either always or never associated with a message, to avoid
3887 + * dangling (and potentially confusing) error messages.
3890 +saveStatusInfoNoCopy(OM_uint32 minor, char *message)
3892 + struct gss_eap_status_info **next = NULL, *p = NULL;
3893 + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
3895 + if (tld != NULL) {
3896 + for (p = tld->statusInfo; p != NULL; p = p->next) {
3897 + if (p->code == minor) {
3898 + /* Set message in-place */
3899 + if (p->message != NULL)
3900 + GSSEAP_FREE(p->message);
3901 + p->message = message;
3906 + p = GSSEAP_CALLOC(1, sizeof(*p));
3910 + if (message != NULL)
3911 + GSSEAP_FREE(message);
3916 + p->message = message;
3921 + tld->statusInfo = p;
3924 +static const char *
3925 +getStatusInfo(OM_uint32 minor)
3927 + struct gss_eap_status_info *p;
3928 + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
3930 + if (tld != NULL) {
3931 + for (p = tld->statusInfo; p != NULL; p = p->next) {
3932 + if (p->code == minor)
3933 + return p->message;
3940 +gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...)
3943 + OM_uint32 tmpMajor, tmpMinor;
3945 + gss_buffer_desc s = GSS_C_EMPTY_BUFFER;
3948 + if (format != NULL) {
3949 + va_start(ap, format);
3950 + snprintf(buf, sizeof(buf), format, ap);
3954 + tmpMajor = makeStringBuffer(&tmpMinor, buf, &s);
3955 + if (!GSS_ERROR(tmpMajor))
3956 + saveStatusInfoNoCopy(minor, (char *)s.value);
3962 + if (format != NULL) {
3963 + va_start(ap, format);
3964 + n = vasprintf(&s, format, ap);
3970 + saveStatusInfoNoCopy(minor, s);
3975 +gssEapDisplayStatus(OM_uint32 *minor,
3976 + OM_uint32 status_value,
3977 + gss_buffer_t status_string)
3980 + krb5_context krbContext = NULL;
3981 + const char *errMsg;
3983 + status_string->length = 0;
3984 + status_string->value = NULL;
3986 + errMsg = getStatusInfo(status_value);
3987 + if (errMsg == NULL) {
3988 + GSSEAP_KRB_INIT(&krbContext);
3990 + /* Try the com_err message */
3991 + errMsg = krb5_get_error_message(krbContext, status_value);
3994 + if (errMsg != NULL) {
3995 + major = makeStringBuffer(minor, errMsg, status_string);
3997 + major = GSS_S_COMPLETE;
4001 + if (krbContext != NULL)
4002 + krb5_free_error_message(krbContext, errMsg);
4007 +OM_uint32 GSSAPI_CALLCONV
4008 +gss_display_status(OM_uint32 *minor,
4009 + OM_uint32 status_value,
4011 + gss_OID mech_type,
4012 + OM_uint32 *message_context,
4013 + gss_buffer_t status_string)
4015 + if (!gssEapIsMechanismOid(mech_type)) {
4016 + *minor = GSSEAP_WRONG_MECH;
4017 + return GSS_S_BAD_MECH;
4020 + if (status_type != GSS_C_MECH_CODE ||
4021 + *message_context != 0) {
4022 + /* we rely on the mechglue for GSS_C_GSS_CODE */
4024 + return GSS_S_BAD_STATUS;
4027 + return gssEapDisplayStatus(minor, status_value, status_string);
4029 diff --git a/mech_eap/duplicate_name.c b/mech_eap/duplicate_name.c
4030 new file mode 100644
4031 index 0000000..303619e
4033 +++ b/mech_eap/duplicate_name.c
4036 + * Copyright (c) 2011, JANET(UK)
4037 + * All rights reserved.
4039 + * Redistribution and use in source and binary forms, with or without
4040 + * modification, are permitted provided that the following conditions
4043 + * 1. Redistributions of source code must retain the above copyright
4044 + * notice, this list of conditions and the following disclaimer.
4046 + * 2. Redistributions in binary form must reproduce the above copyright
4047 + * notice, this list of conditions and the following disclaimer in the
4048 + * documentation and/or other materials provided with the distribution.
4050 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4051 + * may be used to endorse or promote products derived from this software
4052 + * without specific prior written permission.
4054 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4055 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4056 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4057 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4058 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4059 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4060 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4061 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4062 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4063 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4068 + * Duplicate a name.
4071 +#include "gssapiP_eap.h"
4073 +OM_uint32 GSSAPI_CALLCONV
4074 +gss_duplicate_name(OM_uint32 *minor,
4075 + const gss_name_t input_name,
4076 + gss_name_t *dest_name)
4082 + if (input_name == GSS_C_NO_NAME) {
4084 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4087 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4089 + major = gssEapDuplicateName(minor, input_name, dest_name);
4091 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4095 diff --git a/mech_eap/eap_mech.c b/mech_eap/eap_mech.c
4096 new file mode 100644
4097 index 0000000..96e00c2
4099 +++ b/mech_eap/eap_mech.c
4102 + * Copyright (c) 2011, JANET(UK)
4103 + * All rights reserved.
4105 + * Redistribution and use in source and binary forms, with or without
4106 + * modification, are permitted provided that the following conditions
4109 + * 1. Redistributions of source code must retain the above copyright
4110 + * notice, this list of conditions and the following disclaimer.
4112 + * 2. Redistributions in binary form must reproduce the above copyright
4113 + * notice, this list of conditions and the following disclaimer in the
4114 + * documentation and/or other materials provided with the distribution.
4116 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4117 + * may be used to endorse or promote products derived from this software
4118 + * without specific prior written permission.
4120 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4121 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4122 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4123 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4124 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4125 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4126 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4127 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4128 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4129 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4134 + * Initialisation and finalise functions.
4137 +#include "gssapiP_eap.h"
4140 +eapPeerRegisterMethods(OM_uint32 *minor)
4142 + OM_uint32 ret = 0;
4146 + ret = eap_peer_md5_register();
4147 +#endif /* EAP_MD5 */
4151 + ret = eap_peer_tls_register();
4152 +#endif /* EAP_TLS */
4154 +#ifdef EAP_MSCHAPv2
4156 + ret = eap_peer_mschapv2_register();
4157 +#endif /* EAP_MSCHAPv2 */
4161 + ret = eap_peer_peap_register();
4162 +#endif /* EAP_PEAP */
4166 + ret = eap_peer_ttls_register();
4167 +#endif /* EAP_TTLS */
4171 + ret = eap_peer_gtc_register();
4172 +#endif /* EAP_GTC */
4176 + ret = eap_peer_otp_register();
4177 +#endif /* EAP_OTP */
4181 + ret = eap_peer_sim_register();
4182 +#endif /* EAP_SIM */
4186 + ret = eap_peer_leap_register();
4187 +#endif /* EAP_LEAP */
4191 + ret = eap_peer_psk_register();
4192 +#endif /* EAP_PSK */
4196 + ret = eap_peer_aka_register();
4197 +#endif /* EAP_AKA */
4199 +#ifdef EAP_AKA_PRIME
4201 + ret = eap_peer_aka_prime_register();
4202 +#endif /* EAP_AKA_PRIME */
4206 + ret = eap_peer_fast_register();
4207 +#endif /* EAP_FAST */
4211 + ret = eap_peer_pax_register();
4212 +#endif /* EAP_PAX */
4216 + ret = eap_peer_sake_register();
4217 +#endif /* EAP_SAKE */
4221 + ret = eap_peer_gpsk_register();
4222 +#endif /* EAP_GPSK */
4226 + ret = eap_peer_wsc_register();
4227 +#endif /* EAP_WSC */
4231 + ret = eap_peer_ikev2_register();
4232 +#endif /* EAP_IKEV2 */
4234 +#ifdef EAP_VENDOR_TEST
4236 + ret = eap_peer_vendor_test_register();
4237 +#endif /* EAP_VENDOR_TEST */
4241 + ret = eap_peer_tnc_register();
4242 +#endif /* EAP_TNC */
4245 + return GSS_S_COMPLETE;
4247 + *minor = GSSEAP_LIBEAP_INIT_FAILURE;
4248 + return GSS_S_FAILURE;
4252 +gssEapInitLibEap(OM_uint32 *minor)
4254 + return eapPeerRegisterMethods(minor);
4258 +gssEapInitLibRadsec(OM_uint32 *minor)
4261 + *minor = GSSEAP_RADSEC_INIT_FAILURE;
4262 + return GSS_S_FAILURE;
4265 + return GSS_S_COMPLETE;
4268 +void gssEapFinalize(void) GSSEAP_DESTRUCTOR;
4271 +gssEapInitiatorInit(OM_uint32 *minor)
4275 + initialize_eapg_error_table();
4276 + initialize_rse_error_table();
4278 + major = gssEapInitLibEap(minor);
4279 + if (GSS_ERROR(major))
4282 + major = gssEapInitLibRadsec(minor);
4283 + if (GSS_ERROR(major))
4286 +#ifdef GSSEAP_ENABLE_REAUTH
4287 + major = gssEapReauthInitialize(minor);
4288 + if (GSS_ERROR(major))
4293 + return GSS_S_COMPLETE;
4297 +gssEapFinalize(void)
4299 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4302 + gssEapAttrProvidersFinalize(&minor);
4304 + eap_peer_unregister_methods();
4307 +#ifdef GSSEAP_CONSTRUCTOR
4308 +static void gssEapInitiatorInitAssert(void) GSSEAP_CONSTRUCTOR;
4311 +gssEapInitiatorInitAssert(void)
4313 + OM_uint32 major, minor;
4315 + major = gssEapInitiatorInit(&minor);
4317 + GSSEAP_ASSERT(!GSS_ERROR(major));
4320 diff --git a/mech_eap/exchange_meta_data.c b/mech_eap/exchange_meta_data.c
4321 new file mode 100644
4322 index 0000000..5d56795
4324 +++ b/mech_eap/exchange_meta_data.c
4327 + * Copyright (c) 2011, JANET(UK)
4328 + * All rights reserved.
4330 + * Redistribution and use in source and binary forms, with or without
4331 + * modification, are permitted provided that the following conditions
4334 + * 1. Redistributions of source code must retain the above copyright
4335 + * notice, this list of conditions and the following disclaimer.
4337 + * 2. Redistributions in binary form must reproduce the above copyright
4338 + * notice, this list of conditions and the following disclaimer in the
4339 + * documentation and/or other materials provided with the distribution.
4341 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4342 + * may be used to endorse or promote products derived from this software
4343 + * without specific prior written permission.
4345 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4346 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4347 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4348 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4349 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4350 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4351 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4352 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4353 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4354 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4362 +#include "gssapiP_eap.h"
4364 +OM_uint32 GSSAPI_CALLCONV
4365 +gssEapExchangeMetaData(OM_uint32 *minor,
4366 + gss_const_OID mech GSSEAP_UNUSED,
4367 + gss_cred_id_t cred GSSEAP_UNUSED,
4368 + gss_ctx_id_t *ctx GSSEAP_UNUSED,
4369 + const gss_name_t name GSSEAP_UNUSED,
4370 + OM_uint32 req_flags GSSEAP_UNUSED,
4371 + gss_const_buffer_t meta_data GSSEAP_UNUSED)
4374 + return GSS_S_COMPLETE;
4377 +OM_uint32 GSSAPI_CALLCONV
4378 +gss_exchange_meta_data(OM_uint32 *minor,
4379 + gss_const_OID mech,
4380 + gss_cred_id_t cred,
4381 + gss_ctx_id_t *context_handle,
4382 + const gss_name_t name,
4383 + OM_uint32 req_flags,
4384 + gss_const_buffer_t meta_data)
4386 + gss_ctx_id_t ctx = *context_handle;
4389 + if (cred != GSS_C_NO_CREDENTIAL)
4390 + GSSEAP_MUTEX_LOCK(&cred->mutex);
4392 + if (*context_handle != GSS_C_NO_CONTEXT)
4393 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4395 + major = gssEapExchangeMetaData(minor, mech, cred, &ctx,
4396 + name, req_flags, meta_data);
4398 + if (*context_handle != GSS_C_NO_CONTEXT)
4399 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4401 + *context_handle = ctx;
4403 + if (cred != GSS_C_NO_CREDENTIAL)
4404 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
4408 diff --git a/mech_eap/export_name.c b/mech_eap/export_name.c
4409 new file mode 100644
4410 index 0000000..d91033f
4412 +++ b/mech_eap/export_name.c
4415 + * Copyright (c) 2011, JANET(UK)
4416 + * All rights reserved.
4418 + * Redistribution and use in source and binary forms, with or without
4419 + * modification, are permitted provided that the following conditions
4422 + * 1. Redistributions of source code must retain the above copyright
4423 + * notice, this list of conditions and the following disclaimer.
4425 + * 2. Redistributions in binary form must reproduce the above copyright
4426 + * notice, this list of conditions and the following disclaimer in the
4427 + * documentation and/or other materials provided with the distribution.
4429 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4430 + * may be used to endorse or promote products derived from this software
4431 + * without specific prior written permission.
4433 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4434 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4435 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4436 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4437 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4438 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4439 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4440 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4441 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4442 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4447 + * Serialise a name.
4450 +#include "gssapiP_eap.h"
4452 +OM_uint32 GSSAPI_CALLCONV
4453 +gss_export_name(OM_uint32 *minor,
4454 + const gss_name_t input_name,
4455 + gss_buffer_t exported_name)
4461 + if (input_name == GSS_C_NO_NAME) {
4463 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4466 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4468 + major = gssEapExportName(minor, input_name, exported_name);
4470 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4474 diff --git a/mech_eap/export_name_composite.c b/mech_eap/export_name_composite.c
4475 new file mode 100644
4476 index 0000000..b2a90ae
4478 +++ b/mech_eap/export_name_composite.c
4481 + * Copyright (c) 2011, JANET(UK)
4482 + * All rights reserved.
4484 + * Redistribution and use in source and binary forms, with or without
4485 + * modification, are permitted provided that the following conditions
4488 + * 1. Redistributions of source code must retain the above copyright
4489 + * notice, this list of conditions and the following disclaimer.
4491 + * 2. Redistributions in binary form must reproduce the above copyright
4492 + * notice, this list of conditions and the following disclaimer in the
4493 + * documentation and/or other materials provided with the distribution.
4495 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4496 + * may be used to endorse or promote products derived from this software
4497 + * without specific prior written permission.
4499 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4500 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4501 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4502 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4503 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4504 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4505 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4506 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4507 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4508 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4513 + * Serialise a name and its attributes.
4516 +#include "gssapiP_eap.h"
4518 +OM_uint32 GSSAPI_CALLCONV
4519 +gss_export_name_composite(OM_uint32 *minor,
4520 + gss_name_t input_name,
4521 + gss_buffer_t exported_name)
4527 + if (input_name == GSS_C_NO_NAME) {
4529 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4532 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4534 + major = gssEapExportNameInternal(minor, input_name, exported_name,
4535 + EXPORT_NAME_FLAG_OID |
4536 + EXPORT_NAME_FLAG_COMPOSITE);
4538 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4542 diff --git a/mech_eap/export_sec_context.c b/mech_eap/export_sec_context.c
4543 new file mode 100644
4544 index 0000000..e5be6d8
4546 +++ b/mech_eap/export_sec_context.c
4549 + * Copyright (c) 2011, JANET(UK)
4550 + * All rights reserved.
4552 + * Redistribution and use in source and binary forms, with or without
4553 + * modification, are permitted provided that the following conditions
4556 + * 1. Redistributions of source code must retain the above copyright
4557 + * notice, this list of conditions and the following disclaimer.
4559 + * 2. Redistributions in binary form must reproduce the above copyright
4560 + * notice, this list of conditions and the following disclaimer in the
4561 + * documentation and/or other materials provided with the distribution.
4563 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4564 + * may be used to endorse or promote products derived from this software
4565 + * without specific prior written permission.
4567 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4568 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4569 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4570 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4571 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4572 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4573 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4574 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4575 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4576 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4581 + * Serialise a security context. On the acceptor, this may be partially
4585 +#include "gssapiP_eap.h"
4587 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4589 +gssEapExportPartialContext(OM_uint32 *minor,
4591 + gss_buffer_t token)
4593 + OM_uint32 major, tmpMinor;
4594 + size_t length, serverLen = 0;
4596 + char serverBuf[MAXHOSTNAMELEN];
4597 + if (ctx->acceptorCtx.radConn != NULL) {
4598 + if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
4599 + serverBuf, sizeof(serverBuf)) != 0) {
4601 + return gssEapRadiusMapError(minor,
4602 + rs_err_conn_pop(ctx->acceptorCtx.radConn));
4604 + serverBuf[0] = '\0'; /* not implemented yet */
4607 + serverLen = strlen(serverBuf);
4609 + length = 4 + serverLen + 4 + ctx->acceptorCtx.state.length;
4611 + token->value = GSSEAP_MALLOC(length);
4612 + if (token->value == NULL) {
4613 + major = GSS_S_FAILURE;
4617 + token->length = length;
4619 + p = (unsigned char *)token->value;
4621 + store_uint32_be(serverLen, p);
4623 + if (serverLen != 0) {
4624 + memcpy(p, serverBuf, serverLen);
4628 + store_uint32_be(ctx->acceptorCtx.state.length, p);
4630 + if (ctx->acceptorCtx.state.length != 0) {
4631 + memcpy(p, ctx->acceptorCtx.state.value,
4632 + ctx->acceptorCtx.state.length);
4633 + p += ctx->acceptorCtx.state.length;
4636 + GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
4638 + major = GSS_S_COMPLETE;
4642 + if (GSS_ERROR(major))
4643 + gss_release_buffer(&tmpMinor, token);
4647 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
4650 +gssEapExportSecContext(OM_uint32 *minor,
4652 + gss_buffer_t token)
4654 + OM_uint32 major, tmpMinor;
4656 + gss_buffer_desc initiatorName = GSS_C_EMPTY_BUFFER;
4657 + gss_buffer_desc acceptorName = GSS_C_EMPTY_BUFFER;
4658 + gss_buffer_desc partialCtx = GSS_C_EMPTY_BUFFER;
4659 + gss_buffer_desc key;
4662 + if ((CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx)) ||
4663 + ctx->mechanismUsed == GSS_C_NO_OID) {
4664 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
4665 + return GSS_S_NO_CONTEXT;
4668 + key.length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
4669 + key.value = KRB_KEY_DATA(&ctx->rfc3961Key);
4671 + if (ctx->initiatorName != GSS_C_NO_NAME) {
4672 + major = gssEapExportNameInternal(minor, ctx->initiatorName,
4674 + EXPORT_NAME_FLAG_COMPOSITE);
4675 + if (GSS_ERROR(major))
4679 + if (ctx->acceptorName != GSS_C_NO_NAME) {
4680 + major = gssEapExportNameInternal(minor, ctx->acceptorName,
4682 + EXPORT_NAME_FLAG_COMPOSITE);
4683 + if (GSS_ERROR(major))
4687 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4689 + * The partial context is only transmitted for unestablished acceptor
4692 + if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
4693 + (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
4694 + major = gssEapExportPartialContext(minor, ctx, &partialCtx);
4695 + if (GSS_ERROR(major))
4700 + length = 16; /* version, state, flags, */
4701 + length += 4 + ctx->mechanismUsed->length; /* mechanismUsed */
4702 + length += 12 + key.length; /* rfc3961Key.value */
4703 + length += 4 + initiatorName.length; /* initiatorName.value */
4704 + length += 4 + acceptorName.length; /* acceptorName.value */
4705 + length += 24 + sequenceSize(ctx->seqState); /* seqState */
4707 + if (partialCtx.value != NULL)
4708 + length += 4 + partialCtx.length; /* partialCtx.value */
4710 + token->value = GSSEAP_MALLOC(length);
4711 + if (token->value == NULL) {
4712 + major = GSS_S_FAILURE;
4716 + token->length = length;
4718 + p = (unsigned char *)token->value;
4720 + store_uint32_be(EAP_EXPORT_CONTEXT_V1, &p[0]); /* version */
4721 + store_uint32_be(GSSEAP_SM_STATE(ctx), &p[4]);
4722 + store_uint32_be(ctx->flags, &p[8]);
4723 + store_uint32_be(ctx->gssFlags, &p[12]);
4724 + p = store_oid(ctx->mechanismUsed, &p[16]);
4726 + store_uint32_be(ctx->checksumType, &p[0]);
4727 + store_uint32_be(ctx->encryptionType, &p[4]);
4728 + p = store_buffer(&key, &p[8], FALSE);
4730 + p = store_buffer(&initiatorName, p, FALSE);
4731 + p = store_buffer(&acceptorName, p, FALSE);
4733 + store_uint64_be(ctx->expiryTime, &p[0]);
4734 + store_uint64_be(ctx->sendSeq, &p[8]);
4735 + store_uint64_be(ctx->recvSeq, &p[16]);
4738 + major = sequenceExternalize(minor, ctx->seqState, &p, &length);
4739 + if (GSS_ERROR(major))
4742 + if (partialCtx.value != NULL)
4743 + p = store_buffer(&partialCtx, p, FALSE);
4745 + GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
4747 + major = GSS_S_COMPLETE;
4751 + if (GSS_ERROR(major))
4752 + gss_release_buffer(&tmpMinor, token);
4753 + gss_release_buffer(&tmpMinor, &initiatorName);
4754 + gss_release_buffer(&tmpMinor, &acceptorName);
4755 + gss_release_buffer(&tmpMinor, &partialCtx);
4760 +OM_uint32 GSSAPI_CALLCONV
4761 +gss_export_sec_context(OM_uint32 *minor,
4762 + gss_ctx_id_t *context_handle,
4763 + gss_buffer_t interprocess_token)
4765 + OM_uint32 major, tmpMinor;
4766 + gss_ctx_id_t ctx = *context_handle;
4768 + interprocess_token->length = 0;
4769 + interprocess_token->value = NULL;
4771 + if (ctx == GSS_C_NO_CONTEXT) {
4773 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
4778 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4780 + major = gssEapExportSecContext(minor, ctx, interprocess_token);
4781 + if (GSS_ERROR(major)) {
4782 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4786 + *context_handle = GSS_C_NO_CONTEXT;
4788 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4790 + gssEapReleaseContext(&tmpMinor, &ctx);
4792 + return GSS_S_COMPLETE;
4794 diff --git a/mech_eap/get_mic.c b/mech_eap/get_mic.c
4795 new file mode 100644
4796 index 0000000..7161e9c
4798 +++ b/mech_eap/get_mic.c
4801 + * Copyright (c) 2011, JANET(UK)
4802 + * All rights reserved.
4804 + * Redistribution and use in source and binary forms, with or without
4805 + * modification, are permitted provided that the following conditions
4808 + * 1. Redistributions of source code must retain the above copyright
4809 + * notice, this list of conditions and the following disclaimer.
4811 + * 2. Redistributions in binary form must reproduce the above copyright
4812 + * notice, this list of conditions and the following disclaimer in the
4813 + * documentation and/or other materials provided with the distribution.
4815 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4816 + * may be used to endorse or promote products derived from this software
4817 + * without specific prior written permission.
4819 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4820 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4821 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4822 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4823 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4824 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4825 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4826 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4827 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4828 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4833 + * Message protection services: make a message integerity check.
4836 +#include "gssapiP_eap.h"
4838 +OM_uint32 GSSAPI_CALLCONV
4839 +gss_get_mic(OM_uint32 *minor,
4841 + gss_qop_t qop_req,
4842 + gss_buffer_t message_buffer,
4843 + gss_buffer_t message_token)
4846 + gss_iov_buffer_desc iov[2];
4848 + if (ctx == GSS_C_NO_CONTEXT) {
4850 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
4853 + if (qop_req != GSS_C_QOP_DEFAULT) {
4854 + *minor = GSSEAP_UNKNOWN_QOP;
4855 + return GSS_S_UNAVAILABLE;
4860 + message_token->value = NULL;
4861 + message_token->length = 0;
4863 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4865 + if (!CTX_IS_ESTABLISHED(ctx)) {
4866 + major = GSS_S_NO_CONTEXT;
4867 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
4871 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
4872 + iov[0].buffer = *message_buffer;
4874 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
4875 + iov[1].buffer.value = NULL;
4876 + iov[1].buffer.length = 0;
4878 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL, iov, 2, TOK_TYPE_MIC);
4879 + if (GSS_ERROR(major))
4882 + *message_token = iov[1].buffer;
4885 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4889 diff --git a/mech_eap/get_name_attribute.c b/mech_eap/get_name_attribute.c
4890 new file mode 100644
4891 index 0000000..a885823
4893 +++ b/mech_eap/get_name_attribute.c
4896 + * Copyright (c) 2011, JANET(UK)
4897 + * All rights reserved.
4899 + * Redistribution and use in source and binary forms, with or without
4900 + * modification, are permitted provided that the following conditions
4903 + * 1. Redistributions of source code must retain the above copyright
4904 + * notice, this list of conditions and the following disclaimer.
4906 + * 2. Redistributions in binary form must reproduce the above copyright
4907 + * notice, this list of conditions and the following disclaimer in the
4908 + * documentation and/or other materials provided with the distribution.
4910 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4911 + * may be used to endorse or promote products derived from this software
4912 + * without specific prior written permission.
4914 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4915 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4916 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4917 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4918 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4919 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4920 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4921 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4922 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4923 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4927 +#include "gssapiP_eap.h"
4930 + * Wrapper for retrieving a naming attribute.
4933 +OM_uint32 GSSAPI_CALLCONV
4934 +gss_get_name_attribute(OM_uint32 *minor,
4936 + gss_buffer_t attr,
4937 + int *authenticated,
4939 + gss_buffer_t value,
4940 + gss_buffer_t display_value,
4947 + if (name == GSS_C_NO_NAME) {
4949 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4952 + GSSEAP_MUTEX_LOCK(&name->mutex);
4954 + major = gssEapGetNameAttribute(minor, name, attr,
4955 + authenticated, complete,
4956 + value, display_value, more);
4958 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
4962 diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h
4963 new file mode 100644
4964 index 0000000..d1790a0
4966 +++ b/mech_eap/gssapiP_eap.h
4969 + * Copyright (c) 2011, JANET(UK)
4970 + * All rights reserved.
4972 + * Redistribution and use in source and binary forms, with or without
4973 + * modification, are permitted provided that the following conditions
4976 + * 1. Redistributions of source code must retain the above copyright
4977 + * notice, this list of conditions and the following disclaimer.
4979 + * 2. Redistributions in binary form must reproduce the above copyright
4980 + * notice, this list of conditions and the following disclaimer in the
4981 + * documentation and/or other materials provided with the distribution.
4983 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4984 + * may be used to endorse or promote products derived from this software
4985 + * without specific prior written permission.
4987 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4988 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4989 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4990 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4991 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4992 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4993 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4994 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4995 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4996 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5000 +#ifndef _GSSAPIP_EAP_H_
5001 +#define _GSSAPIP_EAP_H_ 1
5003 +#include "config.h"
5005 +#ifdef HAVE_HEIMDAL_VERSION
5006 +#define KRB5_DEPRECATED /* so we can use krb5_free_unparsed_name() */
5009 +#include <assert.h>
5010 +#include <string.h>
5012 +#ifdef HAVE_UNISTD_H
5013 +#include <unistd.h>
5015 +#ifdef HAVE_STDLIB_H
5016 +#include <stdlib.h>
5018 +#ifdef HAVE_STDARG_H
5019 +#include <stdarg.h>
5022 +#ifdef HAVE_SYS_PARAM_H
5023 +#include <sys/param.h>
5027 +#ifndef MAXHOSTNAMELEN
5028 +# include <WinSock2.h>
5029 +# define MAXHOSTNAMELEN NI_MAXHOST
5034 +#include <gssapi/gssapi.h>
5035 +#include <gssapi/gssapi_krb5.h>
5036 +#ifdef HAVE_HEIMDAL_VERSION
5037 +typedef struct gss_any *gss_any_t;
5039 +#include <gssapi/gssapi_ext.h>
5041 +#include "gssapi_eap.h"
5043 +#ifndef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
5044 +typedef const gss_OID_desc *gss_const_OID;
5047 +/* Kerberos headers */
5051 +#include <includes.h>
5052 +#include <common.h>
5053 +#include <eap_peer/eap.h>
5054 +#include <eap_peer/eap_config.h>
5055 +#include <eap_peer/eap_methods.h>
5056 +#include <eap_common/eap_common.h>
5057 +#include <wpabuf.h>
5059 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5060 +/* FreeRADIUS headers */
5064 +#define operator fr_operator
5067 +#include <freeradius/libradius.h>
5068 +#include <freeradius/radius.h>
5072 +/* libradsec headers */
5073 +#include <radsec/radsec.h>
5074 +#include <radsec/request.h>
5081 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
5083 +#include "gsseap_err.h"
5084 +#include "radsec_err.h"
5091 +/* These name flags are informative and not actually used by anything yet */
5092 +#define NAME_FLAG_NAI 0x00000001
5093 +#define NAME_FLAG_SERVICE 0x00000002
5094 +#define NAME_FLAG_COMPOSITE 0x00000004
5096 +struct gss_eap_saml_attr_ctx;
5097 +struct gss_eap_attr_ctx;
5099 +#ifdef HAVE_HEIMDAL_VERSION
5100 +struct gss_name_t_desc_struct
5102 +struct gss_name_struct
5105 + GSSEAP_MUTEX mutex; /* mutex protects attrCtx */
5107 + gss_OID mechanismUsed; /* this is immutable */
5108 + krb5_principal krbPrincipal; /* this is immutable */
5109 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5110 + struct gss_eap_attr_ctx *attrCtx;
5114 +#define CRED_FLAG_INITIATE 0x00010000
5115 +#define CRED_FLAG_ACCEPT 0x00020000
5116 +#define CRED_FLAG_PASSWORD 0x00040000
5117 +#define CRED_FLAG_DEFAULT_CCACHE 0x00080000
5118 +#define CRED_FLAG_RESOLVED 0x00100000
5119 +#define CRED_FLAG_TARGET 0x00200000
5120 +#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
5122 +#ifdef HAVE_HEIMDAL_VERSION
5123 +struct gss_cred_id_t_desc_struct
5125 +struct gss_cred_id_struct
5128 + GSSEAP_MUTEX mutex;
5131 + gss_name_t target; /* for initiator */
5132 + gss_buffer_desc password;
5133 + gss_OID_set mechanisms;
5134 + time_t expiryTime;
5135 + gss_buffer_desc radiusConfigFile;
5136 + gss_buffer_desc radiusConfigStanza;
5137 + gss_buffer_desc caCertificate;
5138 + gss_buffer_desc subjectNameConstraint;
5139 + gss_buffer_desc subjectAltNameConstraint;
5140 +#ifdef GSSEAP_ENABLE_REAUTH
5141 + krb5_ccache krbCredCache;
5142 + gss_cred_id_t reauthCred;
5146 +#define CTX_FLAG_INITIATOR 0x00000001
5147 +#define CTX_FLAG_KRB_REAUTH 0x00000002
5149 +#define CTX_IS_INITIATOR(ctx) (((ctx)->flags & CTX_FLAG_INITIATOR) != 0)
5151 +#define CTX_IS_ESTABLISHED(ctx) ((ctx)->state == GSSEAP_STATE_ESTABLISHED)
5153 +/* Initiator context flags */
5154 +#define CTX_FLAG_EAP_SUCCESS 0x00010000
5155 +#define CTX_FLAG_EAP_RESTART 0x00020000
5156 +#define CTX_FLAG_EAP_FAIL 0x00040000
5157 +#define CTX_FLAG_EAP_RESP 0x00080000
5158 +#define CTX_FLAG_EAP_NO_RESP 0x00100000
5159 +#define CTX_FLAG_EAP_REQ 0x00200000
5160 +#define CTX_FLAG_EAP_PORT_ENABLED 0x00400000
5161 +#define CTX_FLAG_EAP_ALT_ACCEPT 0x00800000
5162 +#define CTX_FLAG_EAP_ALT_REJECT 0x01000000
5163 +#define CTX_FLAG_EAP_MASK 0xFFFF0000
5165 +struct gss_eap_initiator_ctx {
5166 + unsigned int idleWhile;
5167 + struct eap_peer_config eapPeerConfig;
5168 + struct eap_sm *eap;
5169 + struct wpabuf reqData;
5172 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5173 +struct gss_eap_acceptor_ctx {
5174 + struct rs_context *radContext;
5175 + struct rs_connection *radConn;
5177 + gss_buffer_desc state;
5182 +#ifdef HAVE_HEIMDAL_VERSION
5183 +struct gss_ctx_id_t_desc_struct
5185 +struct gss_ctx_id_struct
5188 + GSSEAP_MUTEX mutex;
5189 + enum gss_eap_state state;
5191 + OM_uint32 gssFlags;
5192 + gss_OID mechanismUsed;
5193 + krb5_cksumtype checksumType;
5194 + krb5_enctype encryptionType;
5195 + krb5_keyblock rfc3961Key;
5196 + gss_name_t initiatorName;
5197 + gss_name_t acceptorName;
5198 + time_t expiryTime;
5199 + uint64_t sendSeq, recvSeq;
5201 + gss_cred_id_t cred;
5203 + struct gss_eap_initiator_ctx initiator;
5204 + #define initiatorCtx ctxU.initiator
5205 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5206 + struct gss_eap_acceptor_ctx acceptor;
5207 + #define acceptorCtx ctxU.acceptor
5209 +#ifdef GSSEAP_ENABLE_REAUTH
5210 + gss_ctx_id_t reauth;
5211 + #define reauthCtx ctxU.reauth
5214 + const struct gss_eap_token_buffer_set *inputTokens;
5215 + const struct gss_eap_token_buffer_set *outputTokens;
5218 +#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01
5219 +#define TOK_FLAG_WRAP_CONFIDENTIAL 0x02
5220 +#define TOK_FLAG_ACCEPTOR_SUBKEY 0x04
5222 +#define KEY_USAGE_ACCEPTOR_SEAL 22
5223 +#define KEY_USAGE_ACCEPTOR_SIGN 23
5224 +#define KEY_USAGE_INITIATOR_SEAL 24
5225 +#define KEY_USAGE_INITIATOR_SIGN 25
5227 +/* accept_sec_context.c */
5229 +gssEapAcceptSecContext(OM_uint32 *minor,
5231 + gss_cred_id_t cred,
5232 + gss_buffer_t input_token,
5233 + gss_channel_bindings_t input_chan_bindings,
5234 + gss_name_t *src_name,
5235 + gss_OID *mech_type,
5236 + gss_buffer_t output_token,
5237 + OM_uint32 *ret_flags,
5238 + OM_uint32 *time_rec,
5239 + gss_cred_id_t *delegated_cred_handle);
5241 +/* init_sec_context.c */
5243 +gssEapInitSecContext(OM_uint32 *minor,
5244 + gss_cred_id_t cred,
5246 + gss_name_t target_name,
5247 + gss_OID mech_type,
5248 + OM_uint32 req_flags,
5249 + OM_uint32 time_req,
5250 + gss_channel_bindings_t input_chan_bindings,
5251 + gss_buffer_t input_token,
5252 + gss_OID *actual_mech_type,
5253 + gss_buffer_t output_token,
5254 + OM_uint32 *ret_flags,
5255 + OM_uint32 *time_rec);
5259 +gssEapWrapOrGetMIC(OM_uint32 *minor,
5261 + int conf_req_flag,
5263 + gss_iov_buffer_desc *iov,
5265 + enum gss_eap_token_type toktype);
5268 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
5271 + gss_qop_t *qop_state,
5272 + gss_iov_buffer_desc *iov,
5274 + enum gss_eap_token_type toktype);
5277 +gssEapWrapIovLength(OM_uint32 *minor,
5279 + int conf_req_flag,
5280 + gss_qop_t qop_req,
5282 + gss_iov_buffer_desc *iov,
5285 +gssEapWrap(OM_uint32 *minor,
5287 + int conf_req_flag,
5288 + gss_qop_t qop_req,
5289 + gss_buffer_t input_message_buffer,
5291 + gss_buffer_t output_message_buffer);
5294 +rfc4121Flags(gss_ctx_id_t ctx, int receiving);
5296 +/* display_status.c */
5298 +gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...);
5301 +gssEapDisplayStatus(OM_uint32 *minor,
5302 + OM_uint32 status_value,
5303 + gss_buffer_t status_string);
5305 +#define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \
5306 + (err) <= GSSEAP_RADIUS_PROT_FAILURE)
5308 +/* upper bound of RADIUS error range must be kept in sync with radsec.h */
5309 +#define IS_RADIUS_ERROR(err) ((err) >= ERROR_TABLE_BASE_rse && \
5310 + (err) <= ERROR_TABLE_BASE_rse + 20)
5312 +/* exchange_meta_data.c */
5313 +OM_uint32 GSSAPI_CALLCONV
5314 +gssEapExchangeMetaData(OM_uint32 *minor,
5315 + gss_const_OID mech,
5316 + gss_cred_id_t cred,
5317 + gss_ctx_id_t *ctx,
5318 + const gss_name_t name,
5319 + OM_uint32 req_flags,
5320 + gss_const_buffer_t meta_data);
5322 +/* export_sec_context.c */
5324 +gssEapExportSecContext(OM_uint32 *minor,
5326 + gss_buffer_t token);
5328 +/* import_sec_context.c */
5330 +gssEapImportContext(OM_uint32 *minor,
5331 + gss_buffer_t token,
5332 + gss_ctx_id_t ctx);
5334 +/* inquire_sec_context_by_oid.c */
5335 +#define NEGOEX_INITIATOR_SALT "gss-eap-negoex-initiator"
5336 +#define NEGOEX_INITIATOR_SALT_LEN (sizeof(NEGOEX_INITIATOR_SALT) - 1)
5338 +#define NEGOEX_ACCEPTOR_SALT "gss-eap-negoex-acceptor"
5339 +#define NEGOEX_ACCEPTOR_SALT_LEN (sizeof(NEGOEX_ACCEPTOR_SALT) - 1)
5341 +/* pseudo_random.c */
5343 +gssEapPseudoRandom(OM_uint32 *minor,
5346 + const gss_buffer_t prf_in,
5347 + ssize_t desired_output_len,
5348 + gss_buffer_t prf_out);
5350 +/* query_mechanism_info.c */
5352 +gssQueryMechanismInfo(OM_uint32 *minor,
5353 + gss_const_OID mech_oid,
5354 + unsigned char auth_scheme[16]);
5356 +/* query_meta_data.c */
5358 +gssEapQueryMetaData(OM_uint32 *minor,
5359 + gss_const_OID mech GSSEAP_UNUSED,
5360 + gss_cred_id_t cred,
5361 + gss_ctx_id_t *context_handle,
5362 + const gss_name_t name,
5363 + OM_uint32 req_flags GSSEAP_UNUSED,
5364 + gss_buffer_t meta_data);
5368 +gssEapInitiatorInit(OM_uint32 *minor);
5371 +gssEapFinalize(void);
5377 +#endif /* _GSSAPIP_EAP_H_ */
5378 diff --git a/mech_eap/gssapi_eap.h b/mech_eap/gssapi_eap.h
5379 new file mode 100644
5380 index 0000000..588665b
5382 +++ b/mech_eap/gssapi_eap.h
5385 + * Copyright (c) 2011, JANET(UK)
5386 + * All rights reserved.
5388 + * Redistribution and use in source and binary forms, with or without
5389 + * modification, are permitted provided that the following conditions
5392 + * 1. Redistributions of source code must retain the above copyright
5393 + * notice, this list of conditions and the following disclaimer.
5395 + * 2. Redistributions in binary form must reproduce the above copyright
5396 + * notice, this list of conditions and the following disclaimer in the
5397 + * documentation and/or other materials provided with the distribution.
5399 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5400 + * may be used to endorse or promote products derived from this software
5401 + * without specific prior written permission.
5403 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5404 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5405 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5406 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5407 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5408 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5409 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5410 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5411 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5412 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5416 +#ifndef _GSSAPI_EAP_H_
5417 +#define _GSSAPI_EAP_H_ 1
5419 +#include <gssapi/gssapi.h>
5423 +#endif /* __cplusplus */
5426 + * GSS EAP mechanism OIDs.
5428 +extern gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM;
5429 +extern gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM;
5432 + * Mechanism name OID.
5434 +extern gss_OID GSS_EAP_NT_EAP_NAME;
5437 + * The libradsec configuration file; defaults to radsec.conf
5438 + * in the system configuration directory if unspecified.
5440 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE;
5443 + * The stanza in the libradsec configuration file; defaults
5444 + * to "gss-eap" if unspecified.
5446 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA;
5449 + * Flags as a 32-bit integer in network byte order,
5450 + * followed by a boolean octet indicating whether to
5451 + * clear the specified flags (if absent, defaults to
5452 + * FALSE, ie. set flags).
5454 +extern gss_OID GSS_EAP_CRED_SET_CRED_FLAG;
5457 + * Password; for mechanism glues that do not support
5458 + * gss_acquire_cred_with_password(), this can be set
5459 + * on an existing credentials handle.
5461 +extern gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD;
5464 + * Credentials flag indicating the local attributes
5465 + * processing should be skipped.
5467 +#define GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG 0x00000001
5471 +#endif /* __cplusplus */
5473 +#endif /* _GSSAPI_EAP_H_ */
5474 diff --git a/mech_eap/gsseap_err.et b/mech_eap/gsseap_err.et
5475 new file mode 100644
5476 index 0000000..d60c2c7
5478 +++ b/mech_eap/gsseap_err.et
5481 +# Copyright (c) 2011, JANET(UK)
5482 +# All rights reserved.
5484 +# Redistribution and use in source and binary forms, with or without
5485 +# modification, are permitted provided that the following conditions
5488 +# 1. Redistributions of source code must retain the above copyright
5489 +# notice, this list of conditions and the following disclaimer.
5491 +# 2. Redistributions in binary form must reproduce the above copyright
5492 +# notice, this list of conditions and the following disclaimer in the
5493 +# documentation and/or other materials provided with the distribution.
5495 +# 3. Neither the name of JANET(UK) nor the names of its contributors
5496 +# may be used to endorse or promote products derived from this software
5497 +# without specific prior written permission.
5499 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5500 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5501 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5502 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5503 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5504 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5505 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5506 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5507 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5508 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5515 +# Protocol errors that can be returned in an error token. This should match
5516 +# up with makeErrorToken in accept_sec_context.c.
5518 +error_code GSSEAP_RESERVED, ""
5519 +error_code GSSEAP_WRONG_SIZE, "Buffer is incorrect size"
5520 +error_code GSSEAP_WRONG_MECH, "Mechanism OID is incorrect"
5521 +error_code GSSEAP_BAD_TOK_HEADER, "Token header is malformed or corrupt"
5522 +error_code GSSEAP_TOK_TRUNC, "Token is missing data"
5523 +error_code GSSEAP_BAD_DIRECTION, "Packet was replayed in wrong direction"
5524 +error_code GSSEAP_WRONG_TOK_ID, "Received token ID does not match expected token ID"
5525 +error_code GSSEAP_CRIT_ITOK_UNAVAILABLE, "Critical inner token type unavailable"
5526 +error_code GSSEAP_MISSING_REQUIRED_ITOK, "Missing required inner token"
5527 +error_code GSSEAP_DUPLICATE_ITOK, "Duplicate inner token received"
5528 +error_code GSSEAP_WRONG_ITOK, "Recieved invalid inner token for current state"
5529 +error_code GSSEAP_KEY_UNAVAILABLE, "EAP key unavailable"
5530 +error_code GSSEAP_KEY_TOO_SHORT, "EAP key too short"
5531 +error_code GSSEAP_RADIUS_AUTH_FAILURE, "Authentication rejected by RADIUS server"
5532 +error_code GSSEAP_UNKNOWN_RADIUS_CODE, "Received unknown response code from RADIUS server"
5533 +error_code GSSEAP_MISSING_EAP_REQUEST, "RADIUS response is missing EAP request"
5534 +error_code GSSEAP_RADIUS_PROT_FAILURE, "Generic RADIUS failure"
5539 +error_code GSSEAP_CONTEXT_ESTABLISHED, "Context is already fully established"
5540 +error_code GSSEAP_CONTEXT_INCOMPLETE, "Attempt to use incomplete security context"
5541 +error_code GSSEAP_BAD_CONTEXT_TOKEN, "Context token is malformed or corrupt"
5542 +error_code GSSEAP_BAD_ERROR_TOKEN, "Error token is malformed or corrupt"
5543 +error_code GSSEAP_BAD_CONTEXT_OPTION, "Bad context option"
5548 +error_code GSSEAP_BAD_SERVICE_NAME, "Name is not a valid service name"
5549 +error_code GSSEAP_BAD_INITIATOR_NAME, "Initiator identity must be a valid name"
5550 +error_code GSSEAP_NO_HOSTNAME, "Could not determine local host name"
5551 +error_code GSSEAP_NO_ACCEPTOR_NAME, "Could not determine acceptor identity"
5552 +error_code GSSEAP_BAD_NAME_TOKEN, "Name token is malformed or corrupt"
5553 +error_code GSSEAP_NO_LOCAL_MAPPING, "Unable to map name to a local identity"
5556 +# Credential errors
5558 +error_code GSSEAP_BAD_USAGE, "Credential usage type is unknown"
5559 +error_code GSSEAP_CRED_USAGE_MISMATCH, "Credential usage does not match requested usage"
5560 +error_code GSSEAP_CRED_MECH_MISMATCH, "Credential is not usable with this mechanism"
5561 +error_code GSSEAP_CRED_EXPIRED, "Attributes indicate credentials have expired"
5562 +error_code GSSEAP_BAD_CRED_OPTION, "Bad credential option"
5563 +error_code GSSEAP_NO_DEFAULT_IDENTITY, "Default credentials identity unavailable"
5564 +error_code GSSEAP_NO_DEFAULT_CRED, "Missing default password or other credentials"
5565 +error_code GSSEAP_CRED_RESOLVED, "Credential is already fully resolved"
5568 +# Local identity service errors
5570 +error_code GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE, "Unable to start identity service"
5571 +error_code GSSEAP_NO_IDENTITY_SELECTED, "No identity selected"
5572 +error_code GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR, "Identity service installation error"
5573 +error_code GSSEAP_IDENTITY_SERVICE_OS_ERROR, "Identity service OS error"
5574 +error_code GSSEAP_IDENTITY_SERVICE_IPC_ERROR, "Identity service IPC error"
5575 +error_code GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR, "Unknown identity service error"
5578 +# Wrap/unwrap/PRF errors
5580 +error_code GSSEAP_BAD_WRAP_TOKEN, "Bad RFC 4121 wrap or MIC token"
5581 +error_code GSSEAP_MISSING_IOV, "IOV is missing required buffer"
5582 +error_code GSSEAP_BAD_STREAM_IOV, "Stream IOV can only contain a single data buffer"
5583 +error_code GSSEAP_BAD_PADDING_IOV, "Padding IOV is not permitted for RFC 4121 tokens"
5584 +error_code GSSEAP_UNKNOWN_QOP, "Unknown quality of protection specified"
5585 +error_code GSSEAP_INPUT_TOO_LONG, "PRF input too long"
5586 +error_code GSSEAP_BAD_PRF_KEY, "PRF key usage type is unknown"
5591 +error_code GSSEAP_LIBEAP_INIT_FAILURE, "Failed to initialize EAP library"
5592 +error_code GSSEAP_PEER_SM_INIT_FAILURE, "Failed to create EAP state machine"
5593 +error_code GSSEAP_PEER_SM_STEP_FAILURE, "Failed to step EAP state machine"
5594 +error_code GSSEAP_PEER_AUTH_FAILURE, "EAP peer authentication failure"
5595 +error_code GSSEAP_PEER_BAD_MESSAGE, "Received bad EAP message"
5598 +# RadSec initialisation errors
5600 +error_code GSSEAP_RADSEC_INIT_FAILURE, "Failed to initialize RadSec library"
5601 +error_code GSSEAP_RADSEC_CONTEXT_FAILURE, "Failed to create RadSec context"
5606 +error_code GSSEAP_NO_ATTR_CONTEXT, "Name has no attributes"
5607 +error_code GSSEAP_NO_ATTR_PROVIDERS, "Failed to initialize attribute providers"
5608 +error_code GSSEAP_NO_SUCH_ATTR, "Unknown naming attribute"
5609 +error_code GSSEAP_BAD_ATTR_TOKEN, "Serialised attributes are malformed or corrupt"
5610 +error_code GSSEAP_ATTR_CONTEXT_FAILURE, "Failed to initialize attribute context"
5615 +error_code GSSEAP_SAML_INIT_FAILURE, "Failed to initialize SAML library"
5616 +error_code GSSEAP_SAML_SEC_POLICY_FAILURE, "Failed to process SAML security policy"
5617 +error_code GSSEAP_SAML_BINDING_FAILURE, "Failed in SAML binding processing"
5618 +error_code GSSEAP_SAML_PROFILE_FAILURE, "Failed to process SAML profile"
5619 +error_code GSSEAP_SAML_FATAL_PROFILE_FAILURE, "Non-recoverable failure in SAML profile processing"
5620 +error_code GSSEAP_SAML_RETRY_PROFILE_FAILURE, "Temporary failure in SAML profile processing"
5621 +error_code GSSEAP_SAML_METADATA_FAILURE, "Failure related to SAML metadata use"
5624 +# Shibboleth errors
5626 +error_code GSSEAP_SHIB_INIT_FAILURE, "Failed to initialize Shibboleth"
5627 +error_code GSSEAP_SHIB_ATTR_FAILURE, "Failure during local attribute processing"
5628 +error_code GSSEAP_SHIB_ATTR_EXTRACT_FAILURE, "Failed to extract local attributes"
5629 +error_code GSSEAP_SHIB_ATTR_FILTER_FAILURE, "Failed to filter local attributes"
5630 +error_code GSSEAP_SHIB_ATTR_RESOLVE_FAILURE, "Failed to resolve local attributes"
5631 +error_code GSSEAP_SHIB_CONFIG_FAILURE, "Local attribute configuration failure"
5632 +error_code GSSEAP_SHIB_LISTENER_FAILURE, "Failed to communicate with local attribute server"
5637 +error_code GSSEAP_BINDINGS_MISMATCH, "Channel bindings do not match"
5638 +error_code GSSEAP_NO_MECHGLUE_SYMBOL, "Could not find symbol in mechanism glue"
5639 +error_code GSSEAP_BAD_INVOCATION, "Bad mechanism invoke OID"
5642 diff --git a/mech_eap/import_name.c b/mech_eap/import_name.c
5643 new file mode 100644
5644 index 0000000..8049e01
5646 +++ b/mech_eap/import_name.c
5649 + * Copyright (c) 2011, JANET(UK)
5650 + * All rights reserved.
5652 + * Redistribution and use in source and binary forms, with or without
5653 + * modification, are permitted provided that the following conditions
5656 + * 1. Redistributions of source code must retain the above copyright
5657 + * notice, this list of conditions and the following disclaimer.
5659 + * 2. Redistributions in binary form must reproduce the above copyright
5660 + * notice, this list of conditions and the following disclaimer in the
5661 + * documentation and/or other materials provided with the distribution.
5663 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5664 + * may be used to endorse or promote products derived from this software
5665 + * without specific prior written permission.
5667 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5668 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5669 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5670 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5671 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5672 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5673 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5674 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5675 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5676 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5681 + * Deserialise a name.
5684 +#include "gssapiP_eap.h"
5686 +OM_uint32 GSSAPI_CALLCONV
5687 +gss_import_name(OM_uint32 *minor,
5688 + gss_buffer_t import_name_buffer,
5689 + gss_OID input_name_type,
5690 + gss_name_t *output_name)
5692 + return gssEapImportName(minor, import_name_buffer,
5693 + input_name_type, GSS_C_NO_OID, output_name);
5695 diff --git a/mech_eap/import_sec_context.c b/mech_eap/import_sec_context.c
5696 new file mode 100644
5697 index 0000000..1533a16
5699 +++ b/mech_eap/import_sec_context.c
5702 + * Copyright (c) 2011, JANET(UK)
5703 + * All rights reserved.
5705 + * Redistribution and use in source and binary forms, with or without
5706 + * modification, are permitted provided that the following conditions
5709 + * 1. Redistributions of source code must retain the above copyright
5710 + * notice, this list of conditions and the following disclaimer.
5712 + * 2. Redistributions in binary form must reproduce the above copyright
5713 + * notice, this list of conditions and the following disclaimer in the
5714 + * documentation and/or other materials provided with the distribution.
5716 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5717 + * may be used to endorse or promote products derived from this software
5718 + * without specific prior written permission.
5720 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5721 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5722 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5723 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5724 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5725 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5726 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5727 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5728 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5729 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5734 + * Deserialise a context handle.
5737 +#include "gssapiP_eap.h"
5739 +#define UPDATE_REMAIN(n) do { \
5744 +#define CHECK_REMAIN(n) do { \
5745 + if (remain < (n)) { \
5746 + *minor = GSSEAP_TOK_TRUNC; \
5747 + return GSS_S_DEFECTIVE_TOKEN; \
5751 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5753 +gssEapImportPartialContext(OM_uint32 *minor,
5754 + unsigned char **pBuf,
5759 + unsigned char *p = *pBuf;
5760 + size_t remain = *pRemain;
5761 + gss_buffer_desc buf;
5762 + size_t ctxLength, serverLen;
5764 + /* Length of partial RADIUS context */
5766 + ctxLength = load_uint32_be(p);
5769 + CHECK_REMAIN(ctxLength);
5770 + remain = ctxLength; /* check against partial context length */
5772 + /* Selected RADIUS server */
5774 + serverLen = load_uint32_be(p);
5777 + if (serverLen != 0) {
5778 + CHECK_REMAIN(serverLen);
5780 + ctx->acceptorCtx.radServer = GSSEAP_MALLOC(serverLen + 1);
5781 + if (ctx->acceptorCtx.radServer == NULL) {
5783 + return GSS_S_FAILURE;
5785 + memcpy(ctx->acceptorCtx.radServer, p, serverLen);
5786 + ctx->acceptorCtx.radServer[serverLen] = '\0';
5788 + UPDATE_REMAIN(serverLen);
5791 + /* RADIUS state blob */
5793 + buf.length = load_uint32_be(p);
5796 + if (buf.length != 0) {
5797 + CHECK_REMAIN(buf.length);
5801 + major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state);
5802 + if (GSS_ERROR(major))
5805 + UPDATE_REMAIN(buf.length);
5808 +#ifdef GSSEAP_DEBUG
5809 + GSSEAP_ASSERT(remain == 0);
5813 + *pRemain -= 4 + ctxLength;
5815 + return GSS_S_COMPLETE;
5817 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
5820 +importMechanismOid(OM_uint32 *minor,
5821 + unsigned char **pBuf,
5826 + unsigned char *p = *pBuf;
5827 + size_t remain = *pRemain;
5828 + gss_OID_desc oidBuf;
5830 + oidBuf.length = load_uint32_be(p);
5831 + if (remain < 4 + oidBuf.length || oidBuf.length == 0) {
5832 + *minor = GSSEAP_TOK_TRUNC;
5833 + return GSS_S_DEFECTIVE_TOKEN;
5836 + oidBuf.elements = &p[4];
5838 + major = gssEapCanonicalizeOid(minor, &oidBuf, 0, pOid);
5839 + if (GSS_ERROR(major))
5842 + *pBuf += 4 + oidBuf.length;
5843 + *pRemain -= 4 + oidBuf.length;
5846 + return GSS_S_COMPLETE;
5850 +importKerberosKey(OM_uint32 *minor,
5851 + unsigned char **pBuf,
5853 + krb5_cksumtype *checksumType,
5854 + krb5_enctype *pEncryptionType,
5855 + krb5_keyblock *pKey)
5857 + unsigned char *p = *pBuf;
5858 + size_t remain = *pRemain;
5859 + OM_uint32 encryptionType;
5861 + krb5_context krbContext;
5862 + krb5_keyblock key;
5863 + krb5_error_code code;
5865 + GSSEAP_KRB_INIT(&krbContext);
5867 + KRB_KEY_INIT(pKey);
5869 + if (remain < 12) {
5870 + *minor = GSSEAP_TOK_TRUNC;
5871 + return GSS_S_DEFECTIVE_TOKEN;
5874 + *checksumType = load_uint32_be(&p[0]);
5875 + encryptionType = load_uint32_be(&p[4]);
5876 + length = load_uint32_be(&p[8]);
5878 + if ((length != 0) != (encryptionType != ENCTYPE_NULL)) {
5879 + *minor = GSSEAP_BAD_CONTEXT_TOKEN;
5880 + return GSS_S_DEFECTIVE_TOKEN;
5883 + if (remain - 12 < length) {
5884 + *minor = GSSEAP_TOK_TRUNC;
5885 + return GSS_S_DEFECTIVE_TOKEN;
5888 + if (encryptionType != ENCTYPE_NULL) {
5889 + KRB_KEY_INIT(&key);
5891 + KRB_KEY_TYPE(&key) = encryptionType;
5892 + KRB_KEY_LENGTH(&key) = length;
5893 + KRB_KEY_DATA(&key) = &p[12];
5895 + code = krb5_copy_keyblock_contents(krbContext, &key, pKey);
5898 + return GSS_S_FAILURE;
5902 + *pBuf += 12 + length;
5903 + *pRemain -= 12 + length;
5904 + *pEncryptionType = encryptionType;
5907 + return GSS_S_COMPLETE;
5911 +importName(OM_uint32 *minor,
5912 + unsigned char **pBuf,
5914 + gss_name_t *pName)
5917 + unsigned char *p = *pBuf;
5918 + size_t remain = *pRemain;
5919 + gss_buffer_desc tmp;
5922 + *minor = GSSEAP_TOK_TRUNC;
5923 + return GSS_S_DEFECTIVE_TOKEN;
5926 + tmp.length = load_uint32_be(p);
5927 + if (tmp.length != 0) {
5928 + if (remain - 4 < tmp.length) {
5929 + *minor = GSSEAP_TOK_TRUNC;
5930 + return GSS_S_DEFECTIVE_TOKEN;
5933 + tmp.value = p + 4;
5935 + major = gssEapImportNameInternal(minor, &tmp, pName,
5936 + EXPORT_NAME_FLAG_COMPOSITE);
5937 + if (GSS_ERROR(major))
5941 + *pBuf += 4 + tmp.length;
5942 + *pRemain -= 4 + tmp.length;
5945 + return GSS_S_COMPLETE;
5949 +gssEapImportContext(OM_uint32 *minor,
5950 + gss_buffer_t token,
5954 + unsigned char *p = (unsigned char *)token->value;
5955 + size_t remain = token->length;
5957 + if (remain < 16) {
5958 + *minor = GSSEAP_TOK_TRUNC;
5959 + return GSS_S_DEFECTIVE_TOKEN;
5961 + if (load_uint32_be(&p[0]) != EAP_EXPORT_CONTEXT_V1) {
5962 + *minor = GSSEAP_BAD_CONTEXT_TOKEN;
5963 + return GSS_S_DEFECTIVE_TOKEN;
5965 + ctx->state = load_uint32_be(&p[4]);
5966 + ctx->flags = load_uint32_be(&p[8]);
5967 + ctx->gssFlags = load_uint32_be(&p[12]);
5971 + /* Validate state */
5972 + if (GSSEAP_SM_STATE(ctx) < GSSEAP_STATE_INITIAL ||
5973 + GSSEAP_SM_STATE(ctx) > GSSEAP_STATE_ESTABLISHED)
5974 + return GSS_S_DEFECTIVE_TOKEN;
5976 + /* Only acceptor can export partial context tokens */
5977 + if (CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx))
5978 + return GSS_S_DEFECTIVE_TOKEN;
5980 + major = importMechanismOid(minor, &p, &remain, &ctx->mechanismUsed);
5981 + if (GSS_ERROR(major))
5984 + major = importKerberosKey(minor, &p, &remain,
5985 + &ctx->checksumType,
5986 + &ctx->encryptionType,
5987 + &ctx->rfc3961Key);
5988 + if (GSS_ERROR(major))
5991 + major = importName(minor, &p, &remain, &ctx->initiatorName);
5992 + if (GSS_ERROR(major))
5995 + major = importName(minor, &p, &remain, &ctx->acceptorName);
5996 + if (GSS_ERROR(major))
5999 + /* Check that, if context is established, names are valid */
6000 + if (CTX_IS_ESTABLISHED(ctx) &&
6001 + (CTX_IS_INITIATOR(ctx) ? ctx->acceptorName == GSS_C_NO_NAME
6002 + : ctx->initiatorName == GSS_C_NO_NAME)) {
6003 + return GSS_S_DEFECTIVE_TOKEN;
6006 + if (remain < 24 + sequenceSize(ctx->seqState)) {
6007 + *minor = GSSEAP_TOK_TRUNC;
6008 + return GSS_S_DEFECTIVE_TOKEN;
6010 + ctx->expiryTime = (time_t)load_uint64_be(&p[0]);
6011 + ctx->sendSeq = load_uint64_be(&p[8]);
6012 + ctx->recvSeq = load_uint64_be(&p[16]);
6016 + major = sequenceInternalize(minor, &ctx->seqState, &p, &remain);
6017 + if (GSS_ERROR(major))
6020 +#ifdef GSSEAP_ENABLE_ACCEPTOR
6022 + * The partial context should only be expected for unestablished
6023 + * acceptor contexts.
6025 + if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
6026 + (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
6027 + major = gssEapImportPartialContext(minor, &p, &remain, ctx);
6028 + if (GSS_ERROR(major))
6032 +#ifdef GSSEAP_DEBUG
6033 + GSSEAP_ASSERT(remain == 0);
6035 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
6037 + major = GSS_S_COMPLETE;
6043 +OM_uint32 GSSAPI_CALLCONV
6044 +gss_import_sec_context(OM_uint32 *minor,
6045 + gss_buffer_t interprocess_token,
6046 + gss_ctx_id_t *context_handle)
6048 + OM_uint32 major, tmpMinor;
6049 + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
6051 + *context_handle = GSS_C_NO_CONTEXT;
6053 + if (interprocess_token == GSS_C_NO_BUFFER ||
6054 + interprocess_token->length == 0) {
6055 + *minor = GSSEAP_TOK_TRUNC;
6056 + return GSS_S_DEFECTIVE_TOKEN;
6059 + major = gssEapAllocContext(minor, &ctx);
6060 + if (GSS_ERROR(major))
6063 + major = gssEapImportContext(minor, interprocess_token, ctx);
6064 + if (GSS_ERROR(major))
6067 + *context_handle = ctx;
6070 + if (GSS_ERROR(major))
6071 + gssEapReleaseContext(&tmpMinor, &ctx);
6075 diff --git a/mech_eap/indicate_mechs.c b/mech_eap/indicate_mechs.c
6076 new file mode 100644
6077 index 0000000..d4d275e
6079 +++ b/mech_eap/indicate_mechs.c
6082 + * Copyright (c) 2011, JANET(UK)
6083 + * All rights reserved.
6085 + * Redistribution and use in source and binary forms, with or without
6086 + * modification, are permitted provided that the following conditions
6089 + * 1. Redistributions of source code must retain the above copyright
6090 + * notice, this list of conditions and the following disclaimer.
6092 + * 2. Redistributions in binary form must reproduce the above copyright
6093 + * notice, this list of conditions and the following disclaimer in the
6094 + * documentation and/or other materials provided with the distribution.
6096 + * 3. Neither the name of JANET(UK) nor the names of its contributors
6097 + * may be used to endorse or promote products derived from this software
6098 + * without specific prior written permission.
6100 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6101 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6102 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6103 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
6104 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6105 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6106 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6107 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6108 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6109 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6114 + * Enumerate the supported mechanism OIDs.
6117 +#include "gssapiP_eap.h"
6119 +OM_uint32 GSSAPI_CALLCONV
6120 +gss_indicate_mechs(OM_uint32 *minor,
6121 + gss_OID_set *mech_set)
6123 + return gssEapIndicateMechs(minor, mech_set);
6125 diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c
6126 new file mode 100644
6127 index 0000000..e99b479
6129 +++ b/mech_eap/init_sec_context.c
6132 + * Copyright (c) 2011, JANET(UK)
6133 + * All rights reserved.
6135 + * Redistribution and use in source and binary forms, with or without
6136 + * modification, are permitted provided that the following conditions
6139 + * 1. Redistributions of source code must retain the above copyright
6140 + * notice, this list of conditions and the following disclaimer.
6142 + * 2. Redistributions in binary form must reproduce the above copyright
6143 + * notice, this list of conditions and the following disclaimer in the
6144 + * documentation and/or other materials provided with the distribution.
6146 + * 3. Neither the name of JANET(UK) nor the names of its contributors
6147 + * may be used to endorse or promote products derived from this software
6148 + * without specific prior written permission.
6150 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6151 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6152 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6153 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
6154 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6155 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6156 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6157 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6158 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6159 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6164 + * Establish a security context on the initiator (client). These functions
6165 + * wrap around libeap.
6168 +#include "gssapiP_eap.h"
6171 +policyVariableToFlag(enum eapol_bool_var variable)
6173 + OM_uint32 flag = 0;
6175 + switch (variable) {
6176 + case EAPOL_eapSuccess:
6177 + flag = CTX_FLAG_EAP_SUCCESS;
6179 + case EAPOL_eapRestart:
6180 + flag = CTX_FLAG_EAP_RESTART;
6182 + case EAPOL_eapFail:
6183 + flag = CTX_FLAG_EAP_FAIL;
6185 + case EAPOL_eapResp:
6186 + flag = CTX_FLAG_EAP_RESP;
6188 + case EAPOL_eapNoResp:
6189 + flag = CTX_FLAG_EAP_NO_RESP;
6191 + case EAPOL_eapReq:
6192 + flag = CTX_FLAG_EAP_REQ;
6194 + case EAPOL_portEnabled:
6195 + flag = CTX_FLAG_EAP_PORT_ENABLED;
6197 + case EAPOL_altAccept:
6198 + flag = CTX_FLAG_EAP_ALT_ACCEPT;
6200 + case EAPOL_altReject:
6201 + flag = CTX_FLAG_EAP_ALT_REJECT;
6208 +static struct eap_peer_config *
6209 +peerGetConfig(void *ctx)
6211 + gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
6213 + return &gssCtx->initiatorCtx.eapPeerConfig;
6217 +peerGetBool(void *data, enum eapol_bool_var variable)
6219 + gss_ctx_id_t ctx = data;
6222 + if (ctx == GSS_C_NO_CONTEXT)
6225 + flag = policyVariableToFlag(variable);
6227 + return ((ctx->flags & flag) != 0);
6231 +peerSetBool(void *data, enum eapol_bool_var variable,
6234 + gss_ctx_id_t ctx = data;
6237 + if (ctx == GSS_C_NO_CONTEXT)
6240 + flag = policyVariableToFlag(variable);
6243 + ctx->flags |= flag;
6245 + ctx->flags &= ~(flag);
6248 +static unsigned int
6249 +peerGetInt(void *data, enum eapol_int_var variable)
6251 + gss_ctx_id_t ctx = data;
6253 + if (ctx == GSS_C_NO_CONTEXT)
6256 + GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
6258 + switch (variable) {
6259 + case EAPOL_idleWhile:
6260 + return ctx->initiatorCtx.idleWhile;
6268 +peerSetInt(void *data, enum eapol_int_var variable,
6269 + unsigned int value)
6271 + gss_ctx_id_t ctx = data;
6273 + if (ctx == GSS_C_NO_CONTEXT)
6276 + GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
6278 + switch (variable) {
6279 + case EAPOL_idleWhile:
6280 + ctx->initiatorCtx.idleWhile = value;
6285 +static struct wpabuf *
6286 +peerGetEapReqData(void *ctx)
6288 + gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
6290 + return &gssCtx->initiatorCtx.reqData;
6294 +peerSetConfigBlob(void *ctx GSSEAP_UNUSED,
6295 + struct wpa_config_blob *blob GSSEAP_UNUSED)
6299 +static const struct wpa_config_blob *
6300 +peerGetConfigBlob(void *ctx GSSEAP_UNUSED,
6301 + const char *name GSSEAP_UNUSED)
6307 +peerNotifyPending(void *ctx GSSEAP_UNUSED)
6311 +static struct eapol_callbacks gssEapPolicyCallbacks = {
6317 + peerGetEapReqData,
6318 + peerSetConfigBlob,
6319 + peerGetConfigBlob,
6320 + peerNotifyPending,
6323 +#ifdef GSSEAP_DEBUG
6324 +extern int wpa_debug_level;
6328 +peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
6331 + krb5_context krbContext;
6332 + struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
6333 + gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
6334 + gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
6335 + gss_cred_id_t cred = ctx->cred;
6337 + eapPeerConfig->identity = NULL;
6338 + eapPeerConfig->identity_len = 0;
6339 + eapPeerConfig->anonymous_identity = NULL;
6340 + eapPeerConfig->anonymous_identity_len = 0;
6341 + eapPeerConfig->password = NULL;
6342 + eapPeerConfig->password_len = 0;
6344 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6346 + GSSEAP_KRB_INIT(&krbContext);
6348 + eapPeerConfig->fragment_size = 1024;
6349 +#ifdef GSSEAP_DEBUG
6350 + wpa_debug_level = 0;
6353 + GSSEAP_ASSERT(cred->name != GSS_C_NO_NAME);
6355 + if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) {
6356 + *minor = GSSEAP_BAD_INITIATOR_NAME;
6357 + return GSS_S_BAD_NAME;
6361 + major = gssEapDisplayName(minor, cred->name, &identity, NULL);
6362 + if (GSS_ERROR(major))
6365 + eapPeerConfig->identity = (unsigned char *)identity.value;
6366 + eapPeerConfig->identity_len = identity.length;
6368 + krbPrincRealmToGssBuffer(cred->name->krbPrincipal, &realm);
6370 + /* anonymous_identity */
6371 + eapPeerConfig->anonymous_identity = GSSEAP_MALLOC(realm.length + 2);
6372 + if (eapPeerConfig->anonymous_identity == NULL) {
6374 + return GSS_S_FAILURE;
6377 + eapPeerConfig->anonymous_identity[0] = '@';
6378 + memcpy(eapPeerConfig->anonymous_identity + 1, realm.value, realm.length);
6379 + eapPeerConfig->anonymous_identity[1 + realm.length] = '\0';
6380 + eapPeerConfig->anonymous_identity_len = 1 + realm.length;
6383 + eapPeerConfig->password = (unsigned char *)cred->password.value;
6384 + eapPeerConfig->password_len = cred->password.length;
6387 + eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
6388 + eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
6389 + eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
6392 + return GSS_S_COMPLETE;
6396 +peerConfigFree(OM_uint32 *minor,
6399 + struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
6401 + if (eapPeerConfig->identity != NULL) {
6402 + GSSEAP_FREE(eapPeerConfig->identity);
6403 + eapPeerConfig->identity = NULL;
6404 + eapPeerConfig->identity_len = 0;
6407 + if (eapPeerConfig->anonymous_identity != NULL) {
6408 + GSSEAP_FREE(eapPeerConfig->anonymous_identity);
6409 + eapPeerConfig->anonymous_identity = NULL;
6410 + eapPeerConfig->anonymous_identity_len = 0;
6414 + return GSS_S_COMPLETE;
6418 + * Mark an initiator context as ready for cryptographic operations
6421 +initReady(OM_uint32 *minor, gss_ctx_id_t ctx, OM_uint32 reqFlags)
6424 + const unsigned char *key;
6428 + /* XXX actually check for mutual auth */
6429 + if (reqFlags & GSS_C_MUTUAL_FLAG)
6430 + ctx->gssFlags |= GSS_C_MUTUAL_FLAG;
6433 + /* Cache encryption type derived from selected mechanism OID */
6434 + major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType);
6435 + if (GSS_ERROR(major))
6438 + if (!eap_key_available(ctx->initiatorCtx.eap)) {
6439 + *minor = GSSEAP_KEY_UNAVAILABLE;
6440 + return GSS_S_UNAVAILABLE;
6443 + key = eap_get_eapKeyData(ctx->initiatorCtx.eap, &keyLength);
6445 + if (keyLength < EAP_EMSK_LEN) {
6446 + *minor = GSSEAP_KEY_TOO_SHORT;
6447 + return GSS_S_UNAVAILABLE;
6450 + major = gssEapDeriveRfc3961Key(minor,
6451 + &key[EAP_EMSK_LEN / 2],
6453 + ctx->encryptionType,
6454 + &ctx->rfc3961Key);
6455 + if (GSS_ERROR(major))
6458 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
6459 + &ctx->checksumType);
6460 + if (GSS_ERROR(major))
6463 + major = sequenceInit(minor,
6466 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
6467 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
6469 + if (GSS_ERROR(major))
6473 + return GSS_S_COMPLETE;
6477 +initBegin(OM_uint32 *minor,
6479 + gss_name_t target,
6481 + OM_uint32 reqFlags GSSEAP_UNUSED,
6482 + OM_uint32 timeReq,
6483 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
6486 + gss_cred_id_t cred = ctx->cred;
6488 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6490 + if (cred->expiryTime)
6491 + ctx->expiryTime = cred->expiryTime;
6492 + else if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
6493 + ctx->expiryTime = 0;
6495 + ctx->expiryTime = time(NULL) + timeReq;
6498 + * The credential mutex protects its name, however we need to
6499 + * explicitly lock the acceptor name (unlikely as it may be
6500 + * that it has attributes set on it).
6502 + major = gssEapDuplicateName(minor, cred->name, &ctx->initiatorName);
6503 + if (GSS_ERROR(major))
6506 + if (target != GSS_C_NO_NAME) {
6507 + GSSEAP_MUTEX_LOCK(&target->mutex);
6509 + major = gssEapDuplicateName(minor, target, &ctx->acceptorName);
6510 + if (GSS_ERROR(major)) {
6511 + GSSEAP_MUTEX_UNLOCK(&target->mutex);
6515 + GSSEAP_MUTEX_UNLOCK(&target->mutex);
6518 + major = gssEapCanonicalizeOid(minor,
6520 + OID_FLAG_NULL_VALID | OID_FLAG_MAP_NULL_TO_DEFAULT_MECH,
6521 + &ctx->mechanismUsed);
6522 + if (GSS_ERROR(major))
6525 + /* If credentials were provided, check they're usable with this mech */
6526 + if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
6527 + *minor = GSSEAP_CRED_MECH_MISMATCH;
6528 + return GSS_S_BAD_MECH;
6532 + return GSS_S_COMPLETE;
6536 +eapGssSmInitError(OM_uint32 *minor,
6537 + gss_cred_id_t cred GSSEAP_UNUSED,
6538 + gss_ctx_id_t ctx GSSEAP_UNUSED,
6539 + gss_name_t target GSSEAP_UNUSED,
6540 + gss_OID mech GSSEAP_UNUSED,
6541 + OM_uint32 reqFlags GSSEAP_UNUSED,
6542 + OM_uint32 timeReq GSSEAP_UNUSED,
6543 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6544 + gss_buffer_t inputToken,
6545 + gss_buffer_t outputToken GSSEAP_UNUSED,
6546 + OM_uint32 *smFlags GSSEAP_UNUSED)
6551 + if (inputToken->length < 8) {
6552 + *minor = GSSEAP_TOK_TRUNC;
6553 + return GSS_S_DEFECTIVE_TOKEN;
6556 + p = (unsigned char *)inputToken->value;
6558 + major = load_uint32_be(&p[0]);
6559 + *minor = ERROR_TABLE_BASE_eapg + load_uint32_be(&p[4]);
6561 + if (!GSS_ERROR(major) || !IS_WIRE_ERROR(*minor)) {
6562 + major = GSS_S_FAILURE;
6563 + *minor = GSSEAP_BAD_ERROR_TOKEN;
6566 + GSSEAP_ASSERT(GSS_ERROR(major));
6571 +#ifdef GSSEAP_ENABLE_REAUTH
6573 +eapGssSmInitGssReauth(OM_uint32 *minor,
6574 + gss_cred_id_t cred,
6576 + gss_name_t target,
6577 + gss_OID mech GSSEAP_UNUSED,
6578 + OM_uint32 reqFlags,
6579 + OM_uint32 timeReq,
6580 + gss_channel_bindings_t chanBindings,
6581 + gss_buffer_t inputToken,
6582 + gss_buffer_t outputToken,
6583 + OM_uint32 *smFlags GSSEAP_UNUSED)
6585 + OM_uint32 major, tmpMinor;
6586 + gss_name_t mechTarget = GSS_C_NO_NAME;
6587 + gss_OID actualMech = GSS_C_NO_OID;
6588 + OM_uint32 gssFlags, timeRec;
6591 + * Here we use the passed in credential handle because the resolved
6592 + * context credential does not currently have the reauth creds.
6594 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL) {
6595 + if (!gssEapCanReauthP(cred, target, timeReq))
6596 + return GSS_S_CONTINUE_NEEDED;
6598 + ctx->flags |= CTX_FLAG_KRB_REAUTH;
6599 + } else if ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
6600 + major = GSS_S_DEFECTIVE_TOKEN;
6601 + *minor = GSSEAP_WRONG_ITOK;
6605 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6607 + major = gssEapMechToGlueName(minor, target, &mechTarget);
6608 + if (GSS_ERROR(major))
6611 + major = gssInitSecContext(minor,
6615 + (gss_OID)gss_mech_krb5,
6616 + reqFlags | GSS_C_MUTUAL_FLAG,
6624 + if (GSS_ERROR(major))
6627 + ctx->gssFlags = gssFlags;
6629 + if (major == GSS_S_COMPLETE) {
6630 + GSSEAP_ASSERT(GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE);
6632 + major = gssEapReauthComplete(minor, ctx, cred, actualMech, timeRec);
6633 + if (GSS_ERROR(major))
6635 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
6637 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE);
6641 + gssReleaseName(&tmpMinor, &mechTarget);
6645 +#endif /* GSSEAP_ENABLE_REAUTH */
6647 +#ifdef GSSEAP_DEBUG
6649 +eapGssSmInitVendorInfo(OM_uint32 *minor,
6650 + gss_cred_id_t cred GSSEAP_UNUSED,
6651 + gss_ctx_id_t ctx GSSEAP_UNUSED,
6652 + gss_name_t target GSSEAP_UNUSED,
6653 + gss_OID mech GSSEAP_UNUSED,
6654 + OM_uint32 reqFlags GSSEAP_UNUSED,
6655 + OM_uint32 timeReq GSSEAP_UNUSED,
6656 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6657 + gss_buffer_t inputToken GSSEAP_UNUSED,
6658 + gss_buffer_t outputToken,
6659 + OM_uint32 *smFlags GSSEAP_UNUSED)
6663 + major = makeStringBuffer(minor, "JANET(UK)", outputToken);
6664 + if (GSS_ERROR(major))
6667 + return GSS_S_CONTINUE_NEEDED;
6672 +eapGssSmInitAcceptorName(OM_uint32 *minor,
6673 + gss_cred_id_t cred GSSEAP_UNUSED,
6675 + gss_name_t target GSSEAP_UNUSED,
6676 + gss_OID mech GSSEAP_UNUSED,
6677 + OM_uint32 reqFlags GSSEAP_UNUSED,
6678 + OM_uint32 timeReq GSSEAP_UNUSED,
6679 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6680 + gss_buffer_t inputToken GSSEAP_UNUSED,
6681 + gss_buffer_t outputToken,
6682 + OM_uint32 *smFlags GSSEAP_UNUSED)
6686 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL &&
6687 + ctx->acceptorName != GSS_C_NO_NAME) {
6689 + /* Send desired target name to acceptor */
6690 + major = gssEapDisplayName(minor, ctx->acceptorName,
6691 + outputToken, NULL);
6692 + if (GSS_ERROR(major))
6694 + } else if (inputToken != GSS_C_NO_BUFFER &&
6695 + ctx->acceptorName == GSS_C_NO_NAME) {
6696 + /* Accept target name hint from acceptor */
6697 + major = gssEapImportName(minor, inputToken,
6698 + GSS_C_NT_USER_NAME,
6699 + ctx->mechanismUsed,
6700 + &ctx->acceptorName);
6701 + if (GSS_ERROR(major))
6706 + * Currently, other parts of the code assume that the acceptor name
6707 + * is available, hence this check.
6709 + if (ctx->acceptorName == GSS_C_NO_NAME) {
6710 + *minor = GSSEAP_NO_ACCEPTOR_NAME;
6711 + return GSS_S_FAILURE;
6714 + return GSS_S_CONTINUE_NEEDED;
6718 +eapGssSmInitIdentity(OM_uint32 *minor,
6719 + gss_cred_id_t cred GSSEAP_UNUSED,
6721 + gss_name_t target GSSEAP_UNUSED,
6722 + gss_OID mech GSSEAP_UNUSED,
6723 + OM_uint32 reqFlags GSSEAP_UNUSED,
6724 + OM_uint32 timeReq GSSEAP_UNUSED,
6725 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6726 + gss_buffer_t inputToken GSSEAP_UNUSED,
6727 + gss_buffer_t outputToken GSSEAP_UNUSED,
6728 + OM_uint32 *smFlags)
6730 + struct eap_config eapConfig;
6732 +#ifdef GSSEAP_ENABLE_REAUTH
6733 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) {
6734 + OM_uint32 tmpMinor;
6736 + /* server didn't support reauthentication, sent EAP request */
6737 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
6738 + ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
6739 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
6742 + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
6744 + GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
6745 + GSSEAP_ASSERT(inputToken == GSS_C_NO_BUFFER);
6747 + memset(&eapConfig, 0, sizeof(eapConfig));
6749 + ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
6750 + &gssEapPolicyCallbacks,
6753 + if (ctx->initiatorCtx.eap == NULL) {
6754 + *minor = GSSEAP_PEER_SM_INIT_FAILURE;
6755 + return GSS_S_FAILURE;
6758 + ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED;
6760 + /* poke EAP state machine */
6761 + if (eap_peer_sm_step(ctx->initiatorCtx.eap) != 0) {
6762 + *minor = GSSEAP_PEER_SM_STEP_FAILURE;
6763 + return GSS_S_FAILURE;
6766 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6770 + return GSS_S_CONTINUE_NEEDED;
6774 +eapGssSmInitAuthenticate(OM_uint32 *minor,
6775 + gss_cred_id_t cred GSSEAP_UNUSED,
6777 + gss_name_t target GSSEAP_UNUSED,
6778 + gss_OID mech GSSEAP_UNUSED,
6779 + OM_uint32 reqFlags GSSEAP_UNUSED,
6780 + OM_uint32 timeReq GSSEAP_UNUSED,
6781 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6782 + gss_buffer_t inputToken GSSEAP_UNUSED,
6783 + gss_buffer_t outputToken,
6784 + OM_uint32 *smFlags)
6787 + OM_uint32 tmpMinor;
6788 + struct wpabuf *resp = NULL;
6792 + GSSEAP_ASSERT(inputToken != GSS_C_NO_BUFFER);
6794 + major = peerConfigInit(minor, ctx);
6795 + if (GSS_ERROR(major))
6798 + GSSEAP_ASSERT(ctx->initiatorCtx.eap != NULL);
6799 + GSSEAP_ASSERT(ctx->flags & CTX_FLAG_EAP_PORT_ENABLED);
6801 + ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
6803 + wpabuf_set(&ctx->initiatorCtx.reqData,
6804 + inputToken->value, inputToken->length);
6806 + major = GSS_S_CONTINUE_NEEDED;
6808 + eap_peer_sm_step(ctx->initiatorCtx.eap);
6809 + if (ctx->flags & CTX_FLAG_EAP_RESP) {
6810 + ctx->flags &= ~(CTX_FLAG_EAP_RESP);
6812 + resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
6813 + } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
6814 + major = initReady(minor, ctx, reqFlags);
6815 + if (GSS_ERROR(major))
6818 + ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
6819 + major = GSS_S_CONTINUE_NEEDED;
6820 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6821 + } else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
6822 + major = GSS_S_DEFECTIVE_CREDENTIAL;
6823 + *minor = GSSEAP_PEER_AUTH_FAILURE;
6825 + major = GSS_S_DEFECTIVE_TOKEN;
6826 + *minor = GSSEAP_PEER_BAD_MESSAGE;
6830 + if (resp != NULL) {
6831 + OM_uint32 tmpMajor;
6832 + gss_buffer_desc respBuf;
6834 + GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
6836 + respBuf.length = wpabuf_len(resp);
6837 + respBuf.value = (void *)wpabuf_head(resp);
6839 + tmpMajor = duplicateBuffer(&tmpMinor, &respBuf, outputToken);
6840 + if (GSS_ERROR(tmpMajor)) {
6842 + *minor = tmpMinor;
6845 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6848 + wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0);
6849 + peerConfigFree(&tmpMinor, ctx);
6855 +eapGssSmInitGssFlags(OM_uint32 *minor,
6856 + gss_cred_id_t cred GSSEAP_UNUSED,
6858 + gss_name_t target GSSEAP_UNUSED,
6859 + gss_OID mech GSSEAP_UNUSED,
6860 + OM_uint32 reqFlags GSSEAP_UNUSED,
6861 + OM_uint32 timeReq GSSEAP_UNUSED,
6862 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6863 + gss_buffer_t inputToken GSSEAP_UNUSED,
6864 + gss_buffer_t outputToken,
6865 + OM_uint32 *smFlags GSSEAP_UNUSED)
6867 + unsigned char wireFlags[4];
6868 + gss_buffer_desc flagsBuf;
6870 + store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
6872 + flagsBuf.length = sizeof(wireFlags);
6873 + flagsBuf.value = wireFlags;
6875 + return duplicateBuffer(minor, &flagsBuf, outputToken);
6879 +eapGssSmInitGssChannelBindings(OM_uint32 *minor,
6880 + gss_cred_id_t cred GSSEAP_UNUSED,
6882 + gss_name_t target GSSEAP_UNUSED,
6883 + gss_OID mech GSSEAP_UNUSED,
6884 + OM_uint32 reqFlags GSSEAP_UNUSED,
6885 + OM_uint32 timeReq GSSEAP_UNUSED,
6886 + gss_channel_bindings_t chanBindings,
6887 + gss_buffer_t inputToken GSSEAP_UNUSED,
6888 + gss_buffer_t outputToken,
6889 + OM_uint32 *smFlags)
6892 + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
6894 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
6895 + buffer = chanBindings->application_data;
6897 + major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
6898 + &buffer, NULL, outputToken);
6899 + if (GSS_ERROR(major))
6902 + GSSEAP_ASSERT(outputToken->value != NULL);
6905 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6907 + return GSS_S_CONTINUE_NEEDED;
6911 +eapGssSmInitInitiatorMIC(OM_uint32 *minor,
6912 + gss_cred_id_t cred GSSEAP_UNUSED,
6914 + gss_name_t target GSSEAP_UNUSED,
6915 + gss_OID mech GSSEAP_UNUSED,
6916 + OM_uint32 reqFlags GSSEAP_UNUSED,
6917 + OM_uint32 timeReq GSSEAP_UNUSED,
6918 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6919 + gss_buffer_t inputToken GSSEAP_UNUSED,
6920 + gss_buffer_t outputToken,
6921 + OM_uint32 *smFlags)
6925 + major = gssEapMakeTokenMIC(minor, ctx, outputToken);
6926 + if (GSS_ERROR(major))
6929 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6932 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6934 + return GSS_S_CONTINUE_NEEDED;
6937 +#ifdef GSSEAP_ENABLE_REAUTH
6939 +eapGssSmInitReauthCreds(OM_uint32 *minor,
6940 + gss_cred_id_t cred,
6942 + gss_name_t target GSSEAP_UNUSED,
6943 + gss_OID mech GSSEAP_UNUSED,
6944 + OM_uint32 reqFlags GSSEAP_UNUSED,
6945 + OM_uint32 timeReq GSSEAP_UNUSED,
6946 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6947 + gss_buffer_t inputToken,
6948 + gss_buffer_t outputToken GSSEAP_UNUSED,
6949 + OM_uint32 *smFlags GSSEAP_UNUSED)
6953 + if (ctx->gssFlags & GSS_C_MUTUAL_FLAG) {
6954 + major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
6955 + if (GSS_ERROR(major))
6960 + return GSS_S_CONTINUE_NEEDED;
6962 +#endif /* GSSEAP_ENABLE_REAUTH */
6965 +eapGssSmInitAcceptorMIC(OM_uint32 *minor,
6966 + gss_cred_id_t cred GSSEAP_UNUSED,
6968 + gss_name_t target GSSEAP_UNUSED,
6969 + gss_OID mech GSSEAP_UNUSED,
6970 + OM_uint32 reqFlags GSSEAP_UNUSED,
6971 + OM_uint32 timeReq GSSEAP_UNUSED,
6972 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6973 + gss_buffer_t inputToken,
6974 + gss_buffer_t outputToken GSSEAP_UNUSED,
6975 + OM_uint32 *smFlags GSSEAP_UNUSED)
6979 + major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
6980 + if (GSS_ERROR(major))
6983 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
6987 + return GSS_S_COMPLETE;
6990 +static struct gss_eap_sm eapGssInitiatorSm[] = {
6992 + ITOK_TYPE_CONTEXT_ERR,
6994 + GSSEAP_STATE_ALL & ~(GSSEAP_STATE_INITIAL),
6999 + ITOK_TYPE_ACCEPTOR_NAME_RESP,
7000 + ITOK_TYPE_ACCEPTOR_NAME_REQ,
7001 + GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE,
7003 + eapGssSmInitAcceptorName
7005 +#ifdef GSSEAP_DEBUG
7008 + ITOK_TYPE_VENDOR_INFO,
7009 + GSSEAP_STATE_INITIAL,
7011 + eapGssSmInitVendorInfo
7014 +#ifdef GSSEAP_ENABLE_REAUTH
7016 + ITOK_TYPE_REAUTH_RESP,
7017 + ITOK_TYPE_REAUTH_REQ,
7018 + GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE,
7020 + eapGssSmInitGssReauth
7026 +#ifdef GSSEAP_ENABLE_REAUTH
7027 + GSSEAP_STATE_REAUTHENTICATE |
7029 + GSSEAP_STATE_INITIAL,
7030 + SM_ITOK_FLAG_REQUIRED,
7031 + eapGssSmInitIdentity
7034 + ITOK_TYPE_EAP_REQ,
7035 + ITOK_TYPE_EAP_RESP,
7036 + GSSEAP_STATE_AUTHENTICATE,
7037 + SM_ITOK_FLAG_REQUIRED,
7038 + eapGssSmInitAuthenticate
7042 + ITOK_TYPE_GSS_FLAGS,
7043 + GSSEAP_STATE_INITIATOR_EXTS,
7045 + eapGssSmInitGssFlags
7049 + ITOK_TYPE_GSS_CHANNEL_BINDINGS,
7050 + GSSEAP_STATE_INITIATOR_EXTS,
7051 + SM_ITOK_FLAG_REQUIRED,
7052 + eapGssSmInitGssChannelBindings
7056 + ITOK_TYPE_INITIATOR_MIC,
7057 + GSSEAP_STATE_INITIATOR_EXTS,
7058 + SM_ITOK_FLAG_REQUIRED,
7059 + eapGssSmInitInitiatorMIC
7061 +#ifdef GSSEAP_ENABLE_REAUTH
7063 + ITOK_TYPE_REAUTH_CREDS,
7065 + GSSEAP_STATE_ACCEPTOR_EXTS,
7067 + eapGssSmInitReauthCreds
7070 + /* other extensions go here */
7072 + ITOK_TYPE_ACCEPTOR_MIC,
7074 + GSSEAP_STATE_ACCEPTOR_EXTS,
7075 + SM_ITOK_FLAG_REQUIRED,
7076 + eapGssSmInitAcceptorMIC
7081 +gssEapInitSecContext(OM_uint32 *minor,
7082 + gss_cred_id_t cred,
7084 + gss_name_t target_name,
7085 + gss_OID mech_type,
7086 + OM_uint32 req_flags,
7087 + OM_uint32 time_req,
7088 + gss_channel_bindings_t input_chan_bindings,
7089 + gss_buffer_t input_token,
7090 + gss_OID *actual_mech_type,
7091 + gss_buffer_t output_token,
7092 + OM_uint32 *ret_flags,
7093 + OM_uint32 *time_rec)
7095 + OM_uint32 major, tmpMinor;
7096 + int initialContextToken = (ctx->mechanismUsed == GSS_C_NO_OID);
7099 + * XXX is acquiring the credential lock here necessary? The password is
7100 + * mutable but the contract could specify that this is not updated whilst
7101 + * a context is being initialized.
7103 + if (cred != GSS_C_NO_CREDENTIAL)
7104 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7106 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
7107 + major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
7108 + if (GSS_ERROR(major))
7111 + GSSEAP_ASSERT(ctx->cred != GSS_C_NO_CREDENTIAL);
7114 + GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
7116 + GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_RESOLVED);
7117 + GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_INITIATE);
7119 + if (initialContextToken) {
7120 + major = initBegin(minor, ctx, target_name, mech_type,
7121 + req_flags, time_req, input_chan_bindings);
7122 + if (GSS_ERROR(major))
7126 + major = gssEapSmStep(minor,
7133 + input_chan_bindings,
7136 + eapGssInitiatorSm,
7137 + sizeof(eapGssInitiatorSm) / sizeof(eapGssInitiatorSm[0]));
7138 + if (GSS_ERROR(major))
7141 + if (actual_mech_type != NULL) {
7142 + OM_uint32 tmpMajor;
7144 + tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, actual_mech_type);
7145 + if (GSS_ERROR(tmpMajor)) {
7147 + *minor = tmpMinor;
7151 + if (ret_flags != NULL)
7152 + *ret_flags = ctx->gssFlags;
7153 + if (time_rec != NULL)
7154 + gssEapContextTime(&tmpMinor, ctx, time_rec);
7156 + GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
7159 + if (cred != GSS_C_NO_CREDENTIAL)
7160 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7161 + if (ctx->cred != GSS_C_NO_CREDENTIAL)
7162 + GSSEAP_MUTEX_UNLOCK(&ctx->cred->mutex);
7167 +OM_uint32 GSSAPI_CALLCONV
7168 +gss_init_sec_context(OM_uint32 *minor,
7169 + gss_cred_id_t cred,
7170 + gss_ctx_id_t *context_handle,
7171 + gss_name_t target_name,
7172 + gss_OID mech_type,
7173 + OM_uint32 req_flags,
7174 + OM_uint32 time_req,
7175 + gss_channel_bindings_t input_chan_bindings,
7176 + gss_buffer_t input_token,
7177 + gss_OID *actual_mech_type,
7178 + gss_buffer_t output_token,
7179 + OM_uint32 *ret_flags,
7180 + OM_uint32 *time_rec)
7182 + OM_uint32 major, tmpMinor;
7183 + gss_ctx_id_t ctx = *context_handle;
7187 + output_token->length = 0;
7188 + output_token->value = NULL;
7190 + if (ctx == GSS_C_NO_CONTEXT) {
7191 + if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
7192 + *minor = GSSEAP_WRONG_SIZE;
7193 + return GSS_S_DEFECTIVE_TOKEN;
7196 + major = gssEapAllocContext(minor, &ctx);
7197 + if (GSS_ERROR(major))
7200 + ctx->flags |= CTX_FLAG_INITIATOR;
7202 + *context_handle = ctx;
7205 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
7207 + major = gssEapInitSecContext(minor,
7214 + input_chan_bindings,
7221 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
7223 + if (GSS_ERROR(major))
7224 + gssEapReleaseContext(&tmpMinor, context_handle);
7228 diff --git a/mech_eap/inquire_attrs_for_mech.c b/mech_eap/inquire_attrs_for_mech.c
7229 new file mode 100644
7230 index 0000000..a359f68
7232 +++ b/mech_eap/inquire_attrs_for_mech.c
7235 + * Copyright (c) 2011, JANET(UK)
7236 + * All rights reserved.
7238 + * Redistribution and use in source and binary forms, with or without
7239 + * modification, are permitted provided that the following conditions
7242 + * 1. Redistributions of source code must retain the above copyright
7243 + * notice, this list of conditions and the following disclaimer.
7245 + * 2. Redistributions in binary form must reproduce the above copyright
7246 + * notice, this list of conditions and the following disclaimer in the
7247 + * documentation and/or other materials provided with the distribution.
7249 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7250 + * may be used to endorse or promote products derived from this software
7251 + * without specific prior written permission.
7253 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7254 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7255 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7256 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7257 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7258 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7259 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7260 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7261 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7262 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7267 + * Enumerate the features supported by the GSS EAP mechanism.
7270 +#include "gssapiP_eap.h"
7272 +#define MA_ADD(ma, set) do { \
7273 + major = gss_add_oid_set_member(minor, (gss_OID)(ma), (set)); \
7274 + if (GSS_ERROR(major)) \
7278 +#define MA_SUPPORTED(ma) MA_ADD((ma), mech_attrs)
7279 +#define MA_KNOWN(ma) MA_ADD((ma), known_mech_attrs)
7281 +OM_uint32 GSSAPI_CALLCONV
7282 +gss_inquire_attrs_for_mech(OM_uint32 *minor,
7283 + gss_const_OID mech_oid,
7284 + gss_OID_set *mech_attrs,
7285 + gss_OID_set *known_mech_attrs)
7287 + OM_uint32 major, tmpMinor;
7289 + if (mech_attrs != NULL)
7290 + *mech_attrs = GSS_C_NO_OID_SET;
7291 + if (known_mech_attrs != NULL)
7292 + *known_mech_attrs = GSS_C_NO_OID_SET;
7294 + if (!gssEapIsConcreteMechanismOid((const gss_OID)mech_oid)) {
7295 + *minor = GSSEAP_WRONG_MECH;
7296 + return GSS_S_BAD_MECH;
7299 + if (mech_attrs != NULL) {
7300 + major = gss_create_empty_oid_set(minor, mech_attrs);
7301 + if (GSS_ERROR(major))
7304 +#ifdef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
7305 + if (oidEqual(mech_oid, GSS_EAP_MECHANISM))
7306 + MA_SUPPORTED(GSS_C_MA_MECH_PSEUDO);
7308 + MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE);
7309 + MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
7310 + MA_SUPPORTED(GSS_C_MA_AUTH_INIT);
7311 + MA_SUPPORTED(GSS_C_MA_AUTH_TARG);
7312 + MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT);
7313 + MA_SUPPORTED(GSS_C_MA_INTEG_PROT);
7314 + MA_SUPPORTED(GSS_C_MA_CONF_PROT);
7315 + MA_SUPPORTED(GSS_C_MA_MIC);
7316 + MA_SUPPORTED(GSS_C_MA_WRAP);
7317 + MA_SUPPORTED(GSS_C_MA_REPLAY_DET);
7318 + MA_SUPPORTED(GSS_C_MA_OOS_DET);
7319 + MA_SUPPORTED(GSS_C_MA_CBINDINGS);
7320 + MA_SUPPORTED(GSS_C_MA_CTX_TRANS);
7324 + if (known_mech_attrs != NULL) {
7325 + major = gss_create_empty_oid_set(minor, known_mech_attrs);
7326 + if (GSS_ERROR(major))
7329 +#ifdef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
7330 + MA_KNOWN(GSS_C_MA_MECH_CONCRETE);
7331 + MA_KNOWN(GSS_C_MA_MECH_PSEUDO);
7332 + MA_KNOWN(GSS_C_MA_MECH_COMPOSITE);
7333 + MA_KNOWN(GSS_C_MA_MECH_NEGO);
7334 + MA_KNOWN(GSS_C_MA_MECH_GLUE);
7335 + MA_KNOWN(GSS_C_MA_NOT_MECH);
7336 + MA_KNOWN(GSS_C_MA_DEPRECATED);
7337 + MA_KNOWN(GSS_C_MA_NOT_DFLT_MECH);
7338 + MA_KNOWN(GSS_C_MA_ITOK_FRAMED);
7339 + MA_KNOWN(GSS_C_MA_AUTH_INIT);
7340 + MA_KNOWN(GSS_C_MA_AUTH_TARG);
7341 + MA_KNOWN(GSS_C_MA_AUTH_INIT_INIT);
7342 + MA_KNOWN(GSS_C_MA_AUTH_TARG_INIT);
7343 + MA_KNOWN(GSS_C_MA_AUTH_INIT_ANON);
7344 + MA_KNOWN(GSS_C_MA_AUTH_TARG_ANON);
7345 + MA_KNOWN(GSS_C_MA_DELEG_CRED);
7346 + MA_KNOWN(GSS_C_MA_INTEG_PROT);
7347 + MA_KNOWN(GSS_C_MA_CONF_PROT);
7348 + MA_KNOWN(GSS_C_MA_MIC);
7349 + MA_KNOWN(GSS_C_MA_WRAP);
7350 + MA_KNOWN(GSS_C_MA_PROT_READY);
7351 + MA_KNOWN(GSS_C_MA_REPLAY_DET);
7352 + MA_KNOWN(GSS_C_MA_OOS_DET);
7353 + MA_KNOWN(GSS_C_MA_CBINDINGS);
7354 + MA_KNOWN(GSS_C_MA_PFS);
7355 + MA_KNOWN(GSS_C_MA_COMPRESS);
7356 + MA_KNOWN(GSS_C_MA_CTX_TRANS);
7360 + major = GSS_S_COMPLETE;
7364 + if (GSS_ERROR(major)) {
7365 + gss_release_oid_set(&tmpMinor, mech_attrs);
7366 + gss_release_oid_set(&tmpMinor, known_mech_attrs);
7371 diff --git a/mech_eap/inquire_context.c b/mech_eap/inquire_context.c
7372 new file mode 100644
7373 index 0000000..d37818d
7375 +++ b/mech_eap/inquire_context.c
7378 + * Copyright (c) 2011, JANET(UK)
7379 + * All rights reserved.
7381 + * Redistribution and use in source and binary forms, with or without
7382 + * modification, are permitted provided that the following conditions
7385 + * 1. Redistributions of source code must retain the above copyright
7386 + * notice, this list of conditions and the following disclaimer.
7388 + * 2. Redistributions in binary form must reproduce the above copyright
7389 + * notice, this list of conditions and the following disclaimer in the
7390 + * documentation and/or other materials provided with the distribution.
7392 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7393 + * may be used to endorse or promote products derived from this software
7394 + * without specific prior written permission.
7396 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7397 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7398 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7399 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7400 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7401 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7402 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7403 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7404 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7405 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7410 + * Return context handle properties.
7413 +#include "gssapiP_eap.h"
7415 +OM_uint32 GSSAPI_CALLCONV
7416 +gss_inquire_context(OM_uint32 *minor,
7418 + gss_name_t *src_name,
7419 + gss_name_t *targ_name,
7420 + OM_uint32 *lifetime_rec,
7421 + gss_OID *mech_type,
7422 + OM_uint32 *ctx_flags,
7423 + int *locally_initiated,
7426 + OM_uint32 major, tmpMinor;
7428 + if (ctx == GSS_C_NO_CONTEXT) {
7430 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
7433 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
7435 + if (src_name != NULL) {
7436 + major = gssEapDuplicateName(minor, ctx->initiatorName, src_name);
7437 + if (GSS_ERROR(major))
7441 + if (targ_name != NULL) {
7442 + major = gssEapDuplicateName(minor, ctx->acceptorName, targ_name);
7443 + if (GSS_ERROR(major))
7447 + if (lifetime_rec != NULL) {
7448 + time_t now, lifetime;
7450 + if (ctx->expiryTime == 0) {
7451 + lifetime = GSS_C_INDEFINITE;
7454 + lifetime = now - ctx->expiryTime;
7459 + *lifetime_rec = lifetime;
7462 + if (mech_type != NULL) {
7463 + major = gssEapCanonicalizeOid(minor, ctx->mechanismUsed, 0, mech_type);
7464 + if (GSS_ERROR(major))
7468 + if (ctx_flags != NULL) {
7469 + *ctx_flags = ctx->gssFlags;
7472 + if (locally_initiated != NULL) {
7473 + *locally_initiated = CTX_IS_INITIATOR(ctx);
7476 + if (open != NULL) {
7477 + *open = CTX_IS_ESTABLISHED(ctx);
7480 + major = GSS_S_COMPLETE;
7484 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
7486 + if (GSS_ERROR(major)) {
7487 + gssEapReleaseName(&tmpMinor, src_name);
7488 + gssEapReleaseName(&tmpMinor, targ_name);
7493 diff --git a/mech_eap/inquire_cred.c b/mech_eap/inquire_cred.c
7494 new file mode 100644
7495 index 0000000..227ab16
7497 +++ b/mech_eap/inquire_cred.c
7500 + * Copyright (c) 2011, JANET(UK)
7501 + * All rights reserved.
7503 + * Redistribution and use in source and binary forms, with or without
7504 + * modification, are permitted provided that the following conditions
7507 + * 1. Redistributions of source code must retain the above copyright
7508 + * notice, this list of conditions and the following disclaimer.
7510 + * 2. Redistributions in binary form must reproduce the above copyright
7511 + * notice, this list of conditions and the following disclaimer in the
7512 + * documentation and/or other materials provided with the distribution.
7514 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7515 + * may be used to endorse or promote products derived from this software
7516 + * without specific prior written permission.
7518 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7519 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7520 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7521 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7522 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7523 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7524 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7525 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7526 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7527 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7532 + * Return credential handle properties.
7535 +#include "gssapiP_eap.h"
7537 +OM_uint32 GSSAPI_CALLCONV
7538 +gss_inquire_cred(OM_uint32 *minor,
7539 + gss_cred_id_t cred,
7541 + OM_uint32 *pLifetime,
7542 + gss_cred_usage_t *cred_usage,
7543 + gss_OID_set *mechanisms)
7547 + if (cred == NULL) {
7549 + return GSS_S_NO_CRED;
7552 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7554 + major = gssEapInquireCred(minor, cred, name, pLifetime, cred_usage, mechanisms);
7556 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7560 diff --git a/mech_eap/inquire_cred_by_mech.c b/mech_eap/inquire_cred_by_mech.c
7561 new file mode 100644
7562 index 0000000..191902d
7564 +++ b/mech_eap/inquire_cred_by_mech.c
7567 + * Copyright (c) 2011, JANET(UK)
7568 + * All rights reserved.
7570 + * Redistribution and use in source and binary forms, with or without
7571 + * modification, are permitted provided that the following conditions
7574 + * 1. Redistributions of source code must retain the above copyright
7575 + * notice, this list of conditions and the following disclaimer.
7577 + * 2. Redistributions in binary form must reproduce the above copyright
7578 + * notice, this list of conditions and the following disclaimer in the
7579 + * documentation and/or other materials provided with the distribution.
7581 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7582 + * may be used to endorse or promote products derived from this software
7583 + * without specific prior written permission.
7585 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7586 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7587 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7588 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7589 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7590 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7591 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7592 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7593 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7594 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7599 + * Return credential handle properties.
7602 +#include "gssapiP_eap.h"
7604 +OM_uint32 GSSAPI_CALLCONV
7605 +gss_inquire_cred_by_mech(OM_uint32 *minor,
7606 + gss_cred_id_t cred,
7607 + gss_OID mech_type,
7609 + OM_uint32 *pInitiatorLifetime,
7610 + OM_uint32 *pAcceptorLifetime,
7611 + gss_cred_usage_t *cred_usage)
7613 + OM_uint32 major, lifetime;
7615 + if (cred == NULL) {
7617 + return GSS_S_NO_CRED;
7620 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7622 + if (!gssEapCredAvailable(cred, mech_type)) {
7623 + major = GSS_S_BAD_MECH;
7624 + *minor = GSSEAP_CRED_MECH_MISMATCH;
7628 + major = gssEapInquireCred(minor, cred, name, &lifetime, cred_usage, NULL);
7629 + if (GSS_ERROR(major))
7632 + if (pInitiatorLifetime != NULL)
7633 + *pInitiatorLifetime = (cred->flags & CRED_FLAG_INITIATE) ? lifetime : 0;
7634 + if (pAcceptorLifetime != NULL)
7635 + *pAcceptorLifetime = (cred->flags & CRED_FLAG_ACCEPT) ? lifetime : 0;
7638 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7642 diff --git a/mech_eap/inquire_cred_by_oid.c b/mech_eap/inquire_cred_by_oid.c
7643 new file mode 100644
7644 index 0000000..2ad34ed
7646 +++ b/mech_eap/inquire_cred_by_oid.c
7649 + * Copyright (c) 2011, JANET(UK)
7650 + * All rights reserved.
7652 + * Redistribution and use in source and binary forms, with or without
7653 + * modification, are permitted provided that the following conditions
7656 + * 1. Redistributions of source code must retain the above copyright
7657 + * notice, this list of conditions and the following disclaimer.
7659 + * 2. Redistributions in binary form must reproduce the above copyright
7660 + * notice, this list of conditions and the following disclaimer in the
7661 + * documentation and/or other materials provided with the distribution.
7663 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7664 + * may be used to endorse or promote products derived from this software
7665 + * without specific prior written permission.
7667 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7668 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7669 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7670 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7671 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7672 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7673 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7674 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7675 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7676 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7681 + * Return extended credential handle properties.
7684 +#include "gssapiP_eap.h"
7689 + OM_uint32 (*inquire)(OM_uint32 *, const gss_cred_id_t,
7690 + const gss_OID, gss_buffer_set_t *);
7691 +} inquireCredOps[] = {
7695 +OM_uint32 GSSAPI_CALLCONV
7696 +gss_inquire_cred_by_oid(OM_uint32 *minor,
7697 + const gss_cred_id_t cred_handle,
7698 + const gss_OID desired_object GSSEAP_UNUSED,
7699 + gss_buffer_set_t *data_set)
7705 + *data_set = GSS_C_NO_BUFFER_SET;
7707 + if (cred_handle == GSS_C_NO_CREDENTIAL) {
7709 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
7712 + GSSEAP_MUTEX_LOCK(&cred_handle->mutex);
7714 + major = GSS_S_UNAVAILABLE;
7715 + *minor = GSSEAP_BAD_CRED_OPTION;
7718 + for (i = 0; i < sizeof(inquireCredOps) / sizeof(inquireCredOps[0]); i++) {
7719 + if (oidEqual(&inquireCredOps[i].oid, desired_object)) {
7720 + major = (*inquireCredOps[i].inquire)(minor, cred_handle,
7721 + desired_object, data_set);
7727 + GSSEAP_MUTEX_UNLOCK(&cred_handle->mutex);
7731 diff --git a/mech_eap/inquire_mech_for_saslname.c b/mech_eap/inquire_mech_for_saslname.c
7732 new file mode 100644
7733 index 0000000..bd518c0
7735 +++ b/mech_eap/inquire_mech_for_saslname.c
7738 + * Copyright (c) 2011, JANET(UK)
7739 + * All rights reserved.
7741 + * Redistribution and use in source and binary forms, with or without
7742 + * modification, are permitted provided that the following conditions
7745 + * 1. Redistributions of source code must retain the above copyright
7746 + * notice, this list of conditions and the following disclaimer.
7748 + * 2. Redistributions in binary form must reproduce the above copyright
7749 + * notice, this list of conditions and the following disclaimer in the
7750 + * documentation and/or other materials provided with the distribution.
7752 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7753 + * may be used to endorse or promote products derived from this software
7754 + * without specific prior written permission.
7756 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7757 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7758 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7759 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7760 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7761 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7762 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7763 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7764 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7765 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7770 + * Map mechanism OID to a SASL mechanism name.
7773 +#include "gssapiP_eap.h"
7775 +OM_uint32 GSSAPI_CALLCONV
7776 +gss_inquire_saslname_for_mech(OM_uint32 *minor,
7777 + const gss_OID mech,
7778 + gss_buffer_t sasl_mech_name,
7779 + gss_buffer_t mech_name,
7780 + gss_buffer_t mech_description)
7783 + gss_buffer_t name;
7784 + krb5_enctype etype = ENCTYPE_NULL;
7786 + /* Dynamically construct mechanism name from Kerberos string enctype */
7787 + major = gssEapOidToEnctype(minor, mech, &etype);
7788 + if (GSS_ERROR(major))
7791 + if (mech_name != GSS_C_NO_BUFFER) {
7792 + krb5_context krbContext;
7794 + GSSEAP_KRB_INIT(&krbContext);
7796 + *minor = krbEnctypeToString(krbContext, etype, "eap-", mech_name);
7798 + return GSS_S_FAILURE;
7801 + if (mech_description != GSS_C_NO_BUFFER) {
7802 + major = makeStringBuffer(minor,
7803 + "Extensible Authentication Protocol GSS-API Mechanism",
7804 + mech_description);
7805 + if (GSS_ERROR(major))
7809 + if (sasl_mech_name != GSS_C_NO_BUFFER) {
7810 + name = gssEapOidToSaslName(mech);
7811 + if (name == GSS_C_NO_BUFFER) {
7812 + major = GSS_S_BAD_MECH;
7813 + *minor = GSSEAP_WRONG_MECH;
7815 + major = duplicateBuffer(minor, name, sasl_mech_name);
7821 diff --git a/mech_eap/inquire_mechs_for_name.c b/mech_eap/inquire_mechs_for_name.c
7822 new file mode 100644
7823 index 0000000..89c869c
7825 +++ b/mech_eap/inquire_mechs_for_name.c
7828 + * Copyright (c) 2011, JANET(UK)
7829 + * All rights reserved.
7831 + * Redistribution and use in source and binary forms, with or without
7832 + * modification, are permitted provided that the following conditions
7835 + * 1. Redistributions of source code must retain the above copyright
7836 + * notice, this list of conditions and the following disclaimer.
7838 + * 2. Redistributions in binary form must reproduce the above copyright
7839 + * notice, this list of conditions and the following disclaimer in the
7840 + * documentation and/or other materials provided with the distribution.
7842 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7843 + * may be used to endorse or promote products derived from this software
7844 + * without specific prior written permission.
7846 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7847 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7848 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7849 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7850 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7851 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7852 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7853 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7854 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7855 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7860 + * Determine mechanism OIDs supported by name.
7863 +#include "gssapiP_eap.h"
7865 +OM_uint32 GSSAPI_CALLCONV
7866 +gss_inquire_mechs_for_name(OM_uint32 *minor,
7867 + const gss_name_t input_name,
7868 + gss_OID_set *mech_types)
7870 + OM_uint32 major, tmpMinor;
7873 + *mech_types = GSS_C_NO_OID_SET;
7875 + if (input_name != GSS_C_NO_NAME &&
7876 + input_name->mechanismUsed != GSS_C_NO_OID) {
7877 + major = gss_create_empty_oid_set(minor, mech_types);
7878 + if (GSS_ERROR(major))
7881 + major = gss_add_oid_set_member(minor,
7882 + input_name->mechanismUsed,
7884 + if (GSS_ERROR(major)) {
7885 + gss_release_oid_set(&tmpMinor, mech_types);
7889 + major = gssEapIndicateMechs(minor, mech_types);
7890 + if (GSS_ERROR(major))
7896 diff --git a/mech_eap/inquire_name.c b/mech_eap/inquire_name.c
7897 new file mode 100644
7898 index 0000000..78b08a0
7900 +++ b/mech_eap/inquire_name.c
7903 + * Copyright (c) 2011, JANET(UK)
7904 + * All rights reserved.
7906 + * Redistribution and use in source and binary forms, with or without
7907 + * modification, are permitted provided that the following conditions
7910 + * 1. Redistributions of source code must retain the above copyright
7911 + * notice, this list of conditions and the following disclaimer.
7913 + * 2. Redistributions in binary form must reproduce the above copyright
7914 + * notice, this list of conditions and the following disclaimer in the
7915 + * documentation and/or other materials provided with the distribution.
7917 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7918 + * may be used to endorse or promote products derived from this software
7919 + * without specific prior written permission.
7921 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7922 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7923 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7924 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7925 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7926 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7927 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7928 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7929 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7930 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7935 + * Enumerate name attributes.
7938 +#include "gssapiP_eap.h"
7940 +OM_uint32 GSSAPI_CALLCONV
7941 +gss_inquire_name(OM_uint32 *minor,
7945 + gss_buffer_set_t *attrs)
7947 + OM_uint32 major, tmpMinor;
7951 + if (name_is_MN != NULL)
7953 + if (MN_mech != NULL)
7954 + *MN_mech = GSS_C_NO_OID;
7955 + if (attrs != NULL)
7956 + *attrs = GSS_C_NO_BUFFER_SET;
7958 + if (name == GSS_C_NO_NAME) {
7960 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
7963 + if (attrs == NULL)
7964 + return GSS_S_COMPLETE;
7966 + GSSEAP_MUTEX_LOCK(&name->mutex);
7968 + major = gssEapInquireName(minor, name, name_is_MN, MN_mech, attrs);
7970 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
7972 + if (GSS_ERROR(major))
7973 + gss_release_buffer_set(&tmpMinor, attrs);
7977 diff --git a/mech_eap/inquire_names_for_mech.c b/mech_eap/inquire_names_for_mech.c
7978 new file mode 100644
7979 index 0000000..0e60340
7981 +++ b/mech_eap/inquire_names_for_mech.c
7984 + * Copyright (c) 2011, JANET(UK)
7985 + * All rights reserved.
7987 + * Redistribution and use in source and binary forms, with or without
7988 + * modification, are permitted provided that the following conditions
7991 + * 1. Redistributions of source code must retain the above copyright
7992 + * notice, this list of conditions and the following disclaimer.
7994 + * 2. Redistributions in binary form must reproduce the above copyright
7995 + * notice, this list of conditions and the following disclaimer in the
7996 + * documentation and/or other materials provided with the distribution.
7998 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7999 + * may be used to endorse or promote products derived from this software
8000 + * without specific prior written permission.
8002 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8003 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8004 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8005 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8006 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8007 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8008 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8009 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8010 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8011 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8016 + * Return supported name OID types.
8019 +#include "gssapiP_eap.h"
8021 +OM_uint32 GSSAPI_CALLCONV
8022 +gss_inquire_names_for_mech(OM_uint32 *minor,
8023 + gss_OID mechanism,
8024 + gss_OID_set *ret_name_types)
8026 + OM_uint32 major, tmpMinor;
8027 + gss_OID nameTypes[] = {
8028 + GSS_C_NT_USER_NAME,
8029 + GSS_C_NT_HOSTBASED_SERVICE,
8030 + GSS_C_NT_EXPORT_NAME,
8031 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
8032 + GSS_C_NT_COMPOSITE_EXPORT,
8034 + GSS_EAP_NT_EAP_NAME,
8035 + GSS_C_NT_ANONYMOUS,
8039 + if (!gssEapIsMechanismOid(mechanism)) {
8040 + *minor = GSSEAP_WRONG_MECH;
8041 + return GSS_S_BAD_MECH;
8044 + major = gss_create_empty_oid_set(minor, ret_name_types);
8045 + if (GSS_ERROR(major))
8048 + for (i = 0; i < sizeof(nameTypes)/sizeof(nameTypes[0]); i++) {
8049 + major = gss_add_oid_set_member(minor, nameTypes[i], ret_name_types);
8050 + if (GSS_ERROR(major))
8055 + if (GSS_ERROR(major))
8056 + gss_release_oid_set(&tmpMinor, ret_name_types);
8060 diff --git a/mech_eap/inquire_saslname_for_mech.c b/mech_eap/inquire_saslname_for_mech.c
8061 new file mode 100644
8062 index 0000000..d6d7c14
8064 +++ b/mech_eap/inquire_saslname_for_mech.c
8067 + * Copyright (c) 2011, JANET(UK)
8068 + * All rights reserved.
8070 + * Redistribution and use in source and binary forms, with or without
8071 + * modification, are permitted provided that the following conditions
8074 + * 1. Redistributions of source code must retain the above copyright
8075 + * notice, this list of conditions and the following disclaimer.
8077 + * 2. Redistributions in binary form must reproduce the above copyright
8078 + * notice, this list of conditions and the following disclaimer in the
8079 + * documentation and/or other materials provided with the distribution.
8081 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8082 + * may be used to endorse or promote products derived from this software
8083 + * without specific prior written permission.
8085 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8086 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8087 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8088 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8089 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8090 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8091 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8092 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8093 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8094 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8099 + * Map SASL mechanism name to a mechanism OID.
8102 +#include "gssapiP_eap.h"
8104 +OM_uint32 GSSAPI_CALLCONV
8105 +gss_inquire_mech_for_saslname(OM_uint32 *minor,
8106 + const gss_buffer_t sasl_mech_name,
8107 + gss_OID *mech_type)
8109 + *mech_type = gssEapSaslNameToOid(sasl_mech_name);
8110 + if (*mech_type == GSS_C_NO_OID) {
8111 + *minor = GSSEAP_WRONG_MECH;
8112 + return GSS_S_BAD_MECH;
8115 + return GSS_S_COMPLETE;
8117 diff --git a/mech_eap/inquire_sec_context_by_oid.c b/mech_eap/inquire_sec_context_by_oid.c
8118 new file mode 100644
8119 index 0000000..7435f2e
8121 +++ b/mech_eap/inquire_sec_context_by_oid.c
8124 + * Copyright (c) 2011, JANET(UK)
8125 + * All rights reserved.
8127 + * Redistribution and use in source and binary forms, with or without
8128 + * modification, are permitted provided that the following conditions
8131 + * 1. Redistributions of source code must retain the above copyright
8132 + * notice, this list of conditions and the following disclaimer.
8134 + * 2. Redistributions in binary form must reproduce the above copyright
8135 + * notice, this list of conditions and the following disclaimer in the
8136 + * documentation and/or other materials provided with the distribution.
8138 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8139 + * may be used to endorse or promote products derived from this software
8140 + * without specific prior written permission.
8142 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8143 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8144 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8145 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8146 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8147 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8148 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8149 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8150 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8151 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8156 + * Return extended properties of a context handle.
8159 +#include "gssapiP_eap.h"
8162 +addEnctypeOidToBufferSet(OM_uint32 *minor,
8163 + krb5_enctype encryptionType,
8164 + gss_buffer_set_t *dataSet)
8167 + unsigned char oidBuf[16];
8169 + gss_buffer_desc buf;
8171 + oid.length = sizeof(oidBuf);
8172 + oid.elements = oidBuf;
8174 + major = composeOid(minor,
8175 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04",
8179 + if (GSS_ERROR(major))
8182 + buf.length = oid.length;
8183 + buf.value = oid.elements;
8185 + major = gss_add_buffer_set_member(minor, &buf, dataSet);
8191 +zeroAndReleaseBufferSet(gss_buffer_set_t *dataSet)
8193 + OM_uint32 tmpMinor;
8194 + gss_buffer_set_t set = *dataSet;
8197 + if (set == GSS_C_NO_BUFFER_SET)
8200 + for (i = 0; i <set->count; i++)
8201 + memset(set->elements[i].value, 0, set->elements[i].length);
8203 + gss_release_buffer_set(&tmpMinor, dataSet);
8207 +inquireSessionKey(OM_uint32 *minor,
8208 + const gss_ctx_id_t ctx,
8209 + const gss_OID desired_object GSSEAP_UNUSED,
8210 + gss_buffer_set_t *dataSet)
8213 + gss_buffer_desc buf;
8215 + if (ctx->encryptionType == ENCTYPE_NULL) {
8216 + major = GSS_S_UNAVAILABLE;
8217 + *minor = GSSEAP_KEY_UNAVAILABLE;
8221 + buf.length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
8222 + buf.value = KRB_KEY_DATA(&ctx->rfc3961Key);
8224 + major = gss_add_buffer_set_member(minor, &buf, dataSet);
8225 + if (GSS_ERROR(major))
8228 + major = addEnctypeOidToBufferSet(minor, ctx->encryptionType, dataSet);
8229 + if (GSS_ERROR(major))
8232 + major = GSS_S_COMPLETE;
8236 + if (GSS_ERROR(major))
8237 + zeroAndReleaseBufferSet(dataSet);
8243 +inquireNegoExKey(OM_uint32 *minor,
8244 + const gss_ctx_id_t ctx,
8245 + const gss_OID desired_object,
8246 + gss_buffer_set_t *dataSet)
8248 + OM_uint32 major, tmpMinor;
8249 + int bInitiatorKey;
8250 + gss_buffer_desc salt;
8251 + gss_buffer_desc key = GSS_C_EMPTY_BUFFER;
8254 + bInitiatorKey = CTX_IS_INITIATOR(ctx);
8256 + if (ctx->encryptionType == ENCTYPE_NULL) {
8257 + major = GSS_S_UNAVAILABLE;
8258 + *minor = GSSEAP_KEY_UNAVAILABLE;
8263 + * If the caller supplied the verify key OID, then we need the acceptor
8264 + * key if we are the initiator, and vice versa.
8266 + if (desired_object->length == 11 &&
8267 + memcmp(desired_object->elements,
8268 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07", 11) == 0)
8269 + bInitiatorKey ^= 1;
8271 + if (bInitiatorKey) {
8272 + salt.length = NEGOEX_INITIATOR_SALT_LEN;
8273 + salt.value = NEGOEX_INITIATOR_SALT;
8275 + salt.length = NEGOEX_ACCEPTOR_SALT_LEN;
8276 + salt.value = NEGOEX_ACCEPTOR_SALT;
8279 + keySize = KRB_KEY_LENGTH(&ctx->rfc3961Key);
8281 + major = gssEapPseudoRandom(minor, ctx, GSS_C_PRF_KEY_FULL, &salt,
8283 + if (GSS_ERROR(major))
8286 + major = gss_add_buffer_set_member(minor, &key, dataSet);
8287 + if (GSS_ERROR(major))
8290 + major = addEnctypeOidToBufferSet(minor, ctx->encryptionType, dataSet);
8291 + if (GSS_ERROR(major))
8294 + major = GSS_S_COMPLETE;
8298 + if (key.value != NULL) {
8299 + memset(key.value, 0, key.length);
8300 + gss_release_buffer(&tmpMinor, &key);
8302 + if (GSS_ERROR(major))
8303 + zeroAndReleaseBufferSet(dataSet);
8310 + OM_uint32 (*inquire)(OM_uint32 *, const gss_ctx_id_t,
8311 + const gss_OID, gss_buffer_set_t *);
8312 +} inquireCtxOps[] = {
8314 + /* GSS_C_INQ_SSPI_SESSION_KEY */
8315 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" },
8319 + /* GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT + v1 */
8320 + { 12, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06\x01" },
8321 + gssEapExportLucidSecContext
8324 + /* GSS_C_INQ_NEGOEX_KEY */
8325 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06" },
8329 + /* GSS_C_INQ_NEGOEX_VERIFY_KEY */
8330 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07" },
8335 +OM_uint32 GSSAPI_CALLCONV
8336 +gss_inquire_sec_context_by_oid(OM_uint32 *minor,
8337 + const gss_ctx_id_t ctx,
8338 + const gss_OID desired_object,
8339 + gss_buffer_set_t *data_set)
8344 + *data_set = GSS_C_NO_BUFFER_SET;
8346 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
8349 + if (!CTX_IS_ESTABLISHED(ctx)) {
8350 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
8351 + major = GSS_S_NO_CONTEXT;
8356 + major = GSS_S_UNAVAILABLE;
8357 + *minor = GSSEAP_BAD_CONTEXT_OPTION;
8359 + for (i = 0; i < sizeof(inquireCtxOps) / sizeof(inquireCtxOps[0]); i++) {
8360 + if (oidEqual(&inquireCtxOps[i].oid, desired_object)) {
8361 + major = (*inquireCtxOps[i].inquire)(minor, ctx,
8362 + desired_object, data_set);
8367 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
8371 diff --git a/mech_eap/install-sh b/mech_eap/install-sh
8372 new file mode 100755
8373 index 0000000..6781b98
8375 +++ b/mech_eap/install-sh
8378 +# install - install a program, script, or datafile
8380 +scriptversion=2009-04-28.21; # UTC
8382 +# This originates from X11R5 (mit/util/scripts/install.sh), which was
8383 +# later released in X11R6 (xc/config/util/install.sh) with the
8384 +# following copyright and license.
8386 +# Copyright (C) 1994 X Consortium
8388 +# Permission is hereby granted, free of charge, to any person obtaining a copy
8389 +# of this software and associated documentation files (the "Software"), to
8390 +# deal in the Software without restriction, including without limitation the
8391 +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8392 +# sell copies of the Software, and to permit persons to whom the Software is
8393 +# furnished to do so, subject to the following conditions:
8395 +# The above copyright notice and this permission notice shall be included in
8396 +# all copies or substantial portions of the Software.
8398 +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8399 +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8400 +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8401 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
8402 +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
8403 +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8405 +# Except as contained in this notice, the name of the X Consortium shall not
8406 +# be used in advertising or otherwise to promote the sale, use or other deal-
8407 +# ings in this Software without prior written authorization from the X Consor-
8411 +# FSF changes to this file are in the public domain.
8413 +# Calling this script install-sh is preferred over install.sh, to prevent
8414 +# `make' implicit rules from creating a file called install from it
8415 +# when there is no Makefile.
8417 +# This script is compatible with the BSD install script, but was written
8424 +# set DOITPROG to echo to test this script
8426 +# Don't use :- since 4.3BSD and earlier shells don't like it.
8428 +if test -z "$doit"; then
8434 +# Put in absolute file names if you don't have them in your path;
8435 +# or use environment vars.
8437 +chgrpprog=${CHGRPPROG-chgrp}
8438 +chmodprog=${CHMODPROG-chmod}
8439 +chownprog=${CHOWNPROG-chown}
8440 +cmpprog=${CMPPROG-cmp}
8441 +cpprog=${CPPROG-cp}
8442 +mkdirprog=${MKDIRPROG-mkdir}
8443 +mvprog=${MVPROG-mv}
8444 +rmprog=${RMPROG-rm}
8445 +stripprog=${STRIPPROG-strip}
8448 +initialize_posix_glob='
8449 + test "$posix_glob" != "?" || {
8450 + if (set -f) 2>/dev/null; then
8460 +# Desired mode of installed file.
8464 +chmodcmd=$chmodprog
8475 +copy_on_change=false
8476 +no_target_directory=
8479 +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8480 + or: $0 [OPTION]... SRCFILES... DIRECTORY
8481 + or: $0 [OPTION]... -t DIRECTORY SRCFILES...
8482 + or: $0 [OPTION]... -d DIRECTORIES...
8484 +In the 1st form, copy SRCFILE to DSTFILE.
8485 +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8486 +In the 4th, create DIRECTORIES.
8489 + --help display this help and exit.
8490 + --version display version info and exit.
8493 + -C install only if different (preserve the last data modification time)
8494 + -d create directories instead of installing files.
8495 + -g GROUP $chgrpprog installed files to GROUP.
8496 + -m MODE $chmodprog installed files to MODE.
8497 + -o USER $chownprog installed files to USER.
8498 + -s $stripprog installed files.
8499 + -t DIRECTORY install into DIRECTORY.
8500 + -T report an error if DSTFILE is a directory.
8502 +Environment variables override the default commands:
8503 + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
8507 +while test $# -ne 0; do
8511 + -C) copy_on_change=true;;
8513 + -d) dir_arg=true;;
8515 + -g) chgrpcmd="$chgrpprog $2"
8518 + --help) echo "$usage"; exit $?;;
8522 + *' '* | *' '* | *'
8523 +'* | *'*'* | *'?'* | *'['*)
8524 + echo "$0: invalid mode: $mode" >&2
8529 + -o) chowncmd="$chownprog $2"
8532 + -s) stripcmd=$stripprog;;
8537 + -T) no_target_directory=true;;
8539 + --version) echo "$0 $scriptversion"; exit $?;;
8544 + -*) echo "$0: invalid option: $1" >&2
8552 +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
8553 + # When -d is used, all remaining arguments are directories to create.
8554 + # When -t is used, the destination is already specified.
8555 + # Otherwise, the last argument is the destination. Remove it from $@.
8558 + if test -n "$dst_arg"; then
8559 + # $@ is not empty: it contains at least $arg.
8560 + set fnord "$@" "$dst_arg"
8568 +if test $# -eq 0; then
8569 + if test -z "$dir_arg"; then
8570 + echo "$0: no input file specified." >&2
8573 + # It's OK to call `install-sh -d' without argument.
8574 + # This can happen when creating conditional directories.
8578 +if test -z "$dir_arg"; then
8579 + trap '(exit $?); exit' 1 2 13 15
8581 + # Set umask so as not to create temps with too-generous modes.
8582 + # However, 'strip' requires both read and write access to temps.
8584 + # Optimize common cases.
8585 + *644) cp_umask=133;;
8586 + *755) cp_umask=22;;
8589 + if test -z "$stripcmd"; then
8594 + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
8596 + if test -z "$stripcmd"; then
8601 + cp_umask=$mode$u_plus_rw;;
8607 + # Protect names starting with `-'.
8612 + if test -n "$dir_arg"; then
8619 + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
8620 + # might cause directories to be created, which would be especially bad
8621 + # if $src (and thus $dsttmp) contains '*'.
8622 + if test ! -f "$src" && test ! -d "$src"; then
8623 + echo "$0: $src does not exist." >&2
8627 + if test -z "$dst_arg"; then
8628 + echo "$0: no destination specified." >&2
8633 + # Protect names starting with `-'.
8638 + # If destination is a directory, append the input filename; won't work
8639 + # if double slashes aren't ignored.
8640 + if test -d "$dst"; then
8641 + if test -n "$no_target_directory"; then
8642 + echo "$0: $dst_arg: Is a directory" >&2
8646 + dst=$dstdir/`basename "$src"`
8649 + # Prefer dirname, but fall back on a substitute if dirname fails.
8651 + (dirname "$dst") 2>/dev/null ||
8652 + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
8653 + X"$dst" : 'X\(//\)[^/]' \| \
8654 + X"$dst" : 'X\(//\)$' \| \
8655 + X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
8657 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
8661 + /^X\(\/\/\)[^/].*/{
8681 + obsolete_mkdir_used=false
8683 + if test $dstdir_status != 0; then
8684 + case $posix_mkdir in
8686 + # Create intermediate dirs using mode 755 as modified by the umask.
8687 + # This is like FreeBSD 'install' as of 1997-10-28.
8689 + case $stripcmd.$umask in
8690 + # Optimize common cases.
8691 + *[2367][2367]) mkdir_umask=$umask;;
8692 + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
8695 + mkdir_umask=`expr $umask + 22 \
8696 + - $umask % 100 % 40 + $umask % 20 \
8697 + - $umask % 10 % 4 + $umask % 2
8699 + *) mkdir_umask=$umask,go-w;;
8702 + # With -d, create the new directory with the user-specified mode.
8703 + # Otherwise, rely on $mkdir_umask.
8704 + if test -n "$dir_arg"; then
8705 + mkdir_mode=-m$mode
8712 + *[123567][0-7][0-7])
8713 + # POSIX mkdir -p sets u+wx bits regardless of umask, which
8714 + # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
8717 + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
8718 + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
8720 + if (umask $mkdir_umask &&
8721 + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
8723 + if test -z "$dir_arg" || {
8724 + # Check for POSIX incompatibilities with -m.
8725 + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
8726 + # other-writeable bit of parent directory when it shouldn't.
8727 + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
8728 + ls_ld_tmpdir=`ls -ld "$tmpdir"`
8729 + case $ls_ld_tmpdir in
8730 + d????-?r-*) different_mode=700;;
8731 + d????-?--*) different_mode=755;;
8734 + $mkdirprog -m$different_mode -p -- "$tmpdir" && {
8735 + ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
8736 + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
8739 + then posix_mkdir=:
8741 + rmdir "$tmpdir/d" "$tmpdir"
8743 + # Remove any dirs left behind by ancient mkdir implementations.
8744 + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
8752 + umask $mkdir_umask &&
8753 + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
8758 + # The umask is ridiculous, or mkdir does not conform to POSIX,
8759 + # or it failed possibly due to a race condition. Create the
8760 + # directory the slow way, step by step, checking for races as we go.
8768 + eval "$initialize_posix_glob"
8772 + $posix_glob set -f
8775 + $posix_glob set +f
8782 + test -z "$d" && continue
8785 + if test -d "$prefix"; then
8788 + if $posix_mkdir; then
8789 + (umask=$mkdir_umask &&
8790 + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
8791 + # Don't fail if two instances are running concurrently.
8792 + test -d "$prefix" || exit 1
8795 + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
8796 + *) qprefix=$prefix;;
8798 + prefixes="$prefixes '$qprefix'"
8804 + if test -n "$prefixes"; then
8805 + # Don't fail if two instances are running concurrently.
8806 + (umask $mkdir_umask &&
8807 + eval "\$doit_exec \$mkdirprog $prefixes") ||
8808 + test -d "$dstdir" || exit 1
8809 + obsolete_mkdir_used=true
8814 + if test -n "$dir_arg"; then
8815 + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
8816 + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
8817 + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
8818 + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
8821 + # Make a couple of temp file names in the proper directory.
8822 + dsttmp=$dstdir/_inst.$$_
8823 + rmtmp=$dstdir/_rm.$$_
8825 + # Trap to clean up those temp files at exit.
8826 + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
8828 + # Copy the file name to the temp name.
8829 + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
8831 + # and set any options; do chmod last to preserve setuid bits.
8833 + # If any of these fail, we abort the whole thing. If we want to
8834 + # ignore errors from any of these, just make sure not to ignore
8835 + # errors from the above "$doit $cpprog $src $dsttmp" command.
8837 + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
8838 + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
8839 + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
8840 + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
8842 + # If -C, don't bother to copy if it wouldn't change the file.
8843 + if $copy_on_change &&
8844 + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
8845 + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
8847 + eval "$initialize_posix_glob" &&
8848 + $posix_glob set -f &&
8849 + set X $old && old=:$2:$4:$5:$6 &&
8850 + set X $new && new=:$2:$4:$5:$6 &&
8851 + $posix_glob set +f &&
8853 + test "$old" = "$new" &&
8854 + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
8858 + # Rename the file to the real destination.
8859 + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
8861 + # The rename failed, perhaps because mv can't rename something else
8862 + # to itself, or perhaps because mv is so ancient that it does not
8865 + # Now remove or move aside any old file at destination location.
8866 + # We try this two ways since rm can't unlink itself on some
8867 + # systems and the destination file might be busy for other
8868 + # reasons. In this case, the final cleanup might fail but the new
8869 + # file should still install successfully.
8871 + test ! -f "$dst" ||
8872 + $doit $rmcmd -f "$dst" 2>/dev/null ||
8873 + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
8874 + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
8876 + { echo "$0: cannot unlink or rename $dst" >&2
8881 + # Now rename the file to the real destination.
8882 + $doit $mvcmd "$dsttmp" "$dst"
8891 +# eval: (add-hook 'write-file-hooks 'time-stamp)
8892 +# time-stamp-start: "scriptversion="
8893 +# time-stamp-format: "%:y-%02m-%02d.%02H"
8894 +# time-stamp-time-zone: "UTC"
8895 +# time-stamp-end: "; # UTC"
8897 diff --git a/mech_eap/map_name_to_any.c b/mech_eap/map_name_to_any.c
8898 new file mode 100644
8899 index 0000000..2a8a96c
8901 +++ b/mech_eap/map_name_to_any.c
8904 + * Copyright (c) 2011, JANET(UK)
8905 + * All rights reserved.
8907 + * Redistribution and use in source and binary forms, with or without
8908 + * modification, are permitted provided that the following conditions
8911 + * 1. Redistributions of source code must retain the above copyright
8912 + * notice, this list of conditions and the following disclaimer.
8914 + * 2. Redistributions in binary form must reproduce the above copyright
8915 + * notice, this list of conditions and the following disclaimer in the
8916 + * documentation and/or other materials provided with the distribution.
8918 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8919 + * may be used to endorse or promote products derived from this software
8920 + * without specific prior written permission.
8922 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8923 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8924 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8925 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8926 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8927 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8928 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8929 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8930 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8931 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8935 +#include "gssapiP_eap.h"
8937 +OM_uint32 GSSAPI_CALLCONV
8938 +gss_map_name_to_any(OM_uint32 *minor,
8940 + int authenticated,
8941 + gss_buffer_t type_id,
8942 + gss_any_t *output)
8946 + *output = (gss_any_t)NULL;
8948 + if (name == GSS_C_NO_NAME) {
8950 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
8953 + GSSEAP_MUTEX_LOCK(&name->mutex);
8955 + major = gssEapMapNameToAny(minor, name, authenticated, type_id, output);
8957 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
8961 diff --git a/mech_eap/mech b/mech_eap/mech
8962 new file mode 100644
8963 index 0000000..258a43a
8968 +# Sample mechanism glue configuration for EAP GSS mechanism.
8970 +# Any encryption type supported by Kerberos can be defined as the
8971 +# last element of the OID arc.
8973 +eap-aes128 1.3.6.1.4.1.5322.22.1.17 mech_eap.so
8974 +eap-aes256 1.3.6.1.4.1.5322.22.1.18 mech_eap.so
8975 diff --git a/mech_eap/mech_eap-noacceptor.exports b/mech_eap/mech_eap-noacceptor.exports
8976 new file mode 100644
8977 index 0000000..f00df8a
8979 +++ b/mech_eap/mech_eap-noacceptor.exports
8983 +gss_add_cred_with_password
8984 +gss_canonicalize_name
8987 +gss_delete_sec_context
8989 +gss_display_name_ext
8992 +gss_exchange_meta_data
8994 +gss_export_sec_context
8997 +gss_import_sec_context
8999 +gss_init_sec_context
9000 +gss_inquire_attrs_for_mech
9001 +gss_inquire_context
9003 +gss_inquire_cred_by_mech
9004 +gss_inquire_cred_by_oid
9005 +gss_inquire_mechs_for_name
9006 +gss_inquire_mech_for_saslname
9007 +gss_inquire_names_for_mech
9008 +gss_inquire_saslname_for_mech
9009 +gss_inquire_sec_context_by_oid
9010 +gss_process_context_token
9012 +gss_query_mechanism_info
9013 +gss_query_meta_data
9016 +gss_internal_release_oid
9017 +gss_set_sec_context_option
9024 +gss_wrap_iov_length
9025 +gss_wrap_size_limit
9026 +GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
9027 +GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
9028 +GSS_EAP_NT_EAP_NAME
9029 +GSS_EAP_CRED_SET_CRED_FLAG
9030 +GSS_EAP_CRED_SET_CRED_PASSWORD
9031 +GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
9032 +GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
9033 +gssspi_acquire_cred_with_password
9034 +gssspi_authorize_localname
9035 +gssspi_set_cred_option
9036 diff --git a/mech_eap/mech_eap.exports b/mech_eap/mech_eap.exports
9037 new file mode 100644
9038 index 0000000..6a17a17
9040 +++ b/mech_eap/mech_eap.exports
9042 +gss_accept_sec_context
9045 +gss_add_cred_with_password
9046 +gss_canonicalize_name
9049 +gss_delete_name_attribute
9050 +gss_delete_sec_context
9052 +gss_display_name_ext
9055 +gss_exchange_meta_data
9057 +gss_export_name_composite
9058 +gss_export_sec_context
9060 +gss_get_name_attribute
9062 +gss_import_sec_context
9064 +gss_init_sec_context
9065 +gss_inquire_attrs_for_mech
9066 +gss_inquire_context
9068 +gss_inquire_cred_by_mech
9069 +gss_inquire_cred_by_oid
9070 +gss_inquire_mechs_for_name
9071 +gss_inquire_mech_for_saslname
9073 +gss_inquire_names_for_mech
9074 +gss_inquire_saslname_for_mech
9075 +gss_inquire_sec_context_by_oid
9076 +gss_map_name_to_any
9077 +gss_process_context_token
9079 +gss_query_mechanism_info
9080 +gss_query_meta_data
9081 +gss_release_any_name_mapping
9084 +gss_internal_release_oid
9085 +gss_set_name_attribute
9086 +gss_set_sec_context_option
9093 +gss_wrap_iov_length
9094 +gss_wrap_size_limit
9095 +GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
9096 +GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
9097 +GSS_EAP_NT_EAP_NAME
9098 +GSS_EAP_CRED_SET_CRED_FLAG
9099 +GSS_EAP_CRED_SET_CRED_PASSWORD
9100 +GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
9101 +GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
9102 +gssspi_acquire_cred_with_password
9103 +gssspi_authorize_localname
9104 +gssspi_set_cred_option
9105 diff --git a/mech_eap/mech_invoke.c b/mech_eap/mech_invoke.c
9106 new file mode 100644
9107 index 0000000..bc9bba3
9109 +++ b/mech_eap/mech_invoke.c
9112 + * Copyright (c) 2011, JANET(UK)
9113 + * All rights reserved.
9115 + * Redistribution and use in source and binary forms, with or without
9116 + * modification, are permitted provided that the following conditions
9119 + * 1. Redistributions of source code must retain the above copyright
9120 + * notice, this list of conditions and the following disclaimer.
9122 + * 2. Redistributions in binary form must reproduce the above copyright
9123 + * notice, this list of conditions and the following disclaimer in the
9124 + * documentation and/or other materials provided with the distribution.
9126 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9127 + * may be used to endorse or promote products derived from this software
9128 + * without specific prior written permission.
9130 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9131 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9132 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9133 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9134 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9135 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9136 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9137 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9138 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9139 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9143 +#include "gssapiP_eap.h"
9145 +OM_uint32 GSSAPI_CALLCONV
9146 +gssspi_mech_invoke(OM_uint32 *minor,
9147 + const gss_OID desired_mech,
9148 + const gss_OID desired_object,
9149 + gss_buffer_t value)
9151 + *minor = GSSEAP_BAD_INVOCATION;
9153 + return GSS_S_UNAVAILABLE;
9155 diff --git a/mech_eap/process_context_token.c b/mech_eap/process_context_token.c
9156 new file mode 100644
9157 index 0000000..02a4b6d
9159 +++ b/mech_eap/process_context_token.c
9162 + * Copyright (c) 2011, JANET(UK)
9163 + * All rights reserved.
9165 + * Redistribution and use in source and binary forms, with or without
9166 + * modification, are permitted provided that the following conditions
9169 + * 1. Redistributions of source code must retain the above copyright
9170 + * notice, this list of conditions and the following disclaimer.
9172 + * 2. Redistributions in binary form must reproduce the above copyright
9173 + * notice, this list of conditions and the following disclaimer in the
9174 + * documentation and/or other materials provided with the distribution.
9176 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9177 + * may be used to endorse or promote products derived from this software
9178 + * without specific prior written permission.
9180 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9181 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9182 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9183 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9184 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9185 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9186 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9187 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9188 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9189 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9193 +#include "gssapiP_eap.h"
9195 +OM_uint32 GSSAPI_CALLCONV
9196 +gss_process_context_token(OM_uint32 *minor,
9198 + gss_buffer_t token_buffer)
9201 + gss_iov_buffer_desc iov[1];
9205 + if (ctx == NULL) {
9207 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
9210 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9212 + if (!CTX_IS_ESTABLISHED(ctx)) {
9213 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9214 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
9215 + return GSS_S_NO_CONTEXT;
9218 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
9219 + iov[0].buffer = *token_buffer;
9221 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
9222 + iov, 1, TOK_TYPE_DELETE_CONTEXT);
9223 + if (GSS_ERROR(major)) {
9224 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9228 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9230 + return gssEapReleaseContext(minor, &ctx);
9232 diff --git a/mech_eap/pseudo_random.c b/mech_eap/pseudo_random.c
9233 new file mode 100644
9234 index 0000000..61d1f2a
9236 +++ b/mech_eap/pseudo_random.c
9239 + * Copyright (c) 2011, JANET(UK)
9240 + * All rights reserved.
9242 + * Redistribution and use in source and binary forms, with or without
9243 + * modification, are permitted provided that the following conditions
9246 + * 1. Redistributions of source code must retain the above copyright
9247 + * notice, this list of conditions and the following disclaimer.
9249 + * 2. Redistributions in binary form must reproduce the above copyright
9250 + * notice, this list of conditions and the following disclaimer in the
9251 + * documentation and/or other materials provided with the distribution.
9253 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9254 + * may be used to endorse or promote products derived from this software
9255 + * without specific prior written permission.
9257 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9258 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9259 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9260 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9261 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9262 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9263 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9264 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9265 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9266 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9270 + * Copyright 2009 by the Massachusetts Institute of Technology.
9271 + * All Rights Reserved.
9273 + * Export of this software from the United States of America may
9274 + * require a specific license from the United States Government.
9275 + * It is the responsibility of any person or organization contemplating
9276 + * export to obtain such a license before exporting.
9278 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
9279 + * distribute this software and its documentation for any purpose and
9280 + * without fee is hereby granted, provided that the above copyright
9281 + * notice appear in all copies and that both that copyright notice and
9282 + * this permission notice appear in supporting documentation, and that
9283 + * the name of M.I.T. not be used in advertising or publicity pertaining
9284 + * to distribution of the software without specific, written prior
9285 + * permission. Furthermore if you modify this software you must label
9286 + * your software as modified software and not distribute it in such a
9287 + * fashion that it might be confused with the original M.I.T. software.
9288 + * M.I.T. makes no representations about the suitability of
9289 + * this software for any purpose. It is provided "as is" without express
9290 + * or implied warranty.
9297 +#include "gssapiP_eap.h"
9300 +gssEapPseudoRandom(OM_uint32 *minor,
9303 + const gss_buffer_t prf_in,
9304 + ssize_t desired_output_len,
9305 + gss_buffer_t prf_out)
9307 + krb5_error_code code;
9309 + OM_uint32 tmpMinor;
9313 + krb5_context krbContext;
9315 + prf_out->length = 0;
9316 + prf_out->value = NULL;
9320 + GSSEAP_KRB_INIT(&krbContext);
9322 + KRB_DATA_INIT(&t);
9323 + KRB_DATA_INIT(&ns);
9325 + if (prf_key != GSS_C_PRF_KEY_PARTIAL &&
9326 + prf_key != GSS_C_PRF_KEY_FULL) {
9327 + code = GSSEAP_BAD_PRF_KEY;
9331 + prf_out->value = GSSEAP_MALLOC(desired_output_len);
9332 + if (prf_out->value == NULL) {
9336 + prf_out->length = desired_output_len;
9338 + code = krb5_c_prf_length(krbContext,
9339 + ctx->encryptionType,
9344 + ns.length = 4 + prf_in->length;
9345 + ns.data = GSSEAP_MALLOC(ns.length);
9346 + if (ns.data == NULL) {
9351 +#ifndef HAVE_HEIMDAL_VERSION
9352 + /* Same API, but different allocation rules, unfortunately. */
9353 + t.length = prflen;
9354 + t.data = GSSEAP_MALLOC(t.length);
9355 + if (t.data == NULL) {
9361 + memcpy((unsigned char *)ns.data + 4, prf_in->value, prf_in->length);
9363 + p = (unsigned char *)prf_out->value;
9364 + while (desired_output_len > 0) {
9365 + store_uint32_be(i, ns.data);
9367 + code = krb5_c_prf(krbContext, &ctx->rfc3961Key, &ns, &t);
9371 + memcpy(p, t.data, MIN(t.length, desired_output_len));
9374 + desired_output_len -= t.length;
9380 + gss_release_buffer(&tmpMinor, prf_out);
9381 + if (ns.data != NULL) {
9382 + memset(ns.data, 0, ns.length);
9383 + GSSEAP_FREE(ns.data);
9385 +#ifdef HAVE_HEIMDAL_VERSION
9386 + krb5_free_data_contents(krbContext, &t);
9388 + if (t.data != NULL) {
9389 + memset(t.data, 0, t.length);
9390 + GSSEAP_FREE(t.data);
9396 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
9399 +OM_uint32 GSSAPI_CALLCONV
9400 +gss_pseudo_random(OM_uint32 *minor,
9403 + const gss_buffer_t prf_in,
9404 + ssize_t desired_output_len,
9405 + gss_buffer_t prf_out)
9409 + if (ctx == GSS_C_NO_CONTEXT) {
9411 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
9414 + prf_out->length = 0;
9415 + prf_out->value = NULL;
9419 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9421 + if (CTX_IS_ESTABLISHED(ctx)) {
9422 + major = gssEapPseudoRandom(minor, ctx, prf_key,
9423 + prf_in, desired_output_len, prf_out);
9425 + major = GSS_S_NO_CONTEXT;
9426 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
9429 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9433 diff --git a/mech_eap/query_mechanism_info.c b/mech_eap/query_mechanism_info.c
9434 new file mode 100644
9435 index 0000000..acd3115
9437 +++ b/mech_eap/query_mechanism_info.c
9440 + * Copyright (c) 2011, JANET(UK)
9441 + * All rights reserved.
9443 + * Redistribution and use in source and binary forms, with or without
9444 + * modification, are permitted provided that the following conditions
9447 + * 1. Redistributions of source code must retain the above copyright
9448 + * notice, this list of conditions and the following disclaimer.
9450 + * 2. Redistributions in binary form must reproduce the above copyright
9451 + * notice, this list of conditions and the following disclaimer in the
9452 + * documentation and/or other materials provided with the distribution.
9454 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9455 + * may be used to endorse or promote products derived from this software
9456 + * without specific prior written permission.
9458 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9459 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9460 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9461 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9462 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9463 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9464 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9465 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9466 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9467 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9475 +#include "gssapiP_eap.h"
9478 +gssQueryMechanismInfo(OM_uint32 *minor,
9479 + gss_const_OID mech_oid,
9480 + unsigned char auth_scheme[16])
9483 + krb5_enctype enctype;
9485 + major = gssEapOidToEnctype(minor, (const gss_OID)mech_oid, &enctype);
9486 + if (GSS_ERROR(major))
9489 + /* the enctype is encoded in the increasing part of the GUID */
9490 + memcpy(auth_scheme,
9491 + "\x39\xd7\x7d\x00\xe5\x00\x11\xe0\xac\x64\xcd\x53\x46\x50\xac\xb9", 16);
9493 + auth_scheme[3] = (unsigned char)enctype;
9496 + return GSS_S_COMPLETE;
9499 +OM_uint32 GSSAPI_CALLCONV
9500 +gss_query_mechanism_info(OM_uint32 *minor,
9501 + gss_const_OID mech_oid,
9502 + unsigned char auth_scheme[16])
9504 + return gssQueryMechanismInfo(minor, mech_oid, auth_scheme);
9506 diff --git a/mech_eap/query_meta_data.c b/mech_eap/query_meta_data.c
9507 new file mode 100644
9508 index 0000000..abc7e71
9510 +++ b/mech_eap/query_meta_data.c
9513 + * Copyright (c) 2011, JANET(UK)
9514 + * All rights reserved.
9516 + * Redistribution and use in source and binary forms, with or without
9517 + * modification, are permitted provided that the following conditions
9520 + * 1. Redistributions of source code must retain the above copyright
9521 + * notice, this list of conditions and the following disclaimer.
9523 + * 2. Redistributions in binary form must reproduce the above copyright
9524 + * notice, this list of conditions and the following disclaimer in the
9525 + * documentation and/or other materials provided with the distribution.
9527 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9528 + * may be used to endorse or promote products derived from this software
9529 + * without specific prior written permission.
9531 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9532 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9533 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9534 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9535 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9536 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9537 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9538 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9539 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9540 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9548 +#include "gssapiP_eap.h"
9551 +gssEapQueryMetaData(OM_uint32 *minor,
9552 + gss_const_OID mech GSSEAP_UNUSED,
9553 + gss_cred_id_t cred,
9554 + gss_ctx_id_t *context_handle,
9555 + const gss_name_t name,
9556 + OM_uint32 req_flags GSSEAP_UNUSED,
9557 + gss_buffer_t meta_data)
9559 + OM_uint32 major = GSS_S_COMPLETE;
9560 + int isInitiator = (name != GSS_C_NO_NAME);
9561 + gss_ctx_id_t ctx = *context_handle;
9563 + meta_data->length = 0;
9564 + meta_data->value = NULL;
9566 + if (ctx == GSS_C_NO_CONTEXT) {
9567 + major = gssEapAllocContext(minor, &ctx);
9568 + if (GSS_ERROR(major))
9572 + ctx->flags |= CTX_FLAG_INITIATOR;
9575 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
9576 + if (isInitiator) {
9577 + major = gssEapResolveInitiatorCred(minor, cred,
9578 + name, &ctx->cred);
9580 + major = gssEapAcquireCred(minor,
9591 + if (*context_handle == GSS_C_NO_CONTEXT)
9592 + *context_handle = ctx;
9597 +OM_uint32 GSSAPI_CALLCONV
9598 +gss_query_meta_data(OM_uint32 *minor,
9599 + gss_const_OID mech,
9600 + gss_cred_id_t cred,
9601 + gss_ctx_id_t *context_handle,
9602 + const gss_name_t name,
9603 + OM_uint32 req_flags,
9604 + gss_buffer_t meta_data)
9606 + gss_ctx_id_t ctx = *context_handle;
9609 + if (cred != GSS_C_NO_CREDENTIAL)
9610 + GSSEAP_MUTEX_LOCK(&cred->mutex);
9612 + if (*context_handle != GSS_C_NO_CONTEXT)
9613 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9615 + major = gssEapQueryMetaData(minor, mech, cred, &ctx,
9616 + name, req_flags, meta_data);
9618 + if (*context_handle != GSS_C_NO_CONTEXT)
9619 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9621 + *context_handle = ctx;
9623 + if (cred != GSS_C_NO_CREDENTIAL)
9624 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
9628 diff --git a/mech_eap/radius_ad.exports b/mech_eap/radius_ad.exports
9629 new file mode 100644
9630 index 0000000..8d5d5c4
9632 +++ b/mech_eap/radius_ad.exports
9635 diff --git a/mech_eap/radsec.conf b/mech_eap/radsec.conf
9636 new file mode 100644
9637 index 0000000..27f895a
9639 +++ b/mech_eap/radsec.conf
9641 +dictionary = "/usr/local/etc/raddb/dictionary"
9648 + hostname = "localhost"
9650 + secret = "testing123"
9653 diff --git a/mech_eap/radsec_err.et b/mech_eap/radsec_err.et
9654 new file mode 100644
9655 index 0000000..3b7fae2
9657 +++ b/mech_eap/radsec_err.et
9660 +# Copyright (c) 2011, JANET(UK)
9661 +# All rights reserved.
9663 +# Redistribution and use in source and binary forms, with or without
9664 +# modification, are permitted provided that the following conditions
9667 +# 1. Redistributions of source code must retain the above copyright
9668 +# notice, this list of conditions and the following disclaimer.
9670 +# 2. Redistributions in binary form must reproduce the above copyright
9671 +# notice, this list of conditions and the following disclaimer in the
9672 +# documentation and/or other materials provided with the distribution.
9674 +# 3. Neither the name of JANET(UK) nor the names of its contributors
9675 +# may be used to endorse or promote products derived from this software
9676 +# without specific prior written permission.
9678 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9679 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9680 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9681 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9682 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9683 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9684 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9685 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9686 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9687 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9691 +# Placeholders only
9694 +error_code GSSEAP_RSE_OK, ""
9697 diff --git a/mech_eap/release_any_name_mapping.c b/mech_eap/release_any_name_mapping.c
9698 new file mode 100644
9699 index 0000000..d68fb45
9701 +++ b/mech_eap/release_any_name_mapping.c
9704 + * Copyright (c) 2011, JANET(UK)
9705 + * All rights reserved.
9707 + * Redistribution and use in source and binary forms, with or without
9708 + * modification, are permitted provided that the following conditions
9711 + * 1. Redistributions of source code must retain the above copyright
9712 + * notice, this list of conditions and the following disclaimer.
9714 + * 2. Redistributions in binary form must reproduce the above copyright
9715 + * notice, this list of conditions and the following disclaimer in the
9716 + * documentation and/or other materials provided with the distribution.
9718 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9719 + * may be used to endorse or promote products derived from this software
9720 + * without specific prior written permission.
9722 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9723 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9724 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9725 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9726 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9727 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9728 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9729 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9730 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9731 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9735 +#include "gssapiP_eap.h"
9737 +OM_uint32 GSSAPI_CALLCONV
9738 +gss_release_any_name_mapping(OM_uint32 *minor,
9740 + gss_buffer_t type_id,
9747 + if (name == GSS_C_NO_NAME) {
9749 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
9752 + GSSEAP_MUTEX_LOCK(&name->mutex);
9754 + major = gssEapReleaseAnyNameMapping(minor, name, type_id, input);
9758 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
9762 diff --git a/mech_eap/release_cred.c b/mech_eap/release_cred.c
9763 new file mode 100644
9764 index 0000000..8bb7e54
9766 +++ b/mech_eap/release_cred.c
9769 + * Copyright (c) 2011, JANET(UK)
9770 + * All rights reserved.
9772 + * Redistribution and use in source and binary forms, with or without
9773 + * modification, are permitted provided that the following conditions
9776 + * 1. Redistributions of source code must retain the above copyright
9777 + * notice, this list of conditions and the following disclaimer.
9779 + * 2. Redistributions in binary form must reproduce the above copyright
9780 + * notice, this list of conditions and the following disclaimer in the
9781 + * documentation and/or other materials provided with the distribution.
9783 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9784 + * may be used to endorse or promote products derived from this software
9785 + * without specific prior written permission.
9787 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9788 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9789 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9790 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9791 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9792 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9793 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9794 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9795 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9796 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9801 + * Release a credential handle.
9804 +#include "gssapiP_eap.h"
9806 +OM_uint32 GSSAPI_CALLCONV
9807 +gss_release_cred(OM_uint32 *minor,
9808 + gss_cred_id_t *cred_handle)
9810 + return gssEapReleaseCred(minor, cred_handle);
9812 diff --git a/mech_eap/release_name.c b/mech_eap/release_name.c
9813 new file mode 100644
9814 index 0000000..3d527ce
9816 +++ b/mech_eap/release_name.c
9819 + * Copyright (c) 2011, JANET(UK)
9820 + * All rights reserved.
9822 + * Redistribution and use in source and binary forms, with or without
9823 + * modification, are permitted provided that the following conditions
9826 + * 1. Redistributions of source code must retain the above copyright
9827 + * notice, this list of conditions and the following disclaimer.
9829 + * 2. Redistributions in binary form must reproduce the above copyright
9830 + * notice, this list of conditions and the following disclaimer in the
9831 + * documentation and/or other materials provided with the distribution.
9833 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9834 + * may be used to endorse or promote products derived from this software
9835 + * without specific prior written permission.
9837 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9838 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9839 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9840 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9841 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9842 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9843 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9844 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9845 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9846 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9854 +#include "gssapiP_eap.h"
9856 +OM_uint32 GSSAPI_CALLCONV
9857 +gss_release_name(OM_uint32 *minor,
9860 + return gssEapReleaseName(minor, name);
9862 diff --git a/mech_eap/release_oid.c b/mech_eap/release_oid.c
9863 new file mode 100644
9864 index 0000000..291da40
9866 +++ b/mech_eap/release_oid.c
9869 + * Copyright (c) 2011, JANET(UK)
9870 + * All rights reserved.
9872 + * Redistribution and use in source and binary forms, with or without
9873 + * modification, are permitted provided that the following conditions
9876 + * 1. Redistributions of source code must retain the above copyright
9877 + * notice, this list of conditions and the following disclaimer.
9879 + * 2. Redistributions in binary form must reproduce the above copyright
9880 + * notice, this list of conditions and the following disclaimer in the
9881 + * documentation and/or other materials provided with the distribution.
9883 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9884 + * may be used to endorse or promote products derived from this software
9885 + * without specific prior written permission.
9887 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9888 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9889 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9890 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9891 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9892 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9893 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9894 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9895 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9896 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9901 + * Mark an internalized OID as not required to be released.
9904 +#include "gssapiP_eap.h"
9906 +OM_uint32 GSSAPI_CALLCONV
9907 +gss_internal_release_oid(OM_uint32 *minor,
9910 + return gssEapReleaseOid(minor, oid);
9912 diff --git a/mech_eap/set_cred_option.c b/mech_eap/set_cred_option.c
9913 new file mode 100644
9914 index 0000000..7bb9b7b
9916 +++ b/mech_eap/set_cred_option.c
9919 + * Copyright (c) 2011, JANET(UK)
9920 + * All rights reserved.
9922 + * Redistribution and use in source and binary forms, with or without
9923 + * modification, are permitted provided that the following conditions
9926 + * 1. Redistributions of source code must retain the above copyright
9927 + * notice, this list of conditions and the following disclaimer.
9929 + * 2. Redistributions in binary form must reproduce the above copyright
9930 + * notice, this list of conditions and the following disclaimer in the
9931 + * documentation and/or other materials provided with the distribution.
9933 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9934 + * may be used to endorse or promote products derived from this software
9935 + * without specific prior written permission.
9937 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9938 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9939 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9940 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9941 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9942 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9943 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9944 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9945 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9946 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9951 + * Set an extended property on a credential handle.
9954 +#include "gssapiP_eap.h"
9957 +setCredRadiusConfigFile(OM_uint32 *minor,
9958 + gss_cred_id_t cred,
9959 + const gss_OID oid GSSEAP_UNUSED,
9960 + const gss_buffer_t buffer)
9962 + OM_uint32 major, tmpMinor;
9963 + gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
9965 + if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
9966 + major = duplicateBuffer(minor, buffer, &configFileBuffer);
9967 + if (GSS_ERROR(major))
9971 + gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
9972 + cred->radiusConfigFile = configFileBuffer;
9975 + return GSS_S_COMPLETE;
9979 +setCredRadiusConfigStanza(OM_uint32 *minor,
9980 + gss_cred_id_t cred,
9981 + const gss_OID oid GSSEAP_UNUSED,
9982 + const gss_buffer_t buffer)
9984 + OM_uint32 major, tmpMinor;
9985 + gss_buffer_desc configStanzaBuffer = GSS_C_EMPTY_BUFFER;
9987 + if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
9988 + major = duplicateBuffer(minor, buffer, &configStanzaBuffer);
9989 + if (GSS_ERROR(major))
9993 + gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
9994 + cred->radiusConfigStanza = configStanzaBuffer;
9997 + return GSS_S_COMPLETE;
10001 +setCredFlag(OM_uint32 *minor,
10002 + gss_cred_id_t cred,
10003 + const gss_OID oid GSSEAP_UNUSED,
10004 + const gss_buffer_t buffer)
10007 + unsigned char *p;
10009 + if (buffer == GSS_C_NO_BUFFER) {
10011 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_FAILURE;
10014 + if (buffer->length < 4) {
10015 + *minor = GSSEAP_WRONG_SIZE;
10016 + return GSS_S_FAILURE;
10019 + p = (unsigned char *)buffer->value;
10021 + flags = load_uint32_be(buffer->value) & CRED_FLAG_PUBLIC_MASK;
10023 + if (buffer->length > 4 && p[4])
10024 + cred->flags &= ~(flags);
10026 + cred->flags |= flags;
10029 + return GSS_S_COMPLETE;
10033 +setCredPassword(OM_uint32 *minor,
10034 + gss_cred_id_t cred,
10035 + const gss_OID oid GSSEAP_UNUSED,
10036 + const gss_buffer_t buffer)
10038 + return gssEapSetCredPassword(minor, cred, buffer);
10042 + gss_OID_desc oid;
10043 + OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t cred,
10044 + const gss_OID, const gss_buffer_t);
10045 +} setCredOps[] = {
10046 + /* 1.3.6.1.4.1.5322.22.3.3.1 */
10048 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x01" },
10049 + setCredRadiusConfigFile,
10051 + /* 1.3.6.1.4.1.5322.22.3.3.2 */
10053 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x02" },
10054 + setCredRadiusConfigStanza,
10056 + /* 1.3.6.1.4.1.5322.22.3.3.3 */
10058 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x03" },
10061 + /* 1.3.6.1.4.1.5322.22.3.3.4 */
10063 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x04" },
10068 +gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE = &setCredOps[0].oid;
10069 +gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA = &setCredOps[1].oid;
10070 +gss_OID GSS_EAP_CRED_SET_CRED_FLAG = &setCredOps[2].oid;
10071 +gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD = &setCredOps[3].oid;
10073 +OM_uint32 GSSAPI_CALLCONV
10074 +gssspi_set_cred_option(OM_uint32 *minor,
10075 + gss_cred_id_t *pCred,
10076 + const gss_OID desired_object,
10077 + const gss_buffer_t value)
10080 + gss_cred_id_t cred = *pCred;
10083 + if (cred == GSS_C_NO_CREDENTIAL) {
10085 + return GSS_S_UNAVAILABLE;
10088 + GSSEAP_MUTEX_LOCK(&cred->mutex);
10090 + major = GSS_S_UNAVAILABLE;
10091 + *minor = GSSEAP_BAD_CRED_OPTION;
10093 + for (i = 0; i < sizeof(setCredOps) / sizeof(setCredOps[0]); i++) {
10094 + if (oidEqual(&setCredOps[i].oid, desired_object)) {
10095 + major = (*setCredOps[i].setOption)(minor, cred,
10096 + desired_object, value);
10101 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
10108 +gsseap_set_cred_flag(OM_uint32 *minor,
10109 + gss_cred_id_t cred,
10113 + unsigned char buf[5];
10114 + gss_buffer_desc value;
10116 + value.length = sizeof(buf);
10117 + value.value = buf;
10119 + store_uint32_be(flag, buf);
10120 + buf[4] = (clear != 0);
10122 + return gssspi_set_cred_option(minor, &cred,
10123 + GSS_EAP_CRED_SET_CRED_FLAG, &value);
10126 diff --git a/mech_eap/set_name_attribute.c b/mech_eap/set_name_attribute.c
10127 new file mode 100644
10128 index 0000000..2ccf5d7
10130 +++ b/mech_eap/set_name_attribute.c
10133 + * Copyright (c) 2011, JANET(UK)
10134 + * All rights reserved.
10136 + * Redistribution and use in source and binary forms, with or without
10137 + * modification, are permitted provided that the following conditions
10140 + * 1. Redistributions of source code must retain the above copyright
10141 + * notice, this list of conditions and the following disclaimer.
10143 + * 2. Redistributions in binary form must reproduce the above copyright
10144 + * notice, this list of conditions and the following disclaimer in the
10145 + * documentation and/or other materials provided with the distribution.
10147 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10148 + * may be used to endorse or promote products derived from this software
10149 + * without specific prior written permission.
10151 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10152 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10153 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10154 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10155 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10156 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10157 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10158 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10159 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10160 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10165 + * Set an attribute on a name.
10168 +#include "gssapiP_eap.h"
10170 +OM_uint32 GSSAPI_CALLCONV
10171 +gss_set_name_attribute(OM_uint32 *minor,
10174 + gss_buffer_t attr,
10175 + gss_buffer_t value)
10179 + if (name == GSS_C_NO_NAME) {
10181 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
10184 + GSSEAP_MUTEX_LOCK(&name->mutex);
10186 + major = gssEapSetNameAttribute(minor, name, complete, attr, value);
10188 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
10192 diff --git a/mech_eap/set_sec_context_option.c b/mech_eap/set_sec_context_option.c
10193 new file mode 100644
10194 index 0000000..f9fa3a6
10196 +++ b/mech_eap/set_sec_context_option.c
10199 + * Copyright (c) 2011, JANET(UK)
10200 + * All rights reserved.
10202 + * Redistribution and use in source and binary forms, with or without
10203 + * modification, are permitted provided that the following conditions
10206 + * 1. Redistributions of source code must retain the above copyright
10207 + * notice, this list of conditions and the following disclaimer.
10209 + * 2. Redistributions in binary form must reproduce the above copyright
10210 + * notice, this list of conditions and the following disclaimer in the
10211 + * documentation and/or other materials provided with the distribution.
10213 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10214 + * may be used to endorse or promote products derived from this software
10215 + * without specific prior written permission.
10217 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10218 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10219 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10220 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10221 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10222 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10223 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10224 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10225 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10226 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10231 + * Set an extended property on a context handle.
10234 +#include "gssapiP_eap.h"
10238 + gss_OID_desc oid;
10239 + OM_uint32 (*setOption)(OM_uint32 *, gss_ctx_id_t *pCtx,
10240 + const gss_OID, const gss_buffer_t);
10245 +OM_uint32 GSSAPI_CALLCONV
10246 +gss_set_sec_context_option(OM_uint32 *minor,
10247 + gss_ctx_id_t *pCtx,
10248 + const gss_OID desired_object GSSEAP_UNUSED,
10249 + const gss_buffer_t value GSSEAP_UNUSED)
10252 + gss_ctx_id_t ctx;
10257 + major = GSS_S_UNAVAILABLE;
10258 + *minor = GSSEAP_BAD_CONTEXT_OPTION;
10260 + if (pCtx == NULL)
10261 + ctx = GSS_C_NO_CONTEXT;
10265 + if (ctx != GSS_C_NO_CONTEXT)
10266 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
10269 + for (i = 0; i < sizeof(setCtxOps) / sizeof(setCtxOps[0]); i++) {
10270 + if (oidEqual(&setCtxOps[i].oid, desired_object)) {
10271 + major = (*setCtxOps[i].setOption)(minor, &ctx,
10272 + desired_object, value);
10278 + if (pCtx != NULL && *pCtx == NULL)
10280 + else if (ctx != GSS_C_NO_CONTEXT)
10281 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
10285 diff --git a/mech_eap/store_cred.c b/mech_eap/store_cred.c
10286 new file mode 100644
10287 index 0000000..d17a3ac
10289 +++ b/mech_eap/store_cred.c
10292 + * Copyright (c) 2011, JANET(UK)
10293 + * All rights reserved.
10295 + * Redistribution and use in source and binary forms, with or without
10296 + * modification, are permitted provided that the following conditions
10299 + * 1. Redistributions of source code must retain the above copyright
10300 + * notice, this list of conditions and the following disclaimer.
10302 + * 2. Redistributions in binary form must reproduce the above copyright
10303 + * notice, this list of conditions and the following disclaimer in the
10304 + * documentation and/or other materials provided with the distribution.
10306 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10307 + * may be used to endorse or promote products derived from this software
10308 + * without specific prior written permission.
10310 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10311 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10312 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10313 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10314 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10315 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10316 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10317 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10318 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10319 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10323 +#include "gssapiP_eap.h"
10325 +OM_uint32 GSSAPI_CALLCONV
10326 +gss_store_cred(OM_uint32 *minor,
10327 + const gss_cred_id_t cred,
10328 + gss_cred_usage_t input_usage,
10329 + const gss_OID desired_mech GSSEAP_UNUSED,
10330 +#ifdef GSSEAP_ENABLE_REAUTH
10331 + OM_uint32 overwrite_cred,
10332 + OM_uint32 default_cred,
10334 + OM_uint32 overwrite_cred GSSEAP_UNUSED,
10335 + OM_uint32 default_cred GSSEAP_UNUSED,
10337 + gss_OID_set *elements_stored,
10338 + gss_cred_usage_t *cred_usage_stored)
10342 + if (elements_stored != NULL)
10343 + *elements_stored = GSS_C_NO_OID_SET;
10344 + if (cred_usage_stored != NULL)
10345 + *cred_usage_stored = input_usage;
10347 + if (cred == GSS_C_NO_CREDENTIAL) {
10349 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
10352 + GSSEAP_MUTEX_LOCK(&cred->mutex);
10354 + major = GSS_S_COMPLETE;
10357 +#ifdef GSSEAP_ENABLE_REAUTH
10358 + if (cred->reauthCred != GSS_C_NO_CREDENTIAL) {
10359 + major = gssStoreCred(minor,
10360 + cred->reauthCred,
10362 + (gss_OID)gss_mech_krb5,
10366 + cred_usage_stored);
10370 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
10374 diff --git a/mech_eap/unwrap.c b/mech_eap/unwrap.c
10375 new file mode 100644
10376 index 0000000..a185035
10378 +++ b/mech_eap/unwrap.c
10381 + * Copyright (c) 2011, JANET(UK)
10382 + * All rights reserved.
10384 + * Redistribution and use in source and binary forms, with or without
10385 + * modification, are permitted provided that the following conditions
10388 + * 1. Redistributions of source code must retain the above copyright
10389 + * notice, this list of conditions and the following disclaimer.
10391 + * 2. Redistributions in binary form must reproduce the above copyright
10392 + * notice, this list of conditions and the following disclaimer in the
10393 + * documentation and/or other materials provided with the distribution.
10395 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10396 + * may be used to endorse or promote products derived from this software
10397 + * without specific prior written permission.
10399 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10400 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10401 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10402 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10403 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10404 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10405 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10406 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10407 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10408 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10413 + * Message protection services: unwrap.
10416 +#include "gssapiP_eap.h"
10418 +OM_uint32 GSSAPI_CALLCONV
10419 +gss_unwrap(OM_uint32 *minor,
10420 + gss_ctx_id_t ctx,
10421 + gss_buffer_t input_message_buffer,
10422 + gss_buffer_t output_message_buffer,
10424 + gss_qop_t *qop_state)
10426 + OM_uint32 major, tmpMinor;
10427 + gss_iov_buffer_desc iov[2];
10429 + if (ctx == GSS_C_NO_CONTEXT) {
10431 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
10436 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
10438 + if (!CTX_IS_ESTABLISHED(ctx)) {
10439 + major = GSS_S_NO_CONTEXT;
10440 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
10444 + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
10445 + iov[0].buffer = *input_message_buffer;
10447 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
10448 + iov[1].buffer.value = NULL;
10449 + iov[1].buffer.length = 0;
10451 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
10452 + iov, 2, TOK_TYPE_WRAP);
10453 + if (major == GSS_S_COMPLETE) {
10454 + *output_message_buffer = iov[1].buffer;
10456 + if (iov[1].type & GSS_IOV_BUFFER_FLAG_ALLOCATED)
10457 + gss_release_buffer(&tmpMinor, &iov[1].buffer);
10461 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
10465 diff --git a/mech_eap/unwrap_iov.c b/mech_eap/unwrap_iov.c
10466 new file mode 100644
10467 index 0000000..5ceefa2
10469 +++ b/mech_eap/unwrap_iov.c
10472 + * Copyright (c) 2011, JANET(UK)
10473 + * All rights reserved.
10475 + * Redistribution and use in source and binary forms, with or without
10476 + * modification, are permitted provided that the following conditions
10479 + * 1. Redistributions of source code must retain the above copyright
10480 + * notice, this list of conditions and the following disclaimer.
10482 + * 2. Redistributions in binary form must reproduce the above copyright
10483 + * notice, this list of conditions and the following disclaimer in the
10484 + * documentation and/or other materials provided with the distribution.
10486 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10487 + * may be used to endorse or promote products derived from this software
10488 + * without specific prior written permission.
10490 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10491 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10492 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10493 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10494 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10495 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10496 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10497 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10498 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10499 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10503 + * Copyright 2008 by the Massachusetts Institute of Technology.
10504 + * All Rights Reserved.
10506 + * Export of this software from the United States of America may
10507 + * require a specific license from the United States Government.
10508 + * It is the responsibility of any person or organization contemplating
10509 + * export to obtain such a license before exporting.
10511 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10512 + * distribute this software and its documentation for any purpose and
10513 + * without fee is hereby granted, provided that the above copyright
10514 + * notice appear in all copies and that both that copyright notice and
10515 + * this permission notice appear in supporting documentation, and that
10516 + * the name of M.I.T. not be used in advertising or publicity pertaining
10517 + * to distribution of the software without specific, written prior
10518 + * permission. Furthermore if you modify this software you must label
10519 + * your software as modified software and not distribute it in such a
10520 + * fashion that it might be confused with the original M.I.T. software.
10521 + * M.I.T. makes no representations about the suitability of
10522 + * this software for any purpose. It is provided "as is" without express
10523 + * or implied warranty.
10527 + * Message protection services: unwrap with scatter-gather API.
10530 +#include "gssapiP_eap.h"
10533 + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except
10534 + * for DCE in which case it can just provide TOKEN | DATA (must
10535 + * guarantee that DATA is padded)
10538 +unwrapToken(OM_uint32 *minor,
10539 + gss_ctx_id_t ctx,
10540 +#ifdef HAVE_HEIMDAL_VERSION
10541 + krb5_crypto krbCrypto,
10543 + krb5_keyblock *unused GSSEAP_UNUSED,
10546 + gss_qop_t *qop_state,
10547 + gss_iov_buffer_desc *iov,
10549 + enum gss_eap_token_type toktype)
10551 + OM_uint32 major = GSS_S_FAILURE, code;
10552 + gss_iov_buffer_t header;
10553 + gss_iov_buffer_t padding;
10554 + gss_iov_buffer_t trailer;
10555 + unsigned char flags;
10556 + unsigned char *ptr = NULL;
10559 + size_t dataLen, assocDataLen;
10562 + int conf_flag = 0;
10563 + krb5_context krbContext;
10564 +#ifdef HAVE_HEIMDAL_VERSION
10565 + int freeCrypto = (krbCrypto == NULL);
10568 + GSSEAP_KRB_INIT(&krbContext);
10572 + if (qop_state != NULL)
10573 + *qop_state = GSS_C_QOP_DEFAULT;
10575 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
10576 + GSSEAP_ASSERT(header != NULL);
10578 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
10579 + if (padding != NULL && padding->buffer.length != 0) {
10580 + code = GSSEAP_BAD_PADDING_IOV;
10581 + major = GSS_S_DEFECTIVE_TOKEN;
10585 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
10587 + flags = rfc4121Flags(ctx, TRUE);
10589 + if (toktype == TOK_TYPE_WRAP) {
10590 + keyUsage = !CTX_IS_INITIATOR(ctx)
10591 + ? KEY_USAGE_INITIATOR_SEAL
10592 + : KEY_USAGE_ACCEPTOR_SEAL;
10594 + keyUsage = !CTX_IS_INITIATOR(ctx)
10595 + ? KEY_USAGE_INITIATOR_SIGN
10596 + : KEY_USAGE_ACCEPTOR_SIGN;
10599 + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
10601 + ptr = (unsigned char *)header->buffer.value;
10603 + if (header->buffer.length < 16) {
10604 + code = GSSEAP_TOK_TRUNC;
10605 + major = GSS_S_DEFECTIVE_TOKEN;
10609 + if ((ptr[2] & flags) != flags) {
10610 + code = GSSEAP_BAD_DIRECTION;
10611 + major = GSS_S_BAD_SIG;
10615 +#ifdef HAVE_HEIMDAL_VERSION
10616 + if (krbCrypto == NULL) {
10617 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key,
10618 + ETYPE_NULL, &krbCrypto);
10624 + if (toktype == TOK_TYPE_WRAP) {
10625 + size_t krbTrailerLen;
10627 + if (load_uint16_be(ptr) != TOK_TYPE_WRAP)
10629 + conf_flag = ((ptr[2] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
10630 + if (ptr[3] != 0xFF)
10632 + ec = load_uint16_be(ptr + 4);
10633 + rrc = load_uint16_be(ptr + 6);
10634 + seqnum = load_uint64_be(ptr + 8);
10636 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10637 + conf_flag ? KRB5_CRYPTO_TYPE_TRAILER :
10638 + KRB5_CRYPTO_TYPE_CHECKSUM,
10643 + /* Deal with RRC */
10644 + if (trailer == NULL) {
10645 + size_t desired_rrc = krbTrailerLen;
10648 + desired_rrc += 16; /* E(Header) */
10650 + if ((ctx->gssFlags & GSS_C_DCE_STYLE) == 0)
10651 + desired_rrc += ec;
10654 + /* According to MS, we only need to deal with a fixed RRC for DCE */
10655 + if (rrc != desired_rrc)
10657 + } else if (rrc != 0) {
10662 + unsigned char *althdr;
10665 + code = gssEapDecrypt(krbContext,
10666 + ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0),
10667 + ec, rrc, KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10670 + major = GSS_S_BAD_SIG;
10674 + /* Validate header integrity */
10675 + if (trailer == NULL)
10676 + althdr = (unsigned char *)header->buffer.value + 16 + ec;
10678 + althdr = (unsigned char *)trailer->buffer.value + ec;
10680 + if (load_uint16_be(althdr) != TOK_TYPE_WRAP
10681 + || althdr[2] != ptr[2]
10682 + || althdr[3] != ptr[3]
10683 + || memcmp(althdr + 8, ptr + 8, 8) != 0) {
10684 + code = GSSEAP_BAD_WRAP_TOKEN;
10685 + major = GSS_S_BAD_SIG;
10689 + /* Verify checksum: note EC is checksum size here, not padding */
10690 + if (ec != krbTrailerLen)
10693 + /* Zero EC, RRC before computing checksum */
10694 + store_uint16_be(0, ptr + 4);
10695 + store_uint16_be(0, ptr + 6);
10697 + code = gssEapVerify(krbContext, ctx->checksumType, rrc,
10698 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10699 + iov, iov_count, &valid);
10700 + if (code != 0 || valid == FALSE) {
10701 + major = GSS_S_BAD_SIG;
10706 + code = sequenceCheck(minor, &ctx->seqState, seqnum);
10707 + } else if (toktype == TOK_TYPE_MIC) {
10708 + if (load_uint16_be(ptr) != toktype)
10712 + if (ptr[3] != 0xFF)
10714 + seqnum = load_uint64_be(ptr + 8);
10717 + * Although MIC tokens don't have a RRC, they are similarly
10718 + * composed of a header and a checksum. So the verify_mic()
10719 + * can be implemented with a single header buffer, fake the
10720 + * RRC to the putative trailer length if no trailer buffer.
10722 + code = gssEapVerify(krbContext, ctx->checksumType,
10723 + trailer != NULL ? 0 : header->buffer.length - 16,
10724 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10725 + iov, iov_count, &valid);
10726 + if (code != 0 || valid == FALSE) {
10727 + major = GSS_S_BAD_SIG;
10730 + code = sequenceCheck(minor, &ctx->seqState, seqnum);
10731 + } else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
10732 + if (load_uint16_be(ptr) != TOK_TYPE_DELETE_CONTEXT)
10734 + goto verify_mic_1;
10739 + if (conf_state != NULL)
10740 + *conf_state = conf_flag;
10743 + major = GSS_S_COMPLETE;
10747 + code = GSSEAP_BAD_WRAP_TOKEN;
10748 + major = GSS_S_DEFECTIVE_TOKEN;
10752 +#ifdef HAVE_HEIMDAL_VERSION
10753 + if (freeCrypto && krbCrypto != NULL)
10754 + krb5_crypto_destroy(krbContext, krbCrypto);
10761 +rotateLeft(void *ptr, size_t bufsiz, size_t rc)
10767 + rc = rc % bufsiz;
10771 + tbuf = GSSEAP_MALLOC(rc);
10772 + if (tbuf == NULL)
10775 + memcpy(tbuf, ptr, rc);
10776 + memmove(ptr, (char *)ptr + rc, bufsiz - rc);
10777 + memcpy((char *)ptr + bufsiz - rc, tbuf, rc);
10778 + GSSEAP_FREE(tbuf);
10784 + * Split a STREAM | SIGN_DATA | DATA into
10785 + * HEADER | SIGN_DATA | DATA | PADDING | TRAILER
10788 +unwrapStream(OM_uint32 *minor,
10789 + gss_ctx_id_t ctx,
10791 + gss_qop_t *qop_state,
10792 + gss_iov_buffer_desc *iov,
10794 + enum gss_eap_token_type toktype)
10796 + unsigned char *ptr;
10797 + OM_uint32 code = 0, major = GSS_S_FAILURE;
10798 + krb5_context krbContext;
10799 + int conf_req_flag;
10801 + gss_iov_buffer_desc *tiov = NULL;
10802 + gss_iov_buffer_t stream, data = NULL;
10803 + gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer;
10804 +#ifdef HAVE_HEIMDAL_VERSION
10805 + krb5_crypto krbCrypto = NULL;
10808 + GSSEAP_KRB_INIT(&krbContext);
10810 + GSSEAP_ASSERT(toktype == TOK_TYPE_WRAP);
10812 + if (toktype != TOK_TYPE_WRAP) {
10813 + code = GSSEAP_WRONG_TOK_ID;
10817 + stream = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM);
10818 + GSSEAP_ASSERT(stream != NULL);
10820 + if (stream->buffer.length < 16) {
10821 + major = GSS_S_DEFECTIVE_TOKEN;
10825 + ptr = (unsigned char *)stream->buffer.value;
10826 + ptr += 2; /* skip token type */
10828 + tiov = (gss_iov_buffer_desc *)GSSEAP_CALLOC((size_t)iov_count + 2,
10829 + sizeof(gss_iov_buffer_desc));
10830 + if (tiov == NULL) {
10836 + theader = &tiov[i++];
10837 + theader->type = GSS_IOV_BUFFER_TYPE_HEADER;
10838 + theader->buffer.value = stream->buffer.value;
10839 + theader->buffer.length = 16;
10841 + /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */
10842 + for (j = 0; j < iov_count; j++) {
10843 + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type);
10845 + if (type == GSS_IOV_BUFFER_TYPE_DATA) {
10846 + if (data != NULL) {
10847 + /* only a single DATA buffer can appear */
10848 + code = GSSEAP_BAD_STREAM_IOV;
10853 + tdata = &tiov[i];
10855 + if (type == GSS_IOV_BUFFER_TYPE_DATA ||
10856 + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
10857 + tiov[i++] = iov[j];
10860 + if (data == NULL) {
10861 + /* a single DATA buffer must be present */
10862 + code = GSSEAP_BAD_STREAM_IOV;
10866 + /* PADDING | TRAILER */
10867 + tpadding = &tiov[i++];
10868 + tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING;
10869 + tpadding->buffer.length = 0;
10870 + tpadding->buffer.value = NULL;
10872 + ttrailer = &tiov[i++];
10873 + ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER;
10875 +#ifdef HAVE_HEIMDAL_VERSION
10876 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
10883 + size_t krbHeaderLen = 0;
10884 + size_t krbTrailerLen = 0;
10886 + conf_req_flag = ((ptr[0] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
10887 + ec = conf_req_flag ? load_uint16_be(ptr + 2) : 0;
10888 + rrc = load_uint16_be(ptr + 4);
10891 + code = rotateLeft((unsigned char *)stream->buffer.value + 16,
10892 + stream->buffer.length - 16, rrc);
10895 + store_uint16_be(0, ptr + 4); /* set RRC to zero */
10898 + if (conf_req_flag) {
10899 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10900 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
10903 + theader->buffer.length += krbHeaderLen; /* length validated later */
10906 + /* no PADDING for CFX, EC is used instead */
10907 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10909 + ? KRB5_CRYPTO_TYPE_TRAILER
10910 + : KRB5_CRYPTO_TYPE_CHECKSUM,
10915 + ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) +
10917 + ttrailer->buffer.value = (unsigned char *)stream->buffer.value +
10918 + stream->buffer.length - ttrailer->buffer.length;
10921 + /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/
10922 + /* CFX: GSS-Header | Kerb-Header | Data | | EC | E(Header) | Kerb-Trailer */
10923 + /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/
10925 + /* validate lengths */
10926 + if (stream->buffer.length < theader->buffer.length +
10927 + tpadding->buffer.length +
10928 + ttrailer->buffer.length) {
10929 + major = GSS_S_DEFECTIVE_TOKEN;
10930 + code = GSSEAP_TOK_TRUNC;
10935 + tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length -
10936 + tpadding->buffer.length - theader->buffer.length;
10938 + GSSEAP_ASSERT(data != NULL);
10940 + if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
10941 + code = gssEapAllocIov(tdata, tdata->buffer.length);
10945 + memcpy(tdata->buffer.value,
10946 + (unsigned char *)stream->buffer.value + theader->buffer.length,
10947 + tdata->buffer.length);
10949 + tdata->buffer.value = (unsigned char *)stream->buffer.value +
10950 + theader->buffer.length;
10953 + GSSEAP_ASSERT(i <= iov_count + 2);
10955 + major = unwrapToken(&code, ctx, KRB_CRYPTO_CONTEXT(ctx),
10956 + conf_state, qop_state, tiov, i, toktype);
10957 + if (major == GSS_S_COMPLETE) {
10959 + } else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
10962 + gss_release_buffer(&tmp, &tdata->buffer);
10963 + tdata->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
10967 + if (tiov != NULL)
10968 + GSSEAP_FREE(tiov);
10969 +#ifdef HAVE_HEIMDAL_VERSION
10970 + if (krbCrypto != NULL)
10971 + krb5_crypto_destroy(krbContext, krbCrypto);
10980 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor,
10981 + gss_ctx_id_t ctx,
10983 + gss_qop_t *qop_state,
10984 + gss_iov_buffer_desc *iov,
10986 + enum gss_eap_token_type toktype)
10990 + if (ctx->encryptionType == ENCTYPE_NULL) {
10991 + *minor = GSSEAP_KEY_UNAVAILABLE;
10992 + return GSS_S_UNAVAILABLE;
10995 + if (gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) {
10996 + major = unwrapStream(minor, ctx, conf_state, qop_state,
10997 + iov, iov_count, toktype);
10999 + major = unwrapToken(minor, ctx,
11000 + NULL, /* krbCrypto */
11001 + conf_state, qop_state,
11002 + iov, iov_count, toktype);
11008 +OM_uint32 GSSAPI_CALLCONV
11009 +gss_unwrap_iov(OM_uint32 *minor,
11010 + gss_ctx_id_t ctx,
11012 + gss_qop_t *qop_state,
11013 + gss_iov_buffer_desc *iov,
11018 + if (ctx == GSS_C_NO_CONTEXT) {
11020 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
11025 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
11027 + if (!CTX_IS_ESTABLISHED(ctx)) {
11028 + major = GSS_S_NO_CONTEXT;
11029 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
11033 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
11034 + iov, iov_count, TOK_TYPE_WRAP);
11035 + if (GSS_ERROR(major))
11039 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
11043 diff --git a/mech_eap/util.h b/mech_eap/util.h
11044 new file mode 100644
11045 index 0000000..4f54d41
11047 +++ b/mech_eap/util.h
11050 + * Copyright (c) 2011, JANET(UK)
11051 + * All rights reserved.
11053 + * Redistribution and use in source and binary forms, with or without
11054 + * modification, are permitted provided that the following conditions
11057 + * 1. Redistributions of source code must retain the above copyright
11058 + * notice, this list of conditions and the following disclaimer.
11060 + * 2. Redistributions in binary form must reproduce the above copyright
11061 + * notice, this list of conditions and the following disclaimer in the
11062 + * documentation and/or other materials provided with the distribution.
11064 + * 3. Neither the name of JANET(UK) nor the names of its contributors
11065 + * may be used to endorse or promote products derived from this software
11066 + * without specific prior written permission.
11068 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
11069 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11070 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11071 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
11072 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11073 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
11074 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11075 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
11076 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
11077 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11081 + * Portions Copyright 2003-2010 Massachusetts Institute of Technology.
11082 + * All Rights Reserved.
11084 + * Export of this software from the United States of America may
11085 + * require a specific license from the United States Government.
11086 + * It is the responsibility of any person or organization contemplating
11087 + * export to obtain such a license before exporting.
11089 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
11090 + * distribute this software and its documentation for any purpose and
11091 + * without fee is hereby granted, provided that the above copyright
11092 + * notice appear in all copies and that both that copyright notice and
11093 + * this permission notice appear in supporting documentation, and that
11094 + * the name of M.I.T. not be used in advertising or publicity pertaining
11095 + * to distribution of the software without specific, written prior
11096 + * permission. Furthermore if you modify this software you must label
11097 + * your software as modified software and not distribute it in such a
11098 + * fashion that it might be confused with the original M.I.T. software.
11099 + * M.I.T. makes no representations about the suitability of
11100 + * this software for any purpose. It is provided "as is" without express
11101 + * or implied warranty.
11106 + * Utility functions.
11110 +#define _UTIL_H_ 1
11112 +#ifdef HAVE_SYS_PARAM_H
11113 +#include <sys/param.h>
11115 +#ifdef HAVE_STDINT_H
11116 +#include <stdint.h>
11118 +#include <string.h>
11119 +#include <errno.h>
11124 +#define inline __inline
11125 +#define snprintf _snprintf
11128 +#ifdef __cplusplus
11133 +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
11136 +#if !defined(WIN32) && !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
11137 +#define GSSEAP_UNUSED __attribute__ ((__unused__))
11139 +#define GSSEAP_UNUSED
11142 +/* util_buffer.c */
11144 +makeStringBuffer(OM_uint32 *minor,
11145 + const char *string,
11146 + gss_buffer_t buffer);
11148 +#define makeStringBufferOrCleanup(src, dst) \
11150 + major = makeStringBuffer((minor), (src), (dst));\
11151 + if (GSS_ERROR(major)) \
11156 +bufferToString(OM_uint32 *minor,
11157 + const gss_buffer_t buffer,
11161 +duplicateBuffer(OM_uint32 *minor,
11162 + const gss_buffer_t src,
11163 + gss_buffer_t dst);
11165 +#define duplicateBufferOrCleanup(src, dst) \
11167 + major = duplicateBuffer((minor), (src), (dst)); \
11168 + if (GSS_ERROR(major)) \
11173 +bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
11175 + return (b1->length == b2->length &&
11176 + memcmp(b1->value, b2->value, b2->length) == 0);
11180 +bufferEqualString(const gss_buffer_t b1, const char *s)
11182 + gss_buffer_desc b2;
11184 + b2.length = strlen(s);
11185 + b2.value = (char *)s;
11187 + return bufferEqual(b1, &b2);
11190 +/* util_cksum.c */
11192 +gssEapSign(krb5_context context,
11193 + krb5_cksumtype type,
11195 +#ifdef HAVE_HEIMDAL_VERSION
11196 + krb5_crypto crypto,
11198 + krb5_keyblock *key,
11200 + krb5_keyusage sign_usage,
11201 + gss_iov_buffer_desc *iov,
11205 +gssEapVerify(krb5_context context,
11206 + krb5_cksumtype type,
11208 +#ifdef HAVE_HEIMDAL_VERSION
11209 + krb5_crypto crypto,
11211 + krb5_keyblock *key,
11213 + krb5_keyusage sign_usage,
11214 + gss_iov_buffer_desc *iov,
11220 +gssEapEncodeGssChannelBindings(OM_uint32 *minor,
11221 + gss_channel_bindings_t chanBindings,
11222 + gss_buffer_t encodedBindings);
11225 +/* util_context.c */
11226 +#define EAP_EXPORT_CONTEXT_V1 1
11228 +enum gss_eap_token_type {
11229 + TOK_TYPE_NONE = 0x0000, /* no token */
11230 + TOK_TYPE_MIC = 0x0404, /* RFC 4121 MIC token */
11231 + TOK_TYPE_WRAP = 0x0504, /* RFC 4121 wrap token */
11232 + TOK_TYPE_EXPORT_NAME = 0x0401, /* RFC 2743 exported name */
11233 + TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* exported composite name */
11234 + TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */
11235 + TOK_TYPE_INITIATOR_CONTEXT = 0x0601, /* initiator-sent context token */
11236 + TOK_TYPE_ACCEPTOR_CONTEXT = 0x0602, /* acceptor-sent context token */
11239 +/* inner token types and flags */
11240 +#define ITOK_TYPE_NONE 0x00000000
11241 +#define ITOK_TYPE_CONTEXT_ERR 0x00000001 /* critical */
11242 +#define ITOK_TYPE_ACCEPTOR_NAME_REQ 0x00000002 /* TBD */
11243 +#define ITOK_TYPE_ACCEPTOR_NAME_RESP 0x00000003 /* TBD */
11244 +#define ITOK_TYPE_EAP_RESP 0x00000004 /* critical, required, if not reauth */
11245 +#define ITOK_TYPE_EAP_REQ 0x00000005 /* critical, required, if not reauth */
11246 +#define ITOK_TYPE_GSS_CHANNEL_BINDINGS 0x00000006 /* critical, required, if not reauth */
11247 +#define ITOK_TYPE_REAUTH_CREDS 0x00000007 /* optional */
11248 +#define ITOK_TYPE_REAUTH_REQ 0x00000008 /* optional */
11249 +#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
11250 +#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */
11251 +#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */
11252 +#define ITOK_TYPE_GSS_FLAGS 0x0000000C /* optional */
11253 +#define ITOK_TYPE_INITIATOR_MIC 0x0000000D /* critical, required, if not reauth */
11254 +#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000E /* TBD */
11256 +#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */
11257 +#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */
11259 +#define ITOK_TYPE_MASK (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
11261 +#define GSSEAP_WIRE_FLAGS_MASK ( GSS_C_MUTUAL_FLAG | \
11262 + GSS_C_DCE_STYLE | \
11263 + GSS_C_IDENTIFY_FLAG | \
11264 + GSS_C_EXTENDED_ERROR_FLAG )
11266 +OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
11267 +OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
11270 +gssEapMakeToken(OM_uint32 *minor,
11271 + gss_ctx_id_t ctx,
11272 + const gss_buffer_t innerToken,
11273 + enum gss_eap_token_type tokenType,
11274 + gss_buffer_t outputToken);
11277 +gssEapVerifyToken(OM_uint32 *minor,
11278 + gss_ctx_id_t ctx,
11279 + const gss_buffer_t inputToken,
11280 + enum gss_eap_token_type *tokenType,
11281 + gss_buffer_t innerInputToken);
11284 +gssEapContextTime(OM_uint32 *minor,
11285 + gss_ctx_id_t context_handle,
11286 + OM_uint32 *time_rec);
11289 +gssEapMakeTokenMIC(OM_uint32 *minor,
11290 + gss_ctx_id_t ctx,
11291 + gss_buffer_t tokenMIC);
11294 +gssEapVerifyTokenMIC(OM_uint32 *minor,
11295 + gss_ctx_id_t ctx,
11296 + const gss_buffer_t tokenMIC);
11299 +OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
11300 +OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
11303 +gssEapPrimaryMechForCred(gss_cred_id_t cred);
11306 +gssEapAcquireCred(OM_uint32 *minor,
11307 + const gss_name_t desiredName,
11308 + OM_uint32 timeReq,
11309 + const gss_OID_set desiredMechs,
11311 + gss_cred_id_t *pCred,
11312 + gss_OID_set *pActualMechs,
11313 + OM_uint32 *timeRec);
11316 +gssEapSetCredPassword(OM_uint32 *minor,
11317 + gss_cred_id_t cred,
11318 + const gss_buffer_t password);
11321 +gssEapSetCredService(OM_uint32 *minor,
11322 + gss_cred_id_t cred,
11323 + const gss_name_t target);
11326 +gssEapResolveInitiatorCred(OM_uint32 *minor,
11327 + const gss_cred_id_t cred,
11328 + const gss_name_t target,
11329 + gss_cred_id_t *resolvedCred);
11331 +int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
11334 +gssEapInquireCred(OM_uint32 *minor,
11335 + gss_cred_id_t cred,
11336 + gss_name_t *name,
11337 + OM_uint32 *pLifetime,
11338 + gss_cred_usage_t *cred_usage,
11339 + gss_OID_set *mechanisms);
11341 +/* util_crypt.c */
11343 +gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
11345 +#ifdef HAVE_HEIMDAL_VERSION
11346 + krb5_crypto crypto,
11348 + krb5_keyblock *key,
11351 + gss_iov_buffer_desc *iov, int iov_count);
11354 +gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
11356 +#ifdef HAVE_HEIMDAL_VERSION
11357 + krb5_crypto crypto,
11359 + krb5_keyblock *key,
11362 + gss_iov_buffer_desc *iov, int iov_count);
11365 +gssEapMapCryptoFlag(OM_uint32 type);
11368 +gssEapLocateIov(gss_iov_buffer_desc *iov,
11373 +gssEapIovMessageLength(gss_iov_buffer_desc *iov,
11375 + size_t *data_length,
11376 + size_t *assoc_data_length);
11379 +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count);
11382 +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count);
11385 +gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
11388 +gssEapDeriveRfc3961Key(OM_uint32 *minor,
11389 + const unsigned char *key,
11390 + size_t keyLength,
11391 + krb5_enctype enctype,
11392 + krb5_keyblock *pKey);
11396 +#ifndef KRB_MALLOC
11398 + * If your Kerberos library uses a different allocator to your
11399 + * GSS mechanism glue, then you might wish to define these in
11400 + * config.h or elsewhere. This should eventually go away when
11401 + * we no longer need to allocate memory that is freed by the
11402 + * Kerberos library.
11404 +#define KRB_CALLOC calloc
11405 +#define KRB_MALLOC malloc
11406 +#define KRB_FREE free
11407 +#define KRB_REALLOC realloc
11408 +#endif /* KRB_MALLOC */
11410 +#ifdef HAVE_HEIMDAL_VERSION
11412 +#define KRB_TIME_FOREVER ((time_t)~0L)
11414 +#define KRB_KEY_TYPE(key) ((key)->keytype)
11415 +#define KRB_KEY_DATA(key) ((key)->keyvalue.data)
11416 +#define KRB_KEY_LENGTH(key) ((key)->keyvalue.length)
11418 +#define KRB_PRINC_LENGTH(princ) ((princ)->name.name_string.len)
11419 +#define KRB_PRINC_TYPE(princ) ((princ)->name.name_type)
11420 +#define KRB_PRINC_NAME(princ) ((princ)->name.name_string.val)
11421 +#define KRB_PRINC_REALM(princ) ((princ)->realm)
11423 +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->keyblock)
11424 +#define KRB_KT_ENT_FREE(c, e) krb5_kt_free_entry((c), (e))
11426 +#define KRB_CRYPTO_CONTEXT(ctx) (krbCrypto)
11428 +#define KRB_DATA_INIT(d) krb5_data_zero((d))
11432 +#define KRB_TIME_FOREVER KRB5_INT32_MAX
11434 +#define KRB_KEY_TYPE(key) ((key)->enctype)
11435 +#define KRB_KEY_DATA(key) ((key)->contents)
11436 +#define KRB_KEY_LENGTH(key) ((key)->length)
11438 +#define KRB_PRINC_LENGTH(princ) (krb5_princ_size(NULL, (princ)))
11439 +#define KRB_PRINC_TYPE(princ) (krb5_princ_type(NULL, (princ)))
11440 +#define KRB_PRINC_NAME(princ) (krb5_princ_name(NULL, (princ)))
11441 +#define KRB_PRINC_REALM(princ) (krb5_princ_realm(NULL, (princ)))
11443 +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->key)
11444 +#define KRB_KT_ENT_FREE(c, e) krb5_free_keytab_entry_contents((c), (e))
11446 +#define KRB_CRYPTO_CONTEXT(ctx) (&(ctx)->rfc3961Key)
11448 +#define KRB_DATA_INIT(d) do { \
11449 + (d)->magic = KV5M_DATA; \
11450 + (d)->length = 0; \
11451 + (d)->data = NULL; \
11454 +#endif /* HAVE_HEIMDAL_VERSION */
11456 +#define KRB_KEY_INIT(key) do { \
11457 + KRB_KEY_TYPE(key) = ENCTYPE_NULL; \
11458 + KRB_KEY_DATA(key) = NULL; \
11459 + KRB_KEY_LENGTH(key) = 0; \
11462 +#define GSSEAP_KRB_INIT(ctx) do { \
11463 + OM_uint32 tmpMajor; \
11465 + tmpMajor = gssEapKerberosInit(minor, ctx); \
11466 + if (GSS_ERROR(tmpMajor)) { \
11467 + return tmpMajor; \
11472 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context);
11475 +rfc3961ChecksumTypeForKey(OM_uint32 *minor,
11476 + krb5_keyblock *key,
11477 + krb5_cksumtype *cksumtype);
11480 +krbCryptoLength(krb5_context krbContext,
11481 +#ifdef HAVE_HEIMDAL_VERSION
11482 + krb5_crypto krbCrypto,
11484 + krb5_keyblock *key,
11490 +krbPaddingLength(krb5_context krbContext,
11491 +#ifdef HAVE_HEIMDAL_VERSION
11492 + krb5_crypto krbCrypto,
11494 + krb5_keyblock *key,
11496 + size_t dataLength,
11497 + size_t *padLength);
11500 +krbBlockSize(krb5_context krbContext,
11501 +#ifdef HAVE_HEIMDAL_VERSION
11502 + krb5_crypto krbCrypto,
11504 + krb5_keyblock *key,
11506 + size_t *blockSize);
11509 +krbEnctypeToString(krb5_context krbContext,
11510 + krb5_enctype enctype,
11511 + const char *prefix,
11512 + gss_buffer_t string);
11515 +krbMakeAuthDataKdcIssued(krb5_context context,
11516 + const krb5_keyblock *key,
11517 + krb5_const_principal issuer,
11518 +#ifdef HAVE_HEIMDAL_VERSION
11519 + const AuthorizationData *authdata,
11520 + AuthorizationData *adKdcIssued
11522 + krb5_authdata *const *authdata,
11523 + krb5_authdata ***adKdcIssued
11528 +krbMakeCred(krb5_context context,
11529 + krb5_auth_context authcontext,
11530 + krb5_creds *creds,
11531 + krb5_data *data);
11533 +/* util_lucid.c */
11535 +gssEapExportLucidSecContext(OM_uint32 *minor,
11536 + gss_ctx_id_t ctx,
11537 + const gss_OID desiredObject,
11538 + gss_buffer_set_t *data_set);
11541 +extern gss_OID GSS_EAP_MECHANISM;
11543 +#define OID_FLAG_NULL_VALID 0x00000001
11544 +#define OID_FLAG_FAMILY_MECH_VALID 0x00000002
11545 +#define OID_FLAG_MAP_NULL_TO_DEFAULT_MECH 0x00000004
11546 +#define OID_FLAG_MAP_FAMILY_MECH_TO_NULL 0x00000008
11549 +gssEapCanonicalizeOid(OM_uint32 *minor,
11550 + const gss_OID oid,
11555 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid);
11558 +gssEapDefaultMech(OM_uint32 *minor,
11562 +gssEapIndicateMechs(OM_uint32 *minor,
11563 + gss_OID_set *mechs);
11566 +gssEapEnctypeToOid(OM_uint32 *minor,
11567 + krb5_enctype enctype,
11571 +gssEapOidToEnctype(OM_uint32 *minor,
11572 + const gss_OID oid,
11573 + krb5_enctype *enctype);
11576 +gssEapIsMechanismOid(const gss_OID oid);
11579 +gssEapIsConcreteMechanismOid(const gss_OID oid);
11582 +gssEapValidateMechs(OM_uint32 *minor,
11583 + const gss_OID_set mechs);
11586 +gssEapOidToSaslName(const gss_OID oid);
11589 +gssEapSaslNameToOid(const gss_buffer_t name);
11591 +/* util_moonshot.c */
11593 +libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
11594 + const gss_cred_id_t cred,
11595 + gss_name_t *pName);
11598 +libMoonshotResolveInitiatorCred(OM_uint32 *minor,
11599 + gss_cred_id_t cred,
11600 + const gss_name_t targetName);
11603 +#define EXPORT_NAME_FLAG_OID 0x1
11604 +#define EXPORT_NAME_FLAG_COMPOSITE 0x2
11605 +#define EXPORT_NAME_FLAG_ALLOW_COMPOSITE 0x4
11607 +OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
11608 +OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
11609 +OM_uint32 gssEapExportName(OM_uint32 *minor,
11610 + const gss_name_t name,
11611 + gss_buffer_t exportedName);
11612 +OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
11613 + const gss_name_t name,
11614 + gss_buffer_t exportedName,
11615 + OM_uint32 flags);
11616 +OM_uint32 gssEapImportName(OM_uint32 *minor,
11617 + const gss_buffer_t input_name_buffer,
11618 + const gss_OID input_name_type,
11619 + const gss_OID input_mech_type,
11620 + gss_name_t *output_name);
11621 +OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
11622 + const gss_buffer_t input_name_buffer,
11623 + gss_name_t *output_name,
11624 + OM_uint32 flags);
11626 +gssEapDuplicateName(OM_uint32 *minor,
11627 + const gss_name_t input_name,
11628 + gss_name_t *dest_name);
11631 +gssEapCanonicalizeName(OM_uint32 *minor,
11632 + const gss_name_t input_name,
11633 + const gss_OID mech_type,
11634 + gss_name_t *dest_name);
11637 +gssEapDisplayName(OM_uint32 *minor,
11639 + gss_buffer_t output_name_buffer,
11640 + gss_OID *output_name_type);
11643 +gssEapCompareName(OM_uint32 *minor,
11644 + gss_name_t name1,
11645 + gss_name_t name2,
11646 + int *name_equal);
11650 +composeOid(OM_uint32 *minor_status,
11651 + const char *prefix,
11652 + size_t prefix_len,
11654 + gss_OID_desc *oid);
11657 +decomposeOid(OM_uint32 *minor_status,
11658 + const char *prefix,
11659 + size_t prefix_len,
11660 + gss_OID_desc *oid,
11664 +duplicateOid(OM_uint32 *minor_status,
11665 + const gss_OID_desc * const oid,
11666 + gss_OID *new_oid);
11669 +duplicateOidSet(OM_uint32 *minor,
11670 + const gss_OID_set src,
11671 + gss_OID_set *dst);
11674 +oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2)
11676 + if (o1 == GSS_C_NO_OID)
11677 + return (o2 == GSS_C_NO_OID);
11678 + else if (o2 == GSS_C_NO_OID)
11679 + return (o1 == GSS_C_NO_OID);
11681 + return (o1->length == o2->length &&
11682 + memcmp(o1->elements, o2->elements, o1->length) == 0);
11685 +/* util_ordering.c */
11687 +sequenceInternalize(OM_uint32 *minor,
11689 + unsigned char **buf,
11690 + size_t *lenremain);
11693 +sequenceExternalize(OM_uint32 *minor,
11695 + unsigned char **buf,
11696 + size_t *lenremain);
11699 +sequenceSize(void *vqueue);
11702 +sequenceFree(OM_uint32 *minor, void **vqueue);
11705 +sequenceCheck(OM_uint32 *minor, void **vqueue, uint64_t seqnum);
11708 +sequenceInit(OM_uint32 *minor, void **vqueue, uint64_t seqnum,
11709 + int do_replay, int do_sequence, int wide_nums);
11712 +enum gss_eap_state {
11713 + GSSEAP_STATE_INITIAL = 0x01, /* initial state */
11714 + GSSEAP_STATE_AUTHENTICATE = 0x02, /* exchange EAP messages */
11715 + GSSEAP_STATE_INITIATOR_EXTS = 0x04, /* initiator extensions */
11716 + GSSEAP_STATE_ACCEPTOR_EXTS = 0x08, /* acceptor extensions */
11717 +#ifdef GSSEAP_ENABLE_REAUTH
11718 + GSSEAP_STATE_REAUTHENTICATE = 0x10, /* GSS reauthentication messages */
11720 + GSSEAP_STATE_ESTABLISHED = 0x20, /* context established */
11721 + GSSEAP_STATE_ALL = 0x3F
11724 +#define GSSEAP_STATE_NEXT(s) ((s) << 1)
11726 +#define GSSEAP_SM_STATE(ctx) ((ctx)->state)
11728 +#ifdef GSSEAP_DEBUG
11729 +void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
11730 +#define GSSEAP_SM_TRANSITION(ctx, state) gssEapSmTransition((ctx), (state))
11732 +#define GSSEAP_SM_TRANSITION(ctx, newstate) do { (ctx)->state = (newstate); } while (0)
11735 +#define GSSEAP_SM_TRANSITION_NEXT(ctx) GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT(GSSEAP_SM_STATE((ctx))))
11737 +/* state machine entry */
11738 +struct gss_eap_sm {
11739 + OM_uint32 inputTokenType;
11740 + OM_uint32 outputTokenType;
11741 + enum gss_eap_state validStates;
11742 + OM_uint32 itokFlags;
11743 + OM_uint32 (*processToken)(OM_uint32 *,
11750 + gss_channel_bindings_t,
11756 +/* state machine flags, set by handler */
11757 +#define SM_FLAG_FORCE_SEND_TOKEN 0x00000001 /* send token even if no inner tokens */
11758 +#define SM_FLAG_OUTPUT_TOKEN_CRITICAL 0x00000002 /* output token is critical */
11760 +/* state machine flags, set by state machine */
11761 +#define SM_FLAG_INPUT_TOKEN_CRITICAL 0x10000000 /* input token was critical */
11763 +#define SM_ITOK_FLAG_REQUIRED 0x00000001 /* received tokens must be present */
11766 +gssEapSmStep(OM_uint32 *minor,
11767 + gss_cred_id_t cred,
11768 + gss_ctx_id_t ctx,
11769 + gss_name_t target,
11771 + OM_uint32 reqFlags,
11772 + OM_uint32 timeReq,
11773 + gss_channel_bindings_t chanBindings,
11774 + gss_buffer_t inputToken,
11775 + gss_buffer_t outputToken,
11776 + struct gss_eap_sm *sm,
11780 +gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
11782 +/* util_token.c */
11783 +struct gss_eap_token_buffer_set {
11784 + gss_buffer_set_desc buffers; /* pointers only */
11785 + OM_uint32 *types;
11789 +gssEapEncodeInnerTokens(OM_uint32 *minor,
11790 + struct gss_eap_token_buffer_set *tokens,
11791 + gss_buffer_t buffer);
11793 +gssEapDecodeInnerTokens(OM_uint32 *minor,
11794 + const gss_buffer_t buffer,
11795 + struct gss_eap_token_buffer_set *tokens);
11798 +gssEapReleaseInnerTokens(OM_uint32 *minor,
11799 + struct gss_eap_token_buffer_set *tokens,
11800 + int freeBuffers);
11803 +gssEapAllocInnerTokens(OM_uint32 *minor,
11805 + struct gss_eap_token_buffer_set *tokens);
11808 +tokenSize(const gss_OID_desc *mech, size_t body_size);
11811 +makeTokenHeader(const gss_OID_desc *mech,
11812 + size_t body_size,
11813 + unsigned char **buf,
11814 + enum gss_eap_token_type tok_type);
11817 +verifyTokenHeader(OM_uint32 *minor,
11819 + size_t *body_size,
11820 + unsigned char **buf_in,
11821 + size_t toksize_in,
11822 + enum gss_eap_token_type *ret_tok_type);
11824 +/* Helper macros */
11826 +#ifndef GSSEAP_MALLOC
11827 +#define GSSEAP_CALLOC calloc
11828 +#define GSSEAP_MALLOC malloc
11829 +#define GSSEAP_FREE free
11830 +#define GSSEAP_REALLOC realloc
11833 +#ifndef GSSAPI_CALLCONV
11834 +#define GSSAPI_CALLCONV KRB5_CALLCONV
11837 +#ifndef GSSEAP_ASSERT
11838 +#include <assert.h>
11839 +#define GSSEAP_ASSERT(x) assert((x))
11840 +#endif /* !GSSEAP_ASSERT */
11843 +#define GSSEAP_CONSTRUCTOR
11844 +#define GSSEAP_DESTRUCTOR
11846 +#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
11847 +#define GSSEAP_DESTRUCTOR __attribute__((destructor))
11850 +#define GSSEAP_NOT_IMPLEMENTED do { \
11851 + GSSEAP_ASSERT(0 && "not implemented"); \
11852 + *minor = ENOSYS; \
11853 + return GSS_S_FAILURE; \
11858 +#include <winbase.h>
11860 +#define GSSEAP_GET_LAST_ERROR() (GetLastError()) /* XXX FIXME */
11862 +#define GSSEAP_MUTEX CRITICAL_SECTION
11863 +#define GSSEAP_MUTEX_INIT(m) (InitializeCriticalSection((m)), 0)
11864 +#define GSSEAP_MUTEX_DESTROY(m) DeleteCriticalSection((m))
11865 +#define GSSEAP_MUTEX_LOCK(m) EnterCriticalSection((m))
11866 +#define GSSEAP_MUTEX_UNLOCK(m) LeaveCriticalSection((m))
11867 +#define GSSEAP_ONCE_LEAVE do { return TRUE; } while (0)
11869 +/* Thread-local is handled separately */
11871 +#define GSSEAP_THREAD_ONCE INIT_ONCE
11872 +#define GSSEAP_ONCE_CALLBACK(cb) BOOL CALLBACK cb(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
11873 +#define GSSEAP_ONCE(o, i) InitOnceExecuteOnce((o), (i), NULL, NULL)
11874 +#define GSSEAP_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
11878 +#include <pthread.h>
11880 +#define GSSEAP_GET_LAST_ERROR() (errno)
11882 +#define GSSEAP_MUTEX pthread_mutex_t
11883 +#define GSSEAP_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
11884 +#define GSSEAP_MUTEX_DESTROY(m) pthread_mutex_destroy((m))
11885 +#define GSSEAP_MUTEX_LOCK(m) pthread_mutex_lock((m))
11886 +#define GSSEAP_MUTEX_UNLOCK(m) pthread_mutex_unlock((m))
11888 +#define GSSEAP_THREAD_KEY pthread_key_t
11889 +#define GSSEAP_KEY_CREATE(k, d) pthread_key_create((k), (d))
11890 +#define GSSEAP_GETSPECIFIC(k) pthread_getspecific((k))
11891 +#define GSSEAP_SETSPECIFIC(k, d) pthread_setspecific((k), (d))
11893 +#define GSSEAP_THREAD_ONCE pthread_once_t
11894 +#define GSSEAP_ONCE_CALLBACK(cb) void cb(void)
11895 +#define GSSEAP_ONCE(o, i) pthread_once((o), (i))
11896 +#define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT
11897 +#define GSSEAP_ONCE_LEAVE do { } while (0)
11899 +#endif /* WIN32 */
11901 +/* Helper functions */
11902 +static inline void
11903 +store_uint16_be(uint16_t val, void *vp)
11905 + unsigned char *p = (unsigned char *)vp;
11907 + p[0] = (val >> 8) & 0xff;
11908 + p[1] = (val ) & 0xff;
11911 +static inline uint16_t
11912 +load_uint16_be(const void *cvp)
11914 + const unsigned char *p = (const unsigned char *)cvp;
11916 + return (p[1] | (p[0] << 8));
11919 +static inline void
11920 +store_uint32_be(uint32_t val, void *vp)
11922 + unsigned char *p = (unsigned char *)vp;
11924 + p[0] = (val >> 24) & 0xff;
11925 + p[1] = (val >> 16) & 0xff;
11926 + p[2] = (val >> 8) & 0xff;
11927 + p[3] = (val ) & 0xff;
11930 +static inline uint32_t
11931 +load_uint32_be(const void *cvp)
11933 + const unsigned char *p = (const unsigned char *)cvp;
11935 + return (p[3] | (p[2] << 8)
11936 + | ((uint32_t) p[1] << 16)
11937 + | ((uint32_t) p[0] << 24));
11940 +static inline void
11941 +store_uint64_be(uint64_t val, void *vp)
11943 + unsigned char *p = (unsigned char *)vp;
11945 + p[0] = (unsigned char)((val >> 56) & 0xff);
11946 + p[1] = (unsigned char)((val >> 48) & 0xff);
11947 + p[2] = (unsigned char)((val >> 40) & 0xff);
11948 + p[3] = (unsigned char)((val >> 32) & 0xff);
11949 + p[4] = (unsigned char)((val >> 24) & 0xff);
11950 + p[5] = (unsigned char)((val >> 16) & 0xff);
11951 + p[6] = (unsigned char)((val >> 8) & 0xff);
11952 + p[7] = (unsigned char)((val ) & 0xff);
11955 +static inline uint64_t
11956 +load_uint64_be(const void *cvp)
11958 + const unsigned char *p = (const unsigned char *)cvp;
11960 + return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4);
11963 +static inline unsigned char *
11964 +store_buffer(gss_buffer_t buffer, void *vp, int wide_nums)
11966 + unsigned char *p = (unsigned char *)vp;
11969 + store_uint64_be(buffer->length, p);
11972 + store_uint32_be(buffer->length, p);
11976 + if (buffer->value != NULL) {
11977 + memcpy(p, buffer->value, buffer->length);
11978 + p += buffer->length;
11984 +static inline unsigned char *
11985 +load_buffer(const void *cvp, size_t length, gss_buffer_t buffer)
11987 + buffer->length = 0;
11988 + buffer->value = GSSEAP_MALLOC(length);
11989 + if (buffer->value == NULL)
11991 + buffer->length = length;
11992 + memcpy(buffer->value, cvp, length);
11993 + return (unsigned char *)cvp + length;
11996 +static inline unsigned char *
11997 +store_oid(gss_OID oid, void *vp)
11999 + gss_buffer_desc buf;
12001 + if (oid != GSS_C_NO_OID) {
12002 + buf.length = oid->length;
12003 + buf.value = oid->elements;
12006 + buf.value = NULL;
12009 + return store_buffer(&buf, vp, FALSE);
12012 +static inline void
12013 +krbDataToGssBuffer(krb5_data *data, gss_buffer_t buffer)
12015 + buffer->value = (void *)data->data;
12016 + buffer->length = data->length;
12019 +static inline void
12020 +krbPrincComponentToGssBuffer(krb5_principal krbPrinc,
12021 + int index, gss_buffer_t buffer)
12023 +#ifdef HAVE_HEIMDAL_VERSION
12024 + buffer->value = (void *)KRB_PRINC_NAME(krbPrinc)[index];
12025 + buffer->length = strlen((char *)buffer->value);
12027 + buffer->value = (void *)krb5_princ_component(NULL, krbPrinc, index)->data;
12028 + buffer->length = krb5_princ_component(NULL, krbPrinc, index)->length;
12029 +#endif /* HAVE_HEIMDAL_VERSION */
12032 +static inline void
12033 +krbPrincRealmToGssBuffer(krb5_principal krbPrinc, gss_buffer_t buffer)
12035 +#ifdef HAVE_HEIMDAL_VERSION
12036 + buffer->value = (void *)KRB_PRINC_REALM(krbPrinc);
12037 + buffer->length = strlen((char *)buffer->value);
12039 + krbDataToGssBuffer(KRB_PRINC_REALM(krbPrinc), buffer);
12043 +static inline void
12044 +gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data)
12046 + data->data = (char *)buffer->value;
12047 + data->length = buffer->length;
12051 +struct gss_eap_status_info;
12053 +struct gss_eap_thread_local_data {
12054 + krb5_context krbContext;
12055 + struct gss_eap_status_info *statusInfo;
12058 +struct gss_eap_thread_local_data *
12059 +gssEapGetThreadLocalData(void);
12062 +gssEapDestroyStatusInfo(struct gss_eap_status_info *status);
12065 +gssEapDestroyKrbContext(krb5_context context);
12067 +#ifdef __cplusplus
12071 +#ifdef GSSEAP_ENABLE_ACCEPTOR
12072 +#include "util_json.h"
12073 +#include "util_attr.h"
12074 +#include "util_base64.h"
12075 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
12076 +#ifdef GSSEAP_ENABLE_REAUTH
12077 +#include "util_reauth.h"
12080 +#endif /* _UTIL_H_ */
12081 diff --git a/mech_eap/util_adshim.c b/mech_eap/util_adshim.c
12082 new file mode 100644
12083 index 0000000..513a1a8
12085 +++ b/mech_eap/util_adshim.c
12088 + * Copyright (c) 2011, JANET(UK)
12089 + * All rights reserved.
12091 + * Redistribution and use in source and binary forms, with or without
12092 + * modification, are permitted provided that the following conditions
12095 + * 1. Redistributions of source code must retain the above copyright
12096 + * notice, this list of conditions and the following disclaimer.
12098 + * 2. Redistributions in binary form must reproduce the above copyright
12099 + * notice, this list of conditions and the following disclaimer in the
12100 + * documentation and/or other materials provided with the distribution.
12102 + * 3. Neither the name of JANET(UK) nor the names of its contributors
12103 + * may be used to endorse or promote products derived from this software
12104 + * without specific prior written permission.
12106 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12107 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12108 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12109 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
12110 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12111 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12112 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12113 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12114 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12115 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12119 +#include "gssapiP_eap.h"
12120 +#include "authdata_plugin.h"
12123 + * This rubbish is necessary because MIT doesn't provide another way
12124 + * to access verified AD-KDCIssued elements. We can't verify them
12125 + * ourselves because they're signed in the ticket session key, which
12126 + * is destroyed immediately after the AP-REQ is processed.
12129 +struct radius_ad_context {
12130 + krb5_data avpdata;
12131 + krb5_boolean verified;
12134 +static krb5_data radius_ad_attr = {
12135 + KV5M_DATA, sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp" };
12137 +static krb5_error_code
12138 +radius_ad_init(krb5_context kcontext GSSEAP_UNUSED,
12139 + void **plugin_context)
12141 + *plugin_context = 0;
12146 +radius_ad_flags(krb5_context kcontext GSSEAP_UNUSED,
12147 + void *plugin_context GSSEAP_UNUSED,
12148 + krb5_authdatatype ad_type GSSEAP_UNUSED,
12149 + krb5_flags *flags)
12151 + *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
12155 +radius_ad_fini(krb5_context kcontext GSSEAP_UNUSED,
12156 + void *plugin_context GSSEAP_UNUSED)
12161 +static krb5_error_code
12162 +radius_ad_request_init(krb5_context kcontext GSSEAP_UNUSED,
12163 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12164 + void *plugin_context GSSEAP_UNUSED,
12165 + void **request_context)
12167 + struct radius_ad_context *ctx;
12169 + ctx = GSSEAP_CALLOC(1, sizeof(*ctx));
12173 + *request_context = ctx;
12178 +static krb5_error_code
12179 +radius_ad_export_authdata(krb5_context kcontext,
12180 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12181 + void *plugin_context GSSEAP_UNUSED,
12182 + void *request_context,
12183 + krb5_flags usage GSSEAP_UNUSED,
12184 + krb5_authdata ***out_authdata)
12186 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12187 + krb5_authdata *data[2];
12188 + krb5_authdata datum;
12190 + datum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
12191 + datum.length = radius_ad->avpdata.length;
12192 + datum.contents = (krb5_octet *)radius_ad->avpdata.data;
12194 + data[0] = &datum;
12197 + return krb5_copy_authdata(kcontext, data, out_authdata);
12200 +static krb5_error_code
12201 +radius_ad_import_authdata(krb5_context kcontext,
12202 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12203 + void *plugin_context GSSEAP_UNUSED,
12204 + void *request_context,
12205 + krb5_authdata **authdata,
12206 + krb5_boolean kdc_issued_flag,
12207 + krb5_const_principal issuer GSSEAP_UNUSED)
12209 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12211 + krb5_free_data_contents(kcontext, &radius_ad->avpdata);
12212 + radius_ad->verified = FALSE;
12214 + GSSEAP_ASSERT(authdata[0] != NULL);
12216 + radius_ad->avpdata.data = GSSEAP_MALLOC(authdata[0]->length);
12217 + if (radius_ad->avpdata.data == NULL)
12220 + memcpy(radius_ad->avpdata.data, authdata[0]->contents,
12221 + authdata[0]->length);
12222 + radius_ad->avpdata.length = authdata[0]->length;
12224 + radius_ad->verified = kdc_issued_flag;
12230 +radius_ad_request_fini(krb5_context kcontext,
12231 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12232 + void *plugin_context GSSEAP_UNUSED,
12233 + void *request_context)
12235 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12237 + if (radius_ad != NULL) {
12238 + krb5_free_data_contents(kcontext, &radius_ad->avpdata);
12239 + GSSEAP_FREE(radius_ad);
12243 +static krb5_error_code
12244 +radius_ad_get_attribute(krb5_context kcontext GSSEAP_UNUSED,
12245 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12246 + void *plugin_context GSSEAP_UNUSED,
12247 + void *request_context,
12248 + const krb5_data *attribute,
12249 + krb5_boolean *authenticated,
12250 + krb5_boolean *complete,
12251 + krb5_data *value,
12252 + krb5_data *display_value GSSEAP_UNUSED,
12255 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12257 + if (attribute->length != radius_ad_attr.length ||
12258 + memcmp(attribute->data, radius_ad_attr.data,
12259 + radius_ad_attr.length) != 0)
12262 + if (radius_ad->avpdata.length == 0)
12265 + *authenticated = radius_ad->verified;
12266 + *complete = TRUE;
12269 + value->data = GSSEAP_MALLOC(radius_ad->avpdata.length);
12270 + if (value->data == NULL)
12273 + memcpy(value->data, radius_ad->avpdata.data, radius_ad->avpdata.length);
12274 + value->length = radius_ad->avpdata.length;
12279 +static krb5_error_code
12280 +radius_ad_copy(krb5_context kcontext GSSEAP_UNUSED,
12281 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12282 + void *plugin_context GSSEAP_UNUSED,
12283 + void *request_context,
12284 + void *dst_plugin_context GSSEAP_UNUSED,
12285 + void *dst_request_context)
12287 + struct radius_ad_context *radius_ad_src =
12288 + (struct radius_ad_context *)request_context;
12289 + struct radius_ad_context *radius_ad_dst =
12290 + (struct radius_ad_context *)dst_request_context;
12292 + radius_ad_dst->avpdata.data = GSSEAP_MALLOC(radius_ad_src->avpdata.length);
12293 + if (radius_ad_dst->avpdata.data == NULL)
12296 + memcpy(radius_ad_dst->avpdata.data, radius_ad_src->avpdata.data,
12297 + radius_ad_src->avpdata.length);
12298 + radius_ad_dst->avpdata.length = radius_ad_src->avpdata.length;
12299 + radius_ad_dst->verified = radius_ad_src->verified;
12304 +static krb5_authdatatype radius_ad_ad_types[] =
12305 + { KRB5_AUTHDATA_RADIUS_AVP, 0 };
12307 +krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
12309 + radius_ad_ad_types,
12313 + radius_ad_request_init,
12314 + radius_ad_request_fini,
12316 + radius_ad_get_attribute,
12319 + radius_ad_export_authdata,
12320 + radius_ad_import_authdata,
12329 diff --git a/mech_eap/util_attr.cpp b/mech_eap/util_attr.cpp
12330 new file mode 100644
12331 index 0000000..3bfe785
12333 +++ b/mech_eap/util_attr.cpp
12336 + * Copyright (c) 2011, JANET(UK)
12337 + * All rights reserved.
12339 + * Redistribution and use in source and binary forms, with or without
12340 + * modification, are permitted provided that the following conditions
12343 + * 1. Redistributions of source code must retain the above copyright
12344 + * notice, this list of conditions and the following disclaimer.
12346 + * 2. Redistributions in binary form must reproduce the above copyright
12347 + * notice, this list of conditions and the following disclaimer in the
12348 + * documentation and/or other materials provided with the distribution.
12350 + * 3. Neither the name of JANET(UK) nor the names of its contributors
12351 + * may be used to endorse or promote products derived from this software
12352 + * without specific prior written permission.
12354 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12355 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12356 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12357 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
12358 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12359 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12360 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12361 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12362 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12363 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12368 + * Attribute provider mechanism.
12371 +#include "gssapiP_eap.h"
12373 +#include <typeinfo>
12375 +#include <sstream>
12376 +#include <exception>
12379 +/* lazy initialisation */
12380 +static GSSEAP_THREAD_ONCE gssEapAttrProvidersInitOnce = GSSEAP_ONCE_INITIALIZER;
12381 +static OM_uint32 gssEapAttrProvidersInitStatus = GSS_S_UNAVAILABLE;
12383 +GSSEAP_ONCE_CALLBACK(gssEapAttrProvidersInitInternal)
12385 + OM_uint32 major, minor;
12387 + GSSEAP_ASSERT(gssEapAttrProvidersInitStatus == GSS_S_UNAVAILABLE);
12389 + json_set_alloc_funcs(GSSEAP_MALLOC, GSSEAP_FREE);
12391 + major = gssEapRadiusAttrProviderInit(&minor);
12392 + if (GSS_ERROR(major))
12395 +#ifdef HAVE_OPENSAML
12396 + major = gssEapSamlAttrProvidersInit(&minor);
12397 + if (GSS_ERROR(major))
12401 +#ifdef HAVE_SHIBRESOLVER
12402 + /* Allow Shibboleth initialization failure to be non-fatal */
12403 + gssEapLocalAttrProviderInit(&minor);
12407 +#ifdef GSSEAP_DEBUG
12408 + GSSEAP_ASSERT(major == GSS_S_COMPLETE);
12411 + gssEapAttrProvidersInitStatus = major;
12413 + GSSEAP_ONCE_LEAVE;
12417 +gssEapAttrProvidersInit(OM_uint32 *minor)
12419 + GSSEAP_ONCE(&gssEapAttrProvidersInitOnce, gssEapAttrProvidersInitInternal);
12421 + if (GSS_ERROR(gssEapAttrProvidersInitStatus))
12422 + *minor = GSSEAP_NO_ATTR_PROVIDERS;
12424 + return gssEapAttrProvidersInitStatus;
12428 +gssEapAttrProvidersFinalize(OM_uint32 *minor)
12430 + if (gssEapAttrProvidersInitStatus == GSS_S_COMPLETE) {
12431 +#ifdef HAVE_SHIBRESOLVER
12432 + gssEapLocalAttrProviderFinalize(minor);
12434 +#ifdef HAVE_OPENSAML
12435 + gssEapSamlAttrProvidersFinalize(minor);
12437 + gssEapRadiusAttrProviderFinalize(minor);
12439 + gssEapAttrProvidersInitStatus = GSS_S_UNAVAILABLE;
12442 + return GSS_S_COMPLETE;
12445 +static gss_eap_attr_create_provider gssEapAttrFactories[ATTR_TYPE_MAX + 1];
12448 + * Register a provider for a particular type and prefix
12451 +gss_eap_attr_ctx::registerProvider(unsigned int type,
12452 + gss_eap_attr_create_provider factory)
12454 + GSSEAP_ASSERT(type <= ATTR_TYPE_MAX);
12456 + GSSEAP_ASSERT(gssEapAttrFactories[type] == NULL);
12458 + gssEapAttrFactories[type] = factory;
12462 + * Unregister a provider
12465 +gss_eap_attr_ctx::unregisterProvider(unsigned int type)
12467 + GSSEAP_ASSERT(type <= ATTR_TYPE_MAX);
12469 + gssEapAttrFactories[type] = NULL;
12473 + * Create an attribute context, that manages instances of providers
12475 +gss_eap_attr_ctx::gss_eap_attr_ctx(void)
12479 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12480 + gss_eap_attr_provider *provider;
12482 + if (gssEapAttrFactories[i] != NULL) {
12483 + provider = (gssEapAttrFactories[i])();
12488 + m_providers[i] = provider;
12493 + * Convert an attribute prefix to a type
12496 +gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix) const
12500 + for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
12501 + const char *pprefix;
12503 + if (!providerEnabled(i))
12506 + pprefix = m_providers[i]->prefix();
12507 + if (pprefix == NULL)
12510 + if (strlen(pprefix) == prefix->length &&
12511 + memcmp(pprefix, prefix->value, prefix->length) == 0)
12515 + return ATTR_TYPE_LOCAL;
12519 + * Convert a type to an attribute prefix
12522 +gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type) const
12524 + gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
12526 + if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_MAX)
12529 + if (!providerEnabled(type))
12532 + prefix.value = (void *)m_providers[type]->prefix();
12533 + if (prefix.value != NULL)
12534 + prefix.length = strlen((char *)prefix.value);
12540 +gss_eap_attr_ctx::providerEnabled(unsigned int type) const
12542 + if (type == ATTR_TYPE_LOCAL &&
12543 + (m_flags & ATTR_FLAG_DISABLE_LOCAL))
12546 + if (m_providers[type] == NULL)
12553 +gss_eap_attr_ctx::releaseProvider(unsigned int type)
12555 + delete m_providers[type];
12556 + m_providers[type] = NULL;
12560 + * Initialize a context from an existing context.
12563 +gss_eap_attr_ctx::initWithExistingContext(const gss_eap_attr_ctx *manager)
12567 + m_flags = manager->m_flags;
12569 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12570 + gss_eap_attr_provider *provider;
12572 + if (!providerEnabled(i)) {
12573 + releaseProvider(i);
12577 + provider = m_providers[i];
12579 + ret = provider->initWithExistingContext(this,
12580 + manager->m_providers[i]);
12581 + if (ret == false) {
12582 + releaseProvider(i);
12591 + * Initialize a context from a GSS credential and context.
12594 +gss_eap_attr_ctx::initWithGssContext(const gss_cred_id_t cred,
12595 + const gss_ctx_id_t ctx)
12599 + if (cred != GSS_C_NO_CREDENTIAL &&
12600 + (cred->flags & GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG)) {
12601 + m_flags |= ATTR_FLAG_DISABLE_LOCAL;
12604 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12605 + gss_eap_attr_provider *provider;
12607 + if (!providerEnabled(i)) {
12608 + releaseProvider(i);
12612 + provider = m_providers[i];
12614 + ret = provider->initWithGssContext(this, cred, ctx);
12615 + if (ret == false) {
12616 + releaseProvider(i);
12625 +gss_eap_attr_ctx::initWithJsonObject(JSONObject &obj)
12627 + bool ret = false;
12628 + bool foundSource[ATTR_TYPE_MAX + 1];
12629 + unsigned int type;
12631 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++)
12632 + foundSource[type] = false;
12634 + if (obj["version"].integer() != 1)
12637 + m_flags = obj["flags"].integer();
12639 + JSONObject sources = obj["sources"];
12641 + /* Initialize providers from serialized state */
12642 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
12643 + gss_eap_attr_provider *provider;
12646 + if (!providerEnabled(type)) {
12647 + releaseProvider(type);
12651 + provider = m_providers[type];
12652 + key = provider->name();
12656 + JSONObject source = sources.get(key);
12657 + if (!source.isNull() &&
12658 + !provider->initWithJsonObject(this, source)) {
12659 + releaseProvider(type);
12663 + foundSource[type] = true;
12666 + /* Initialize remaining providers from initialized providers */
12667 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
12668 + gss_eap_attr_provider *provider;
12670 + if (foundSource[type] || !providerEnabled(type))
12673 + provider = m_providers[type];
12675 + ret = provider->initWithGssContext(this,
12676 + GSS_C_NO_CREDENTIAL,
12677 + GSS_C_NO_CONTEXT);
12678 + if (ret == false) {
12679 + releaseProvider(type);
12688 +gss_eap_attr_ctx::jsonRepresentation(void) const
12690 + JSONObject obj, sources;
12693 + obj.set("version", 1);
12694 + obj.set("flags", m_flags);
12696 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12697 + gss_eap_attr_provider *provider;
12700 + provider = m_providers[i];
12701 + if (provider == NULL)
12702 + continue; /* provider not initialised */
12704 + key = provider->name();
12706 + continue; /* provider does not have state */
12708 + JSONObject source = provider->jsonRepresentation();
12709 + sources.set(key, source);
12712 + obj.set("sources", sources);
12718 + * Initialize a context from an exported context or name token
12721 +gss_eap_attr_ctx::initWithBuffer(const gss_buffer_t buffer)
12723 + OM_uint32 major, minor;
12726 + json_error_t error;
12728 + major = bufferToString(&minor, buffer, &s);
12729 + if (GSS_ERROR(major))
12732 + JSONObject obj = JSONObject::load(s, 0, &error);
12733 + if (!obj.isNull()) {
12734 + ret = initWithJsonObject(obj);
12743 +gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
12745 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++)
12746 + delete m_providers[i];
12750 + * Locate provider for a given type
12752 +gss_eap_attr_provider *
12753 +gss_eap_attr_ctx::getProvider(unsigned int type) const
12755 + GSSEAP_ASSERT(type >= ATTR_TYPE_MIN && type <= ATTR_TYPE_MAX);
12756 + return m_providers[type];
12760 + * Get primary provider. Only the primary provider is serialised when
12761 + * gss_export_sec_context() or gss_export_name_composite() is called.
12763 +gss_eap_attr_provider *
12764 +gss_eap_attr_ctx::getPrimaryProvider(void) const
12766 + return m_providers[ATTR_TYPE_MIN];
12770 + * Set an attribute
12773 +gss_eap_attr_ctx::setAttribute(int complete,
12774 + const gss_buffer_t attr,
12775 + const gss_buffer_t value)
12777 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12778 + unsigned int type;
12779 + gss_eap_attr_provider *provider;
12780 + bool ret = false;
12782 + decomposeAttributeName(attr, &type, &suffix);
12784 + provider = m_providers[type];
12785 + if (provider != NULL) {
12786 + ret = provider->setAttribute(complete,
12787 + (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
12795 + * Delete an attrbiute
12798 +gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
12800 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12801 + unsigned int type;
12802 + gss_eap_attr_provider *provider;
12803 + bool ret = false;
12805 + decomposeAttributeName(attr, &type, &suffix);
12807 + provider = m_providers[type];
12808 + if (provider != NULL) {
12809 + ret = provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
12816 + * Enumerate attribute types with callback
12819 +gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
12821 + bool ret = false;
12824 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12825 + gss_eap_attr_provider *provider = m_providers[i];
12827 + if (provider == NULL)
12830 + ret = provider->getAttributeTypes(cb, data);
12831 + if (ret == false)
12838 +struct eap_gss_get_attr_types_args {
12839 + unsigned int type;
12840 + gss_buffer_set_t attrs;
12844 +addAttribute(const gss_eap_attr_ctx *manager,
12845 + const gss_eap_attr_provider *provider GSSEAP_UNUSED,
12846 + const gss_buffer_t attribute,
12849 + eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
12850 + gss_buffer_desc qualified;
12851 + OM_uint32 major, minor;
12853 + if (args->type != ATTR_TYPE_LOCAL) {
12854 + manager->composeAttributeName(args->type, attribute, &qualified);
12855 + major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
12856 + gss_release_buffer(&minor, &qualified);
12858 + major = gss_add_buffer_set_member(&minor, attribute, &args->attrs);
12861 + return GSS_ERROR(major) == false;
12865 + * Enumerate attribute types, output is buffer set
12868 +gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
12870 + eap_gss_get_attr_types_args args;
12871 + OM_uint32 major, minor;
12872 + bool ret = false;
12875 + major = gss_create_empty_buffer_set(&minor, attrs);
12876 + if (GSS_ERROR(major))
12877 + throw std::bad_alloc();
12879 + args.attrs = *attrs;
12881 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12882 + gss_eap_attr_provider *provider = m_providers[i];
12886 + if (provider == NULL)
12889 + ret = provider->getAttributeTypes(addAttribute, (void *)&args);
12890 + if (ret == false)
12894 + if (ret == false)
12895 + gss_release_buffer_set(&minor, attrs);
12901 + * Get attribute with given name
12904 +gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
12905 + int *authenticated,
12907 + gss_buffer_t value,
12908 + gss_buffer_t display_value,
12911 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12912 + unsigned int type;
12913 + gss_eap_attr_provider *provider;
12916 + decomposeAttributeName(attr, &type, &suffix);
12918 + provider = m_providers[type];
12919 + if (provider == NULL)
12922 + ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
12923 + authenticated, complete,
12924 + value, display_value, more);
12930 + * Map attribute context to C++ object
12933 +gss_eap_attr_ctx::mapToAny(int authenticated,
12934 + gss_buffer_t type_id) const
12936 + unsigned int type;
12937 + gss_eap_attr_provider *provider;
12938 + gss_buffer_desc suffix;
12940 + decomposeAttributeName(type_id, &type, &suffix);
12942 + provider = m_providers[type];
12943 + if (provider == NULL)
12944 + return (gss_any_t)NULL;
12946 + return provider->mapToAny(authenticated, &suffix);
12950 + * Release mapped context
12953 +gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
12954 + gss_any_t input) const
12956 + unsigned int type;
12957 + gss_eap_attr_provider *provider;
12958 + gss_buffer_desc suffix;
12960 + decomposeAttributeName(type_id, &type, &suffix);
12962 + provider = m_providers[type];
12963 + if (provider != NULL)
12964 + provider->releaseAnyNameMapping(&suffix, input);
12968 + * Export attribute context to buffer
12971 +gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
12976 + JSONObject obj = jsonRepresentation();
12979 + obj.dump(stdout);
12982 + s = obj.dump(JSON_COMPACT);
12984 + if (GSS_ERROR(makeStringBuffer(&minor, s, buffer)))
12985 + throw std::bad_alloc();
12989 + * Return soonest expiry time of providers
12992 +gss_eap_attr_ctx::getExpiryTime(void) const
12995 + time_t expiryTime = 0;
12997 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12998 + gss_eap_attr_provider *provider = m_providers[i];
12999 + time_t providerExpiryTime;
13001 + if (provider == NULL)
13004 + providerExpiryTime = provider->getExpiryTime();
13005 + if (providerExpiryTime == 0)
13008 + if (expiryTime == 0 || providerExpiryTime < expiryTime)
13009 + expiryTime = providerExpiryTime;
13012 + return expiryTime;
13016 +gss_eap_attr_ctx::mapException(OM_uint32 *minor, std::exception &e) const
13021 + /* Errors we handle ourselves */
13022 + if (typeid(e) == typeid(std::bad_alloc)) {
13023 + major = GSS_S_FAILURE;
13026 + } else if (typeid(e) == typeid(JSONException)) {
13027 + major = GSS_S_BAD_NAME;
13028 + *minor = GSSEAP_BAD_ATTR_TOKEN;
13029 + gssEapSaveStatusInfo(*minor, "%s", e.what());
13033 + /* Errors we delegate to providers */
13034 + major = GSS_S_CONTINUE_NEEDED;
13036 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
13037 + gss_eap_attr_provider *provider = m_providers[i];
13039 + if (provider == NULL)
13042 + major = provider->mapException(minor, e);
13043 + if (major != GSS_S_CONTINUE_NEEDED)
13047 + if (major == GSS_S_CONTINUE_NEEDED) {
13048 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13049 + major = GSS_S_FAILURE;
13053 + GSSEAP_ASSERT(GSS_ERROR(major));
13059 + * Decompose attribute name into prefix and suffix
13062 +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
13063 + gss_buffer_t prefix,
13064 + gss_buffer_t suffix)
13069 + for (i = 0; i < attribute->length; i++) {
13070 + if (((char *)attribute->value)[i] == ' ') {
13071 + p = (char *)attribute->value + i + 1;
13076 + prefix->value = attribute->value;
13077 + prefix->length = i;
13079 + if (p != NULL && *p != '\0') {
13080 + suffix->length = attribute->length - 1 - prefix->length;
13081 + suffix->value = p;
13083 + suffix->length = 0;
13084 + suffix->value = NULL;
13089 + * Decompose attribute name into type and suffix
13092 +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
13093 + unsigned int *type,
13094 + gss_buffer_t suffix) const
13096 + gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
13098 + decomposeAttributeName(attribute, &prefix, suffix);
13099 + *type = attributePrefixToType(&prefix);
13103 + * Compose attribute name from prefix, suffix; returns C++ string
13106 +gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
13107 + const gss_buffer_t suffix)
13111 + if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
13114 + str.append((const char *)prefix->value, prefix->length);
13116 + if (suffix != GSS_C_NO_BUFFER) {
13118 + str.append((const char *)suffix->value, suffix->length);
13125 + * Compose attribute name from type, suffix; returns C++ string
13128 +gss_eap_attr_ctx::composeAttributeName(unsigned int type,
13129 + const gss_buffer_t suffix)
13131 + gss_buffer_desc prefix = attributeTypeToPrefix(type);
13133 + return composeAttributeName(&prefix, suffix);
13137 + * Compose attribute name from prefix, suffix; returns GSS buffer
13140 +gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
13141 + const gss_buffer_t suffix,
13142 + gss_buffer_t attribute)
13144 + std::string str = composeAttributeName(prefix, suffix);
13146 + if (str.length() != 0) {
13147 + return duplicateBuffer(str, attribute);
13149 + attribute->length = 0;
13150 + attribute->value = NULL;
13155 + * Compose attribute name from type, suffix; returns GSS buffer
13158 +gss_eap_attr_ctx::composeAttributeName(unsigned int type,
13159 + const gss_buffer_t suffix,
13160 + gss_buffer_t attribute) const
13162 + gss_buffer_desc prefix = attributeTypeToPrefix(type);
13164 + return composeAttributeName(&prefix, suffix, attribute);
13171 +gssEapInquireName(OM_uint32 *minor,
13174 + gss_OID *MN_mech,
13175 + gss_buffer_set_t *attrs)
13179 + if (name_is_MN != NULL)
13180 + *name_is_MN = (name->mechanismUsed != GSS_C_NULL_OID);
13182 + if (MN_mech != NULL) {
13183 + major = gssEapCanonicalizeOid(minor, name->mechanismUsed,
13184 + OID_FLAG_NULL_VALID, MN_mech);
13185 + if (GSS_ERROR(major))
13189 + if (name->attrCtx == NULL) {
13190 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13191 + return GSS_S_UNAVAILABLE;
13194 + if (GSS_ERROR(gssEapAttrProvidersInit(minor))) {
13195 + return GSS_S_UNAVAILABLE;
13199 + if (!name->attrCtx->getAttributeTypes(attrs)) {
13200 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13201 + return GSS_S_UNAVAILABLE;
13203 + } catch (std::exception &e) {
13204 + return name->attrCtx->mapException(minor, e);
13207 + return GSS_S_COMPLETE;
13211 +gssEapGetNameAttribute(OM_uint32 *minor,
13213 + gss_buffer_t attr,
13214 + int *authenticated,
13216 + gss_buffer_t value,
13217 + gss_buffer_t display_value,
13220 + if (authenticated != NULL)
13221 + *authenticated = 0;
13222 + if (complete != NULL)
13225 + if (value != NULL) {
13226 + value->length = 0;
13227 + value->value = NULL;
13230 + if (display_value != NULL) {
13231 + display_value->length = 0;
13232 + display_value->value = NULL;
13235 + if (name->attrCtx == NULL) {
13236 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13237 + return GSS_S_UNAVAILABLE;
13240 + if (GSS_ERROR(gssEapAttrProvidersInit(minor))) {
13241 + return GSS_S_UNAVAILABLE;
13245 + if (!name->attrCtx->getAttribute(attr, authenticated, complete,
13246 + value, display_value, more)) {
13247 + *minor = GSSEAP_NO_SUCH_ATTR;
13248 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13249 + (int)attr->length, (char *)attr->value);
13250 + return GSS_S_UNAVAILABLE;
13252 + } catch (std::exception &e) {
13253 + return name->attrCtx->mapException(minor, e);
13256 + return GSS_S_COMPLETE;
13260 +gssEapDeleteNameAttribute(OM_uint32 *minor,
13262 + gss_buffer_t attr)
13264 + if (name->attrCtx == NULL) {
13265 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13266 + return GSS_S_UNAVAILABLE;
13269 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13270 + return GSS_S_UNAVAILABLE;
13273 + if (!name->attrCtx->deleteAttribute(attr)) {
13274 + *minor = GSSEAP_NO_SUCH_ATTR;
13275 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13276 + (int)attr->length, (char *)attr->value);
13277 + return GSS_S_UNAVAILABLE;
13279 + } catch (std::exception &e) {
13280 + return name->attrCtx->mapException(minor, e);
13283 + return GSS_S_COMPLETE;
13287 +gssEapSetNameAttribute(OM_uint32 *minor,
13290 + gss_buffer_t attr,
13291 + gss_buffer_t value)
13293 + if (name->attrCtx == NULL) {
13294 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13295 + return GSS_S_UNAVAILABLE;
13298 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13299 + return GSS_S_UNAVAILABLE;
13302 + if (!name->attrCtx->setAttribute(complete, attr, value)) {
13303 + *minor = GSSEAP_NO_SUCH_ATTR;
13304 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13305 + (int)attr->length, (char *)attr->value);
13306 + return GSS_S_UNAVAILABLE;
13308 + } catch (std::exception &e) {
13309 + return name->attrCtx->mapException(minor, e);
13312 + return GSS_S_COMPLETE;
13316 +gssEapExportAttrContext(OM_uint32 *minor,
13318 + gss_buffer_t buffer)
13320 + if (name->attrCtx == NULL) {
13321 + buffer->length = 0;
13322 + buffer->value = NULL;
13324 + return GSS_S_COMPLETE;
13327 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13328 + return GSS_S_UNAVAILABLE;
13331 + name->attrCtx->exportToBuffer(buffer);
13332 + } catch (std::exception &e) {
13333 + return name->attrCtx->mapException(minor, e);
13336 + return GSS_S_COMPLETE;
13340 +gssEapImportAttrContext(OM_uint32 *minor,
13341 + gss_buffer_t buffer,
13344 + gss_eap_attr_ctx *ctx = NULL;
13345 + OM_uint32 major = GSS_S_FAILURE;
13347 + GSSEAP_ASSERT(name->attrCtx == NULL);
13349 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13350 + return GSS_S_UNAVAILABLE;
13352 + if (buffer->length == 0)
13353 + return GSS_S_COMPLETE;
13356 + ctx = new gss_eap_attr_ctx();
13358 + if (ctx->initWithBuffer(buffer)) {
13359 + name->attrCtx = ctx;
13360 + major = GSS_S_COMPLETE;
13363 + major = GSS_S_BAD_NAME;
13364 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13366 + } catch (std::exception &e) {
13368 + major = ctx->mapException(minor, e);
13371 + GSSEAP_ASSERT(major == GSS_S_COMPLETE || name->attrCtx == NULL);
13373 + if (GSS_ERROR(major))
13380 +gssEapDuplicateAttrContext(OM_uint32 *minor,
13384 + gss_eap_attr_ctx *ctx = NULL;
13385 + OM_uint32 major = GSS_S_FAILURE;
13387 + GSSEAP_ASSERT(out->attrCtx == NULL);
13389 + if (in->attrCtx == NULL) {
13391 + return GSS_S_COMPLETE;
13394 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13395 + return GSS_S_UNAVAILABLE;
13398 + ctx = new gss_eap_attr_ctx();
13400 + if (ctx->initWithExistingContext(in->attrCtx)) {
13401 + out->attrCtx = ctx;
13402 + major = GSS_S_COMPLETE;
13405 + major = GSS_S_FAILURE;
13406 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13408 + } catch (std::exception &e) {
13409 + major = in->attrCtx->mapException(minor, e);
13412 + GSSEAP_ASSERT(major == GSS_S_COMPLETE || out->attrCtx == NULL);
13414 + if (GSS_ERROR(major))
13417 + return GSS_S_COMPLETE;
13421 +gssEapMapNameToAny(OM_uint32 *minor,
13423 + int authenticated,
13424 + gss_buffer_t type_id,
13425 + gss_any_t *output)
13427 + if (name->attrCtx == NULL) {
13428 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13429 + return GSS_S_UNAVAILABLE;
13432 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13433 + return GSS_S_UNAVAILABLE;
13436 + *output = name->attrCtx->mapToAny(authenticated, type_id);
13437 + } catch (std::exception &e) {
13438 + return name->attrCtx->mapException(minor, e);
13441 + return GSS_S_COMPLETE;
13445 +gssEapReleaseAnyNameMapping(OM_uint32 *minor,
13447 + gss_buffer_t type_id,
13448 + gss_any_t *input)
13450 + if (name->attrCtx == NULL) {
13451 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13452 + return GSS_S_UNAVAILABLE;
13455 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13456 + return GSS_S_UNAVAILABLE;
13459 + if (*input != NULL)
13460 + name->attrCtx->releaseAnyNameMapping(type_id, *input);
13462 + } catch (std::exception &e) {
13463 + return name->attrCtx->mapException(minor, e);
13466 + return GSS_S_COMPLETE;
13470 +gssEapReleaseAttrContext(OM_uint32 *minor,
13473 + if (name->attrCtx != NULL)
13474 + delete name->attrCtx;
13477 + return GSS_S_COMPLETE;
13481 + * Public accessor for initialisng a context from a GSS context. Also
13482 + * sets expiry time on GSS context as a side-effect.
13485 +gssEapCreateAttrContext(OM_uint32 *minor,
13486 + gss_cred_id_t gssCred,
13487 + gss_ctx_id_t gssCtx,
13488 + struct gss_eap_attr_ctx **pAttrContext,
13489 + time_t *pExpiryTime)
13491 + gss_eap_attr_ctx *ctx = NULL;
13494 + GSSEAP_ASSERT(gssCtx != GSS_C_NO_CONTEXT);
13496 + *pAttrContext = NULL;
13498 + major = gssEapAttrProvidersInit(minor);
13499 + if (GSS_ERROR(major))
13503 + /* Set *pAttrContext here to for reentrancy */
13504 + *pAttrContext = ctx = new gss_eap_attr_ctx();
13506 + if (ctx->initWithGssContext(gssCred, gssCtx)) {
13507 + *pExpiryTime = ctx->getExpiryTime();
13508 + major = GSS_S_COMPLETE;
13511 + major = GSS_S_FAILURE;
13512 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13514 + } catch (std::exception &e) {
13516 + major = ctx->mapException(minor, e);
13519 + if (GSS_ERROR(major)) {
13521 + *pAttrContext = NULL;
13526 diff --git a/mech_eap/util_attr.h b/mech_eap/util_attr.h
13527 new file mode 100644
13528 index 0000000..2af0850
13530 +++ b/mech_eap/util_attr.h
13533 + * Copyright (c) 2011, JANET(UK)
13534 + * All rights reserved.
13536 + * Redistribution and use in source and binary forms, with or without
13537 + * modification, are permitted provided that the following conditions
13540 + * 1. Redistributions of source code must retain the above copyright
13541 + * notice, this list of conditions and the following disclaimer.
13543 + * 2. Redistributions in binary form must reproduce the above copyright
13544 + * notice, this list of conditions and the following disclaimer in the
13545 + * documentation and/or other materials provided with the distribution.
13547 + * 3. Neither the name of JANET(UK) nor the names of its contributors
13548 + * may be used to endorse or promote products derived from this software
13549 + * without specific prior written permission.
13551 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13552 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13553 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13554 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
13555 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13556 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13557 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13558 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13559 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13560 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13565 + * Attribute provider interface.
13568 +#ifndef _UTIL_ATTR_H_
13569 +#define _UTIL_ATTR_H_ 1
13571 +#ifdef __cplusplus
13575 +using namespace gss_eap_util;
13577 +struct gss_eap_attr_provider;
13578 +struct gss_eap_attr_ctx;
13581 +(*gss_eap_attr_enumeration_cb)(const gss_eap_attr_ctx *ctx,
13582 + const gss_eap_attr_provider *source,
13583 + const gss_buffer_t attribute,
13586 +#define ATTR_TYPE_RADIUS 0U /* RADIUS AVPs */
13587 +#ifdef HAVE_OPENSAML
13588 +#define ATTR_TYPE_SAML_ASSERTION 1U /* SAML assertion */
13589 +#define ATTR_TYPE_SAML 2U /* SAML attributes */
13591 +#define ATTR_TYPE_LOCAL 3U /* Local attributes */
13592 +#define ATTR_TYPE_MIN ATTR_TYPE_RADIUS
13593 +#define ATTR_TYPE_MAX ATTR_TYPE_LOCAL
13595 +#define ATTR_FLAG_DISABLE_LOCAL 0x00000001
13598 + * Attribute provider: this represents a source of attributes derived
13599 + * from the security context.
13601 +struct gss_eap_attr_provider
13604 + gss_eap_attr_provider(void) {}
13605 + virtual ~gss_eap_attr_provider(void) {}
13607 + bool initWithManager(const gss_eap_attr_ctx *manager)
13609 + m_manager = manager;
13613 + virtual bool initWithExistingContext(const gss_eap_attr_ctx *manager,
13614 + const gss_eap_attr_provider *ctx GSSEAP_UNUSED)
13616 + return initWithManager(manager);
13619 + virtual bool initWithGssContext(const gss_eap_attr_ctx *manager,
13620 + const gss_cred_id_t cred GSSEAP_UNUSED,
13621 + const gss_ctx_id_t ctx GSSEAP_UNUSED)
13623 + return initWithManager(manager);
13626 + virtual bool getAttributeTypes(gss_eap_attr_enumeration_cb GSSEAP_UNUSED,
13627 + void *data GSSEAP_UNUSED) const
13632 + virtual bool setAttribute(int complete GSSEAP_UNUSED,
13633 + const gss_buffer_t attr GSSEAP_UNUSED,
13634 + const gss_buffer_t value GSSEAP_UNUSED)
13639 + virtual bool deleteAttribute(const gss_buffer_t value GSSEAP_UNUSED)
13644 + virtual bool getAttribute(const gss_buffer_t attr GSSEAP_UNUSED,
13645 + int *authenticated GSSEAP_UNUSED,
13646 + int *complete GSSEAP_UNUSED,
13647 + gss_buffer_t value GSSEAP_UNUSED,
13648 + gss_buffer_t display_value GSSEAP_UNUSED,
13649 + int *more GSSEAP_UNUSED) const
13654 + virtual gss_any_t mapToAny(int authenticated GSSEAP_UNUSED,
13655 + gss_buffer_t type_id GSSEAP_UNUSED) const
13660 + virtual void releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
13661 + gss_any_t input GSSEAP_UNUSED) const
13665 + /* prefix to be prepended to attributes emitted by gss_get_name_attribute */
13666 + virtual const char *prefix(void) const
13671 + /* optional key for storing JSON dictionary */
13672 + virtual const char *name(void) const
13677 + virtual bool initWithJsonObject(const gss_eap_attr_ctx *manager,
13678 + JSONObject &object GSSEAP_UNUSED)
13680 + return initWithManager(manager);
13684 + virtual JSONObject jsonRepresentation(void) const
13686 + return JSONObject::null();
13689 + virtual time_t getExpiryTime(void) const { return 0; }
13691 + virtual OM_uint32 mapException(OM_uint32 *minor GSSEAP_UNUSED,
13692 + std::exception &e GSSEAP_UNUSED) const
13694 + return GSS_S_CONTINUE_NEEDED;
13697 + static bool init(void) { return true; }
13698 + static void finalize(void) {}
13700 + static gss_eap_attr_provider *createAttrContext(void) { return NULL; }
13703 + const gss_eap_attr_ctx *m_manager;
13706 + /* make non-copyable */
13707 + gss_eap_attr_provider(const gss_eap_attr_provider&);
13708 + gss_eap_attr_provider& operator=(const gss_eap_attr_provider&);
13711 +typedef gss_eap_attr_provider *(*gss_eap_attr_create_provider)(void);
13714 + * Attribute context: this manages a set of providers for a given
13715 + * security context.
13717 +struct gss_eap_attr_ctx
13720 + gss_eap_attr_ctx(void);
13721 + ~gss_eap_attr_ctx(void);
13723 + bool initWithExistingContext(const gss_eap_attr_ctx *manager);
13724 + bool initWithGssContext(const gss_cred_id_t cred,
13725 + const gss_ctx_id_t ctx);
13727 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
13728 + bool getAttributeTypes(gss_buffer_set_t *attrs);
13730 + bool setAttribute(int complete,
13731 + const gss_buffer_t attr,
13732 + const gss_buffer_t value);
13733 + bool deleteAttribute(const gss_buffer_t value);
13734 + bool getAttribute(const gss_buffer_t attr,
13735 + int *authenticated,
13737 + gss_buffer_t value,
13738 + gss_buffer_t display_value,
13739 + int *more) const;
13740 + gss_any_t mapToAny(int authenticated,
13741 + gss_buffer_t type_id) const;
13742 + void releaseAnyNameMapping(gss_buffer_t type_id,
13743 + gss_any_t input) const;
13745 + void exportToBuffer(gss_buffer_t buffer) const;
13746 + bool initWithBuffer(const gss_buffer_t buffer);
13748 + static std::string
13749 + composeAttributeName(const gss_buffer_t prefix,
13750 + const gss_buffer_t suffix);
13752 + decomposeAttributeName(const gss_buffer_t attribute,
13753 + gss_buffer_t prefix,
13754 + gss_buffer_t suffix);
13756 + composeAttributeName(const gss_buffer_t prefix,
13757 + const gss_buffer_t suffix,
13758 + gss_buffer_t attribute);
13761 + composeAttributeName(unsigned int type,
13762 + const gss_buffer_t suffix);
13764 + decomposeAttributeName(const gss_buffer_t attribute,
13765 + unsigned int *type,
13766 + gss_buffer_t suffix) const;
13768 + composeAttributeName(unsigned int type,
13769 + const gss_buffer_t suffix,
13770 + gss_buffer_t attribute) const;
13772 + gss_eap_attr_provider *getProvider(unsigned int type) const;
13775 + registerProvider(unsigned int type,
13776 + gss_eap_attr_create_provider factory);
13778 + unregisterProvider(unsigned int type);
13780 + time_t getExpiryTime(void) const;
13781 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
13784 + bool providerEnabled(unsigned int type) const;
13785 + void releaseProvider(unsigned int type);
13787 + unsigned int attributePrefixToType(const gss_buffer_t prefix) const;
13788 + gss_buffer_desc attributeTypeToPrefix(unsigned int type) const;
13790 + bool initWithJsonObject(JSONObject &object);
13791 + JSONObject jsonRepresentation(void) const;
13793 + gss_eap_attr_provider *getPrimaryProvider(void) const;
13795 + /* make non-copyable */
13796 + gss_eap_attr_ctx(const gss_eap_attr_ctx&);
13797 + gss_eap_attr_ctx& operator=(const gss_eap_attr_ctx&);
13799 + uint32_t m_flags;
13800 + gss_eap_attr_provider *m_providers[ATTR_TYPE_MAX + 1];
13803 +#endif /* __cplusplus */
13805 +#include "util_radius.h"
13806 +#include "util_saml.h"
13807 +#include "util_shib.h"
13809 +#ifdef __cplusplus
13811 +static inline void
13812 +duplicateBuffer(gss_buffer_desc &src, gss_buffer_t dst)
13816 + if (GSS_ERROR(duplicateBuffer(&minor, &src, dst)))
13817 + throw std::bad_alloc();
13820 +static inline void
13821 +duplicateBuffer(std::string &str, gss_buffer_t buffer)
13823 + gss_buffer_desc tmp;
13825 + tmp.length = str.length();
13826 + tmp.value = (char *)str.c_str();
13828 + duplicateBuffer(tmp, buffer);
13832 +struct gss_eap_attr_ctx;
13835 +#ifdef __cplusplus
13840 + * C wrappers for attribute context functions. These match their
13841 + * GSS naming extension equivalents. The caller is required to
13842 + * obtain the name mutex.
13846 +gssEapCreateAttrContext(OM_uint32 *minor,
13847 + gss_cred_id_t acceptorCred,
13848 + gss_ctx_id_t acceptorCtx,
13849 + struct gss_eap_attr_ctx **pAttrCtx,
13850 + time_t *pExpiryTime);
13853 +gssEapInquireName(OM_uint32 *minor,
13856 + gss_OID *MN_mech,
13857 + gss_buffer_set_t *attrs);
13860 +gssEapGetNameAttribute(OM_uint32 *minor,
13862 + gss_buffer_t attr,
13863 + int *authenticated,
13865 + gss_buffer_t value,
13866 + gss_buffer_t display_value,
13870 +gssEapDeleteNameAttribute(OM_uint32 *minor,
13872 + gss_buffer_t attr);
13875 +gssEapSetNameAttribute(OM_uint32 *minor,
13878 + gss_buffer_t attr,
13879 + gss_buffer_t value);
13882 +gssEapExportAttrContext(OM_uint32 *minor,
13884 + gss_buffer_t buffer);
13887 +gssEapImportAttrContext(OM_uint32 *minor,
13888 + gss_buffer_t buffer,
13889 + gss_name_t name);
13892 +gssEapDuplicateAttrContext(OM_uint32 *minor,
13897 +gssEapMapNameToAny(OM_uint32 *minor,
13899 + int authenticated,
13900 + gss_buffer_t type_id,
13901 + gss_any_t *output);
13904 +gssEapReleaseAnyNameMapping(OM_uint32 *minor,
13906 + gss_buffer_t type_id,
13907 + gss_any_t *input);
13910 +gssEapReleaseAttrContext(OM_uint32 *minor,
13911 + gss_name_t name);
13914 +gssEapAttrProvidersFinalize(OM_uint32 *minor);
13916 +#ifdef __cplusplus
13920 +#endif /* _UTIL_ATTR_H_ */
13921 diff --git a/mech_eap/util_base64.c b/mech_eap/util_base64.c
13922 new file mode 100644
13923 index 0000000..aaa1ea8
13925 +++ b/mech_eap/util_base64.c
13928 + * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
13929 + * (Royal Institute of Technology, Stockholm, Sweden).
13930 + * All rights reserved.
13932 + * Redistribution and use in source and binary forms, with or without
13933 + * modification, are permitted provided that the following conditions
13936 + * 1. Redistributions of source code must retain the above copyright
13937 + * notice, this list of conditions and the following disclaimer.
13939 + * 2. Redistributions in binary form must reproduce the above copyright
13940 + * notice, this list of conditions and the following disclaimer in the
13941 + * documentation and/or other materials provided with the distribution.
13943 + * 3. Neither the name of the Institute nor the names of its contributors
13944 + * may be used to endorse or promote products derived from this software
13945 + * without specific prior written permission.
13947 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
13948 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13949 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13950 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
13951 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13952 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13953 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13954 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13955 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13956 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13960 +#include "gssapiP_eap.h"
13962 +static const char base64_chars[] =
13963 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13969 + for (p = base64_chars; *p; p++)
13971 + return p - base64_chars;
13976 +base64Encode(const void *data, int size, char **str)
13981 + const unsigned char *q;
13983 + if (size > INT_MAX/4 || size < 0) {
13988 + p = s = (char *)GSSEAP_MALLOC(BASE64_EXPAND(size));
13993 + q = (const unsigned char *) data;
13995 + for (i = 0; i < size;) {
14005 + p[0] = base64_chars[(c & 0x00fc0000) >> 18];
14006 + p[1] = base64_chars[(c & 0x0003f000) >> 12];
14007 + p[2] = base64_chars[(c & 0x00000fc0) >> 6];
14008 + p[3] = base64_chars[(c & 0x0000003f) >> 0];
14011 + if (i > size + 1)
14017 + return strlen(s);
14020 +#define DECODE_ERROR 0xffffffff
14022 +static unsigned int
14023 +token_decode(const char *token)
14026 + unsigned int val = 0;
14028 + if (strlen(token) < 4)
14029 + return DECODE_ERROR;
14030 + for (i = 0; i < 4; i++) {
14032 + if (token[i] == '=')
14034 + else if (marker > 0)
14035 + return DECODE_ERROR;
14037 + val += pos(token[i]);
14040 + return DECODE_ERROR;
14041 + return (marker << 24) | val;
14045 +base64Decode(const char *str, void *data)
14048 + unsigned char *q;
14053 + while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
14054 + unsigned int val = token_decode(p);
14055 + unsigned int marker = (val >> 24) & 0xff;
14056 + if (val == DECODE_ERROR)
14058 + *q++ = (val >> 16) & 0xff;
14060 + *q++ = (val >> 8) & 0xff;
14062 + *q++ = val & 0xff;
14067 + return q - (unsigned char *) data;
14071 +base64Valid(const char *str)
14073 + const char *p = str;
14076 + while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
14077 + unsigned int val = token_decode(p);
14078 + if (val == DECODE_ERROR) {
14088 diff --git a/mech_eap/util_base64.h b/mech_eap/util_base64.h
14089 new file mode 100644
14090 index 0000000..d015efe
14092 +++ b/mech_eap/util_base64.h
14095 + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
14096 + * (Royal Institute of Technology, Stockholm, Sweden).
14097 + * All rights reserved.
14099 + * Redistribution and use in source and binary forms, with or without
14100 + * modification, are permitted provided that the following conditions
14103 + * 1. Redistributions of source code must retain the above copyright
14104 + * notice, this list of conditions and the following disclaimer.
14106 + * 2. Redistributions in binary form must reproduce the above copyright
14107 + * notice, this list of conditions and the following disclaimer in the
14108 + * documentation and/or other materials provided with the distribution.
14110 + * 3. Neither the name of the Institute nor the names of its contributors
14111 + * may be used to endorse or promote products derived from this software
14112 + * without specific prior written permission.
14114 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
14115 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14116 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14117 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
14118 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14119 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14120 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14121 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14122 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14123 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14129 +#ifndef _UTIL_BASE64_H_
14130 +#define _UTIL_BASE64_H_
14132 +#ifdef __cplusplus
14137 +base64Encode(const void *, int, char **);
14140 +base64Decode(const char *, void *);
14143 +base64Valid(const char *str);
14145 +#define BASE64_EXPAND(n) (n * 4 / 3 + 4)
14147 +#ifdef __cplusplus
14152 diff --git a/mech_eap/util_buffer.c b/mech_eap/util_buffer.c
14153 new file mode 100644
14154 index 0000000..e135db9
14156 +++ b/mech_eap/util_buffer.c
14159 + * Copyright (c) 2011, JANET(UK)
14160 + * All rights reserved.
14162 + * Redistribution and use in source and binary forms, with or without
14163 + * modification, are permitted provided that the following conditions
14166 + * 1. Redistributions of source code must retain the above copyright
14167 + * notice, this list of conditions and the following disclaimer.
14169 + * 2. Redistributions in binary form must reproduce the above copyright
14170 + * notice, this list of conditions and the following disclaimer in the
14171 + * documentation and/or other materials provided with the distribution.
14173 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14174 + * may be used to endorse or promote products derived from this software
14175 + * without specific prior written permission.
14177 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14178 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14179 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14180 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14181 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14182 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14183 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14184 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14185 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14186 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14191 + * Buffer handling helpers.
14194 +#include "gssapiP_eap.h"
14197 +makeStringBuffer(OM_uint32 *minor,
14198 + const char *string,
14199 + gss_buffer_t buffer)
14201 + size_t len = strlen(string);
14203 + buffer->value = GSSEAP_MALLOC(len + 1);
14204 + if (buffer->value == NULL) {
14206 + return GSS_S_FAILURE;
14208 + memcpy(buffer->value, string, len + 1);
14209 + buffer->length = len;
14212 + return GSS_S_COMPLETE;
14216 +bufferToString(OM_uint32 *minor,
14217 + const gss_buffer_t buffer,
14222 + s = GSSEAP_MALLOC(buffer->length + 1);
14225 + return GSS_S_FAILURE;
14227 + memcpy(s, buffer->value, buffer->length);
14228 + s[buffer->length] = '\0';
14233 + return GSS_S_COMPLETE;
14237 +duplicateBuffer(OM_uint32 *minor,
14238 + const gss_buffer_t src,
14239 + gss_buffer_t dst)
14242 + dst->value = NULL;
14244 + if (src == GSS_C_NO_BUFFER)
14245 + return GSS_S_COMPLETE;
14247 + dst->value = GSSEAP_MALLOC(src->length + 1);
14248 + if (dst->value == NULL) {
14250 + return GSS_S_FAILURE;
14253 + dst->length = src->length;
14254 + memcpy(dst->value, src->value, dst->length);
14256 + ((unsigned char *)dst->value)[dst->length] = '\0';
14259 + return GSS_S_COMPLETE;
14261 diff --git a/mech_eap/util_cksum.c b/mech_eap/util_cksum.c
14262 new file mode 100644
14263 index 0000000..aedc93e
14265 +++ b/mech_eap/util_cksum.c
14268 + * Copyright (c) 2011, JANET(UK)
14269 + * All rights reserved.
14271 + * Redistribution and use in source and binary forms, with or without
14272 + * modification, are permitted provided that the following conditions
14275 + * 1. Redistributions of source code must retain the above copyright
14276 + * notice, this list of conditions and the following disclaimer.
14278 + * 2. Redistributions in binary form must reproduce the above copyright
14279 + * notice, this list of conditions and the following disclaimer in the
14280 + * documentation and/or other materials provided with the distribution.
14282 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14283 + * may be used to endorse or promote products derived from this software
14284 + * without specific prior written permission.
14286 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14287 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14288 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14289 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14290 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14291 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14292 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14293 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14294 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14295 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14299 + * Copyright 1993 by OpenVision Technologies, Inc.
14301 + * Permission to use, copy, modify, distribute, and sell this software
14302 + * and its documentation for any purpose is hereby granted without fee,
14303 + * provided that the above copyright notice appears in all copies and
14304 + * that both that copyright notice and this permission notice appear in
14305 + * supporting documentation, and that the name of OpenVision not be used
14306 + * in advertising or publicity pertaining to distribution of the software
14307 + * without specific, written prior permission. OpenVision makes no
14308 + * representations about the suitability of this software for any
14309 + * purpose. It is provided "as is" without express or implied warranty.
14311 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
14312 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
14313 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
14314 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
14315 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14316 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14317 + * PERFORMANCE OF THIS SOFTWARE.
14321 + * Message protection services: checksum helpers.
14324 +#include "gssapiP_eap.h"
14327 +gssEapChecksum(krb5_context context,
14328 + krb5_cksumtype type,
14330 +#ifdef HAVE_HEIMDAL_VERSION
14331 + krb5_crypto crypto,
14333 + krb5_keyblock *crypto,
14335 + krb5_keyusage sign_usage,
14336 + gss_iov_buffer_desc *iov,
14341 + krb5_error_code code;
14342 + gss_iov_buffer_desc *header;
14343 + gss_iov_buffer_desc *trailer;
14344 + krb5_crypto_iov *kiov;
14345 + size_t kiov_count;
14347 + size_t k5_checksumlen;
14352 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen);
14356 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
14357 + GSSEAP_ASSERT(header != NULL);
14359 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
14360 + GSSEAP_ASSERT(rrc != 0 || trailer != NULL);
14362 + if (trailer == NULL) {
14363 + if (rrc != k5_checksumlen)
14364 + return KRB5_BAD_MSIZE;
14365 + if (header->buffer.length != 16 + k5_checksumlen)
14366 + return KRB5_BAD_MSIZE;
14367 + } else if (trailer->buffer.length != k5_checksumlen)
14368 + return KRB5_BAD_MSIZE;
14370 + kiov_count = 2 + iov_count;
14371 + kiov = (krb5_crypto_iov *)GSSEAP_MALLOC(kiov_count * sizeof(krb5_crypto_iov));
14372 + if (kiov == NULL)
14375 + /* Checksum over ( Data | Header ) */
14378 + for (j = 0; j < iov_count; j++) {
14379 + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
14380 + kiov[i].data.length = iov[j].buffer.length;
14381 + kiov[i].data.data = (char *)iov[j].buffer.value;
14386 + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
14387 + kiov[i].data.length = 16;
14388 + kiov[i].data.data = (char *)header->buffer.value;
14392 + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
14393 + if (trailer == NULL) {
14394 + kiov[i].data.length = header->buffer.length - 16;
14395 + kiov[i].data.data = (char *)header->buffer.value + 16;
14397 + kiov[i].data.length = trailer->buffer.length;
14398 + kiov[i].data.data = (char *)trailer->buffer.value;
14402 +#ifdef HAVE_HEIMDAL_VERSION
14404 + code = krb5_verify_checksum_iov(context, crypto, sign_usage,
14405 + kiov, kiov_count, &type);
14406 + *valid = (code == 0);
14408 + code = krb5_create_checksum_iov(context, crypto, sign_usage,
14409 + kiov, kiov_count, &type);
14413 + krb5_boolean kvalid = FALSE;
14415 + code = krb5_c_verify_checksum_iov(context, type, crypto,
14416 + sign_usage, kiov, kiov_count, &kvalid);
14420 + code = krb5_c_make_checksum_iov(context, type, crypto,
14421 + sign_usage, kiov, kiov_count);
14423 +#endif /* HAVE_HEIMDAL_VERSION */
14425 + GSSEAP_FREE(kiov);
14431 +gssEapSign(krb5_context context,
14432 + krb5_cksumtype type,
14434 +#ifdef HAVE_HEIMDAL_VERSION
14435 + krb5_crypto crypto,
14437 + krb5_keyblock *crypto,
14439 + krb5_keyusage sign_usage,
14440 + gss_iov_buffer_desc *iov,
14443 + return gssEapChecksum(context, type, rrc, crypto,
14444 + sign_usage, iov, iov_count, 0, NULL);
14448 +gssEapVerify(krb5_context context,
14449 + krb5_cksumtype type,
14451 +#ifdef HAVE_HEIMDAL_VERSION
14452 + krb5_crypto crypto,
14454 + krb5_keyblock *crypto,
14456 + krb5_keyusage sign_usage,
14457 + gss_iov_buffer_desc *iov,
14461 + return gssEapChecksum(context, type, rrc, crypto,
14462 + sign_usage, iov, iov_count, 1, valid);
14467 +gssEapEncodeGssChannelBindings(OM_uint32 *minor,
14468 + gss_channel_bindings_t chanBindings,
14469 + gss_buffer_t encodedBindings)
14471 + OM_uint32 major, tmpMinor;
14473 + unsigned char *p;
14475 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS) {
14477 + length += chanBindings->initiator_address.length;
14478 + length += chanBindings->acceptor_address.length;
14479 + length += chanBindings->application_data.length;
14481 + encodedBindings->value = GSSEAP_MALLOC(length);
14482 + if (encodedBindings->value == NULL) {
14484 + return GSS_S_FAILURE;
14487 + encodedBindings->length = length;
14488 + p = (unsigned char *)encodedBindings->value;
14490 + store_uint32_be(chanBindings->initiator_addrtype, p);
14491 + store_buffer(&chanBindings->initiator_address, p + 4, 0);
14492 + p += 4 + chanBindings->initiator_address.length;
14494 + store_uint32_be(chanBindings->acceptor_addrtype, p);
14495 + store_buffer(&chanBindings->acceptor_address, p + 4, 0);
14496 + p += 4 + chanBindings->acceptor_address.length;
14498 + store_buffer(&chanBindings->application_data, p, 1);
14499 + p += chanBindings->application_data.length;
14501 + encodedBindings->length = 0;
14502 + encodedBindings->value = NULL;
14506 + return GSS_S_COMPLETE;
14509 diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c
14510 new file mode 100644
14511 index 0000000..e18edc5
14513 +++ b/mech_eap/util_context.c
14516 + * Copyright (c) 2011, JANET(UK)
14517 + * All rights reserved.
14519 + * Redistribution and use in source and binary forms, with or without
14520 + * modification, are permitted provided that the following conditions
14523 + * 1. Redistributions of source code must retain the above copyright
14524 + * notice, this list of conditions and the following disclaimer.
14526 + * 2. Redistributions in binary form must reproduce the above copyright
14527 + * notice, this list of conditions and the following disclaimer in the
14528 + * documentation and/or other materials provided with the distribution.
14530 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14531 + * may be used to endorse or promote products derived from this software
14532 + * without specific prior written permission.
14534 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14535 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14536 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14537 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14538 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14539 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14540 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14541 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14542 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14543 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14548 + * Utility routines for context handles.
14551 +#include "gssapiP_eap.h"
14554 +gssEapAllocContext(OM_uint32 *minor,
14555 + gss_ctx_id_t *pCtx)
14557 + OM_uint32 tmpMinor;
14558 + gss_ctx_id_t ctx;
14560 + GSSEAP_ASSERT(*pCtx == GSS_C_NO_CONTEXT);
14562 + ctx = (gss_ctx_id_t)GSSEAP_CALLOC(1, sizeof(*ctx));
14563 + if (ctx == NULL) {
14565 + return GSS_S_FAILURE;
14568 + if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
14569 + *minor = GSSEAP_GET_LAST_ERROR();
14570 + gssEapReleaseContext(&tmpMinor, &ctx);
14571 + return GSS_S_FAILURE;
14574 + ctx->state = GSSEAP_STATE_INITIAL;
14575 + ctx->mechanismUsed = GSS_C_NO_OID;
14578 + * Integrity, confidentiality, sequencing and replay detection are
14579 + * always available. Regardless of what flags are requested in
14580 + * GSS_Init_sec_context, implementations MUST set the flag corresponding
14581 + * to these services in the output of GSS_Init_sec_context and
14582 + * GSS_Accept_sec_context.
14584 + ctx->gssFlags = GSS_C_TRANS_FLAG | /* exporting contexts */
14585 + GSS_C_INTEG_FLAG | /* integrity */
14586 + GSS_C_CONF_FLAG | /* confidentiality */
14587 + GSS_C_SEQUENCE_FLAG | /* sequencing */
14588 + GSS_C_REPLAY_FLAG; /* replay detection */
14592 + return GSS_S_COMPLETE;
14596 +releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx)
14598 + eap_peer_sm_deinit(ctx->eap);
14601 +#ifdef GSSEAP_ENABLE_ACCEPTOR
14603 +releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
14605 + OM_uint32 tmpMinor;
14607 + if (ctx->radConn != NULL)
14608 + rs_conn_destroy(ctx->radConn);
14609 + if (ctx->radContext != NULL)
14610 + rs_context_destroy(ctx->radContext);
14611 + if (ctx->radServer != NULL)
14612 + GSSEAP_FREE(ctx->radServer);
14613 + gss_release_buffer(&tmpMinor, &ctx->state);
14614 + if (ctx->vps != NULL)
14615 + gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
14617 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
14620 +gssEapReleaseContext(OM_uint32 *minor,
14621 + gss_ctx_id_t *pCtx)
14623 + OM_uint32 tmpMinor;
14624 + gss_ctx_id_t ctx = *pCtx;
14625 + krb5_context krbContext = NULL;
14627 + if (ctx == GSS_C_NO_CONTEXT) {
14628 + return GSS_S_COMPLETE;
14631 + gssEapKerberosInit(&tmpMinor, &krbContext);
14633 +#ifdef GSSEAP_ENABLE_REAUTH
14634 + if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
14635 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
14637 +#endif /* GSSEAP_ENABLE_REAUTH */
14638 + if (CTX_IS_INITIATOR(ctx)) {
14639 + releaseInitiatorContext(&ctx->initiatorCtx);
14641 +#ifdef GSSEAP_ENABLE_ACCEPTOR
14643 + releaseAcceptorContext(&ctx->acceptorCtx);
14645 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
14647 + krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
14648 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
14649 + gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
14650 + gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
14651 + sequenceFree(&tmpMinor, &ctx->seqState);
14652 + gssEapReleaseCred(&tmpMinor, &ctx->cred);
14654 + GSSEAP_MUTEX_DESTROY(&ctx->mutex);
14656 + memset(ctx, 0, sizeof(*ctx));
14657 + GSSEAP_FREE(ctx);
14658 + *pCtx = GSS_C_NO_CONTEXT;
14661 + return GSS_S_COMPLETE;
14665 +gssEapMakeToken(OM_uint32 *minor,
14666 + gss_ctx_id_t ctx,
14667 + const gss_buffer_t innerToken,
14668 + enum gss_eap_token_type tokenType,
14669 + gss_buffer_t outputToken)
14671 + unsigned char *p;
14673 + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID);
14675 + outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
14676 + outputToken->value = GSSEAP_MALLOC(outputToken->length);
14677 + if (outputToken->value == NULL) {
14679 + return GSS_S_FAILURE;
14682 + p = (unsigned char *)outputToken->value;
14683 + makeTokenHeader(ctx->mechanismUsed, innerToken->length, &p, tokenType);
14684 + memcpy(p, innerToken->value, innerToken->length);
14687 + return GSS_S_COMPLETE;
14691 +gssEapVerifyToken(OM_uint32 *minor,
14692 + gss_ctx_id_t ctx,
14693 + const gss_buffer_t inputToken,
14694 + enum gss_eap_token_type *actualToken,
14695 + gss_buffer_t innerInputToken)
14699 + unsigned char *p = (unsigned char *)inputToken->value;
14700 + gss_OID_desc oidBuf;
14703 + if (ctx->mechanismUsed != GSS_C_NO_OID) {
14704 + oid = ctx->mechanismUsed;
14706 + oidBuf.elements = NULL;
14707 + oidBuf.length = 0;
14711 + major = verifyTokenHeader(minor, oid, &bodySize, &p,
14712 + inputToken->length, actualToken);
14713 + if (GSS_ERROR(major))
14716 + if (ctx->mechanismUsed == GSS_C_NO_OID) {
14717 + major = gssEapCanonicalizeOid(minor, oid, 0, &ctx->mechanismUsed);
14718 + if (GSS_ERROR(major))
14722 + innerInputToken->length = bodySize;
14723 + innerInputToken->value = p;
14726 + return GSS_S_COMPLETE;
14730 +gssEapContextTime(OM_uint32 *minor,
14731 + gss_ctx_id_t context_handle,
14732 + OM_uint32 *time_rec)
14736 + if (context_handle->expiryTime == 0) {
14737 + *time_rec = GSS_C_INDEFINITE;
14739 + time_t now, lifetime;
14742 + lifetime = context_handle->expiryTime - now;
14743 + if (lifetime <= 0) {
14745 + return GSS_S_CONTEXT_EXPIRED;
14747 + *time_rec = lifetime;
14750 + return GSS_S_COMPLETE;
14754 +gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor,
14755 + gss_ctx_id_t ctx,
14756 + gss_buffer_t tokenMIC,
14760 + gss_iov_buffer_desc *iov = NULL;
14762 + enum gss_eap_token_type tokType;
14763 + OM_uint32 micTokType;
14764 + unsigned char wireTokType[2];
14765 + unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL;
14766 + const struct gss_eap_token_buffer_set *tokens;
14768 + tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens;
14770 + GSSEAP_ASSERT(tokens != NULL);
14772 + iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov));
14773 + if (iov == NULL) {
14774 + major = GSS_S_FAILURE;
14779 + innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count);
14780 + if (innerTokTypes == NULL) {
14782 + major = GSS_S_FAILURE;
14786 + innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count);
14787 + if (innerTokLengths == NULL) {
14788 + major = GSS_S_FAILURE;
14793 + /* Mechanism OID */
14794 + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID);
14795 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14796 + iov[i].buffer.length = ctx->mechanismUsed->length;
14797 + iov[i].buffer.value = ctx->mechanismUsed->elements;
14801 + if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) {
14802 + tokType = TOK_TYPE_INITIATOR_CONTEXT;
14803 + micTokType = ITOK_TYPE_INITIATOR_MIC;
14805 + tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
14806 + micTokType = ITOK_TYPE_ACCEPTOR_MIC;
14808 + store_uint16_be(tokType, wireTokType);
14810 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14811 + iov[i].buffer.length = sizeof(wireTokType);
14812 + iov[i].buffer.value = wireTokType;
14815 + for (j = 0; j < tokens->buffers.count; j++) {
14817 + (tokens->types[j] & ITOK_TYPE_MASK) == micTokType)
14818 + continue; /* will use this slot for trailer */
14820 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14821 + iov[i].buffer.length = 4;
14822 + iov[i].buffer.value = &innerTokTypes[j * 4];
14823 + store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED),
14824 + iov[i].buffer.value);
14827 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14828 + iov[i].buffer.length = 4;
14829 + iov[i].buffer.value = &innerTokLengths[j * 4];
14830 + store_uint32_be(tokens->buffers.elements[j].length,
14831 + iov[i].buffer.value);
14834 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14835 + iov[i].buffer = tokens->buffers.elements[j];
14840 + GSSEAP_ASSERT(tokenMIC->length >= 16);
14842 + GSSEAP_ASSERT(i < 2 + (3 * tokens->buffers.count));
14844 + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER;
14845 + iov[i].buffer = *tokenMIC;
14848 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
14849 + iov, i, TOK_TYPE_MIC);
14851 + iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
14852 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
14853 + iov, i, TOK_TYPE_MIC);
14854 + if (!GSS_ERROR(major))
14855 + *tokenMIC = iov[i - 1].buffer;
14860 + gssEapReleaseIov(iov, tokens->buffers.count);
14861 + if (innerTokTypes != NULL)
14862 + GSSEAP_FREE(innerTokTypes);
14863 + if (innerTokLengths != NULL)
14864 + GSSEAP_FREE(innerTokLengths);
14870 +gssEapMakeTokenMIC(OM_uint32 *minor,
14871 + gss_ctx_id_t ctx,
14872 + gss_buffer_t tokenMIC)
14874 + tokenMIC->length = 0;
14875 + tokenMIC->value = NULL;
14877 + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE);
14881 +gssEapVerifyTokenMIC(OM_uint32 *minor,
14882 + gss_ctx_id_t ctx,
14883 + const gss_buffer_t tokenMIC)
14885 + if (tokenMIC->length < 16) {
14886 + *minor = GSSEAP_TOK_TRUNC;
14887 + return GSS_S_BAD_SIG;
14890 + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE);
14892 diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c
14893 new file mode 100644
14894 index 0000000..746bd61
14896 +++ b/mech_eap/util_cred.c
14899 + * Copyright (c) 2011, JANET(UK)
14900 + * All rights reserved.
14902 + * Redistribution and use in source and binary forms, with or without
14903 + * modification, are permitted provided that the following conditions
14906 + * 1. Redistributions of source code must retain the above copyright
14907 + * notice, this list of conditions and the following disclaimer.
14909 + * 2. Redistributions in binary form must reproduce the above copyright
14910 + * notice, this list of conditions and the following disclaimer in the
14911 + * documentation and/or other materials provided with the distribution.
14913 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14914 + * may be used to endorse or promote products derived from this software
14915 + * without specific prior written permission.
14917 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14918 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14919 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14920 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14921 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14922 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14923 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14924 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14925 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14926 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14931 + * Utility routines for credential handles.
14934 +#include "gssapiP_eap.h"
14937 +# include <shlobj.h> /* may need to use ShFolder.h instead */
14938 +# include <stdio.h>
14944 +gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
14946 + OM_uint32 tmpMinor;
14947 + gss_cred_id_t cred;
14949 + *pCred = GSS_C_NO_CREDENTIAL;
14951 + cred = (gss_cred_id_t)GSSEAP_CALLOC(1, sizeof(*cred));
14952 + if (cred == NULL) {
14954 + return GSS_S_FAILURE;
14957 + if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
14958 + *minor = GSSEAP_GET_LAST_ERROR();
14959 + gssEapReleaseCred(&tmpMinor, &cred);
14960 + return GSS_S_FAILURE;
14966 + return GSS_S_COMPLETE;
14970 +zeroAndReleasePassword(gss_buffer_t password)
14972 + if (password->value != NULL) {
14973 + memset(password->value, 0, password->length);
14974 + GSSEAP_FREE(password->value);
14977 + password->value = NULL;
14978 + password->length = 0;
14982 +gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
14984 + OM_uint32 tmpMinor;
14985 + gss_cred_id_t cred = *pCred;
14986 + krb5_context krbContext = NULL;
14988 + if (cred == GSS_C_NO_CREDENTIAL) {
14989 + return GSS_S_COMPLETE;
14992 + GSSEAP_KRB_INIT(&krbContext);
14994 + gssEapReleaseName(&tmpMinor, &cred->name);
14995 + gssEapReleaseName(&tmpMinor, &cred->target);
14997 + zeroAndReleasePassword(&cred->password);
14999 + gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
15000 + gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
15001 + gss_release_buffer(&tmpMinor, &cred->caCertificate);
15002 + gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
15003 + gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
15005 +#ifdef GSSEAP_ENABLE_REAUTH
15006 + if (cred->krbCredCache != NULL) {
15007 + if (cred->flags & CRED_FLAG_DEFAULT_CCACHE)
15008 + krb5_cc_close(krbContext, cred->krbCredCache);
15010 + krb5_cc_destroy(krbContext, cred->krbCredCache);
15012 + if (cred->reauthCred != GSS_C_NO_CREDENTIAL)
15013 + gssReleaseCred(&tmpMinor, &cred->reauthCred);
15016 + GSSEAP_MUTEX_DESTROY(&cred->mutex);
15017 + memset(cred, 0, sizeof(*cred));
15018 + GSSEAP_FREE(cred);
15022 + return GSS_S_COMPLETE;
15026 +readStaticIdentityFile(OM_uint32 *minor,
15027 + gss_buffer_t defaultIdentity,
15028 + gss_buffer_t defaultPassword)
15030 + OM_uint32 major, tmpMinor;
15032 + char buf[BUFSIZ];
15033 + char *ccacheName;
15036 + struct passwd *pw = NULL, pwd;
15037 + char pwbuf[BUFSIZ];
15040 + defaultIdentity->length = 0;
15041 + defaultIdentity->value = NULL;
15043 + if (defaultPassword != GSS_C_NO_BUFFER) {
15044 + defaultPassword->length = 0;
15045 + defaultPassword->value = NULL;
15048 + ccacheName = getenv("GSSEAP_IDENTITY");
15049 + if (ccacheName == NULL) {
15051 + TCHAR szPath[MAX_PATH];
15053 + if (!SUCCEEDED(SHGetFolderPath(NULL,
15054 + CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
15055 + NULL, /* User access token */
15056 + 0, /* SHGFP_TYPE_CURRENT */
15058 + major = GSS_S_CRED_UNAVAIL;
15059 + *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
15063 + snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
15065 + if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
15066 + pw == NULL || pw->pw_dir == NULL) {
15067 + major = GSS_S_CRED_UNAVAIL;
15068 + *minor = GSSEAP_GET_LAST_ERROR();
15072 + snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
15073 +#endif /* WIN32 */
15074 + ccacheName = buf;
15077 + fp = fopen(ccacheName, "r");
15078 + if (fp == NULL) {
15079 + major = GSS_S_CRED_UNAVAIL;
15080 + *minor = GSSEAP_NO_DEFAULT_CRED;
15084 + while (fgets(buf, sizeof(buf), fp) != NULL) {
15085 + gss_buffer_desc src, *dst;
15087 + src.length = strlen(buf);
15090 + if (src.length == 0)
15093 + if (buf[src.length - 1] == '\n') {
15094 + buf[src.length - 1] = '\0';
15095 + if (--src.length == 0)
15100 + dst = defaultIdentity;
15102 + dst = defaultPassword;
15106 + if (dst != GSS_C_NO_BUFFER) {
15107 + major = duplicateBuffer(minor, &src, dst);
15108 + if (GSS_ERROR(major))
15115 + if (defaultIdentity->length == 0) {
15116 + major = GSS_S_CRED_UNAVAIL;
15117 + *minor = GSSEAP_NO_DEFAULT_CRED;
15121 + major = GSS_S_COMPLETE;
15128 + if (GSS_ERROR(major)) {
15129 + gss_release_buffer(&tmpMinor, defaultIdentity);
15130 + zeroAndReleasePassword(defaultPassword);
15133 + memset(buf, 0, sizeof(buf));
15139 +gssEapPrimaryMechForCred(gss_cred_id_t cred)
15141 + gss_OID nameMech = GSS_C_NO_OID;
15143 + if (cred->mechanisms != GSS_C_NO_OID_SET &&
15144 + cred->mechanisms->count == 1)
15145 + nameMech = &cred->mechanisms->elements[0];
15151 +gssEapAcquireCred(OM_uint32 *minor,
15152 + const gss_name_t desiredName,
15153 + OM_uint32 timeReq GSSEAP_UNUSED,
15154 + const gss_OID_set desiredMechs,
15156 + gss_cred_id_t *pCred,
15157 + gss_OID_set *pActualMechs,
15158 + OM_uint32 *timeRec)
15160 + OM_uint32 major, tmpMinor;
15161 + gss_cred_id_t cred;
15163 + /* XXX TODO validate with changed set_cred_option API */
15164 + *pCred = GSS_C_NO_CREDENTIAL;
15166 + major = gssEapAllocCred(minor, &cred);
15167 + if (GSS_ERROR(major))
15170 + switch (credUsage) {
15172 + cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT;
15174 + case GSS_C_INITIATE:
15175 + cred->flags |= CRED_FLAG_INITIATE;
15177 + case GSS_C_ACCEPT:
15178 + cred->flags |= CRED_FLAG_ACCEPT;
15181 + major = GSS_S_FAILURE;
15182 + *minor = GSSEAP_BAD_USAGE;
15187 + major = gssEapValidateMechs(minor, desiredMechs);
15188 + if (GSS_ERROR(major))
15191 + major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
15192 + if (GSS_ERROR(major))
15195 + if (desiredName != GSS_C_NO_NAME) {
15196 + GSSEAP_MUTEX_LOCK(&desiredName->mutex);
15198 + major = gssEapDuplicateName(minor, desiredName, &cred->name);
15199 + if (GSS_ERROR(major)) {
15200 + GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
15204 + GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
15207 +#ifdef GSSEAP_ENABLE_ACCEPTOR
15208 + if (cred->flags & CRED_FLAG_ACCEPT) {
15209 + struct rs_context *radContext;
15211 + major = gssEapCreateRadiusContext(minor, cred, &radContext);
15212 + if (GSS_ERROR(major))
15215 + rs_context_destroy(radContext);
15219 + if (pActualMechs != NULL) {
15220 + major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
15221 + if (GSS_ERROR(major))
15225 + if (timeRec != NULL)
15226 + *timeRec = GSS_C_INDEFINITE;
15230 + major = GSS_S_COMPLETE;
15234 + if (GSS_ERROR(major))
15235 + gssEapReleaseCred(&tmpMinor, &cred);
15241 + * Return TRUE if cred available for mechanism. Caller need no acquire
15242 + * lock because mechanisms list is immutable.
15245 +gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech)
15250 + GSSEAP_ASSERT(mech != GSS_C_NO_OID);
15252 + if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
15255 + gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present);
15261 +staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
15262 + const gss_cred_id_t cred,
15263 + gss_name_t *pName)
15265 + OM_uint32 major, tmpMinor;
15266 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
15267 + gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
15269 + *pName = GSS_C_NO_NAME;
15271 + major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
15272 + if (major == GSS_S_COMPLETE) {
15273 + major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
15274 + nameMech, pName);
15277 + gss_release_buffer(&tmpMinor, &defaultIdentity);
15283 +gssEapResolveCredIdentity(OM_uint32 *minor,
15284 + gss_cred_id_t cred)
15287 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
15289 + if (cred->name != GSS_C_NO_NAME) {
15291 + return GSS_S_COMPLETE;
15294 + if (cred->flags & CRED_FLAG_ACCEPT) {
15295 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
15296 + char serviceName[5 + MAXHOSTNAMELEN];
15298 + /* default host-based service is host@localhost */
15299 + memcpy(serviceName, "host@", 5);
15300 + if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
15301 + *minor = GSSEAP_NO_HOSTNAME;
15302 + return GSS_S_FAILURE;
15305 + nameBuf.value = serviceName;
15306 + nameBuf.length = strlen((char *)nameBuf.value);
15308 + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
15309 + nameMech, &cred->name);
15310 + if (GSS_ERROR(major))
15312 + } else if (cred->flags & CRED_FLAG_INITIATE) {
15313 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
15314 + major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
15315 + if (major == GSS_S_CRED_UNAVAIL)
15317 + major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
15318 + if (major != GSS_S_CRED_UNAVAIL)
15323 + return GSS_S_COMPLETE;
15327 +gssEapInquireCred(OM_uint32 *minor,
15328 + gss_cred_id_t cred,
15329 + gss_name_t *name,
15330 + OM_uint32 *pLifetime,
15331 + gss_cred_usage_t *cred_usage,
15332 + gss_OID_set *mechanisms)
15335 + time_t now, lifetime;
15337 + if (name != NULL) {
15338 + major = gssEapResolveCredIdentity(minor, cred);
15339 + if (GSS_ERROR(major))
15342 + if (cred->name != GSS_C_NO_NAME) {
15343 + major = gssEapDuplicateName(minor, cred->name, name);
15344 + if (GSS_ERROR(major))
15347 + *name = GSS_C_NO_NAME;
15350 + if (cred_usage != NULL) {
15351 + OM_uint32 flags = (cred->flags & (CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT));
15354 + case CRED_FLAG_INITIATE:
15355 + *cred_usage = GSS_C_INITIATE;
15357 + case CRED_FLAG_ACCEPT:
15358 + *cred_usage = GSS_C_ACCEPT;
15361 + *cred_usage = GSS_C_BOTH;
15366 + if (mechanisms != NULL) {
15367 + if (cred->mechanisms != GSS_C_NO_OID_SET)
15368 + major = duplicateOidSet(minor, cred->mechanisms, mechanisms);
15370 + major = gssEapIndicateMechs(minor, mechanisms);
15371 + if (GSS_ERROR(major))
15375 + if (cred->expiryTime == 0) {
15376 + lifetime = GSS_C_INDEFINITE;
15378 + now = time(NULL);
15379 + lifetime = now - cred->expiryTime;
15380 + if (lifetime < 0)
15384 + if (pLifetime != NULL) {
15385 + *pLifetime = lifetime;
15388 + if (lifetime == 0) {
15389 + major = GSS_S_CREDENTIALS_EXPIRED;
15390 + *minor = GSSEAP_CRED_EXPIRED;
15394 + major = GSS_S_COMPLETE;
15402 +gssEapSetCredPassword(OM_uint32 *minor,
15403 + gss_cred_id_t cred,
15404 + const gss_buffer_t password)
15406 + OM_uint32 major, tmpMinor;
15407 + gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
15409 + if (cred->flags & CRED_FLAG_RESOLVED) {
15410 + major = GSS_S_FAILURE;
15411 + *minor = GSSEAP_CRED_RESOLVED;
15415 + if (password != GSS_C_NO_BUFFER) {
15416 + major = duplicateBuffer(minor, password, &newPassword);
15417 + if (GSS_ERROR(major))
15420 + cred->flags |= CRED_FLAG_PASSWORD;
15422 + cred->flags &= ~(CRED_FLAG_PASSWORD);
15425 + gss_release_buffer(&tmpMinor, &cred->password);
15426 + cred->password = newPassword;
15428 + major = GSS_S_COMPLETE;
15436 +gssEapSetCredService(OM_uint32 *minor,
15437 + gss_cred_id_t cred,
15438 + const gss_name_t target)
15440 + OM_uint32 major, tmpMinor;
15441 + gss_name_t newTarget = GSS_C_NO_NAME;
15443 + if (cred->flags & CRED_FLAG_RESOLVED) {
15444 + major = GSS_S_FAILURE;
15445 + *minor = GSSEAP_CRED_RESOLVED;
15449 + if (target != GSS_C_NO_NAME) {
15450 + major = gssEapDuplicateName(minor, target, &newTarget);
15451 + if (GSS_ERROR(major))
15454 + cred->flags |= CRED_FLAG_TARGET;
15456 + cred->flags &= ~(CRED_FLAG_TARGET);
15459 + gssEapReleaseName(&tmpMinor, &cred->target);
15460 + cred->target = newTarget;
15462 + major = GSS_S_COMPLETE;
15470 +gssEapDuplicateCred(OM_uint32 *minor,
15471 + const gss_cred_id_t src,
15472 + gss_cred_id_t *pDst)
15474 + OM_uint32 major, tmpMinor;
15475 + gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
15477 + *pDst = GSS_C_NO_CREDENTIAL;
15479 + major = gssEapAllocCred(minor, &dst);
15480 + if (GSS_ERROR(major))
15483 + dst->flags = src->flags;
15485 + if (src->name != GSS_C_NO_NAME) {
15486 + major = gssEapDuplicateName(minor, src->name, &dst->name);
15487 + if (GSS_ERROR(major))
15491 + if (src->target != GSS_C_NO_NAME) {
15492 + major = gssEapDuplicateName(minor, src->target, &dst->target);
15493 + if (GSS_ERROR(major))
15497 + if (src->password.value != NULL) {
15498 + major = duplicateBuffer(minor, &src->password, &dst->password);
15499 + if (GSS_ERROR(major))
15503 + major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
15504 + if (GSS_ERROR(major))
15507 + dst->expiryTime = src->expiryTime;
15509 + if (src->radiusConfigFile.value != NULL)
15510 + duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
15511 + if (src->radiusConfigStanza.value != NULL)
15512 + duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
15513 + if (src->caCertificate.value != NULL)
15514 + duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
15515 + if (src->subjectNameConstraint.value != NULL)
15516 + duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
15517 + if (src->subjectAltNameConstraint.value != NULL)
15518 + duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
15520 +#ifdef GSSEAP_ENABLE_REAUTH
15521 + /* XXX krbCredCache, reauthCred */
15525 + dst = GSS_C_NO_CREDENTIAL;
15527 + major = GSS_S_COMPLETE;
15531 + gssEapReleaseCred(&tmpMinor, &dst);
15537 +staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
15539 + OM_uint32 major, tmpMinor;
15540 + gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
15541 + gss_name_t defaultIdentityName = GSS_C_NO_NAME;
15542 + gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
15543 + int isDefaultIdentity = FALSE;
15545 + major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
15546 + if (GSS_ERROR(major))
15549 + major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
15550 + gssEapPrimaryMechForCred(cred), &defaultIdentityName);
15551 + if (GSS_ERROR(major))
15554 + if (defaultIdentityName == GSS_C_NO_NAME) {
15555 + if (cred->name == GSS_C_NO_NAME) {
15556 + major = GSS_S_CRED_UNAVAIL;
15557 + *minor = GSSEAP_NO_DEFAULT_IDENTITY;
15561 + if (cred->name == GSS_C_NO_NAME) {
15562 + cred->name = defaultIdentityName;
15563 + defaultIdentityName = GSS_C_NO_NAME;
15564 + isDefaultIdentity = TRUE;
15566 + major = gssEapCompareName(minor, cred->name,
15567 + defaultIdentityName, &isDefaultIdentity);
15568 + if (GSS_ERROR(major))
15573 + if (isDefaultIdentity &&
15574 + (cred->flags & CRED_FLAG_PASSWORD) == 0) {
15575 + major = gssEapSetCredPassword(minor, cred, &defaultPassword);
15576 + if (GSS_ERROR(major))
15581 + gssEapReleaseName(&tmpMinor, &defaultIdentityName);
15582 + zeroAndReleasePassword(&defaultPassword);
15583 + gss_release_buffer(&tmpMinor, &defaultIdentity);
15589 +gssEapResolveInitiatorCred(OM_uint32 *minor,
15590 + const gss_cred_id_t cred,
15591 + const gss_name_t targetName
15592 +#ifndef HAVE_MOONSHOT_GET_IDENTITY
15596 + gss_cred_id_t *pResolvedCred)
15598 + OM_uint32 major, tmpMinor;
15599 + gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
15601 + if (cred == GSS_C_NO_CREDENTIAL) {
15602 + major = gssEapAcquireCred(minor,
15604 + GSS_C_INDEFINITE,
15605 + GSS_C_NO_OID_SET,
15610 + if (GSS_ERROR(major))
15613 + if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
15614 + major = GSS_S_NO_CRED;
15615 + *minor = GSSEAP_CRED_USAGE_MISMATCH;
15619 + major = gssEapDuplicateCred(minor, cred, &resolvedCred);
15620 + if (GSS_ERROR(major))
15624 + if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
15625 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
15626 + major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
15627 + if (major == GSS_S_CRED_UNAVAIL)
15629 + major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
15630 + if (GSS_ERROR(major) && major != GSS_S_CRED_UNAVAIL)
15633 + /* If we have a caller-supplied password, the credential is resolved. */
15634 + if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) {
15635 + major = GSS_S_CRED_UNAVAIL;
15636 + *minor = GSSEAP_NO_DEFAULT_CRED;
15640 + resolvedCred->flags |= CRED_FLAG_RESOLVED;
15643 + *pResolvedCred = resolvedCred;
15644 + resolvedCred = GSS_C_NO_CREDENTIAL;
15646 + major = GSS_S_COMPLETE;
15650 + gssEapReleaseCred(&tmpMinor, &resolvedCred);
15654 diff --git a/mech_eap/util_crypt.c b/mech_eap/util_crypt.c
15655 new file mode 100644
15656 index 0000000..b6e203e
15658 +++ b/mech_eap/util_crypt.c
15661 + * Copyright (c) 2011, JANET(UK)
15662 + * All rights reserved.
15664 + * Redistribution and use in source and binary forms, with or without
15665 + * modification, are permitted provided that the following conditions
15668 + * 1. Redistributions of source code must retain the above copyright
15669 + * notice, this list of conditions and the following disclaimer.
15671 + * 2. Redistributions in binary form must reproduce the above copyright
15672 + * notice, this list of conditions and the following disclaimer in the
15673 + * documentation and/or other materials provided with the distribution.
15675 + * 3. Neither the name of JANET(UK) nor the names of its contributors
15676 + * may be used to endorse or promote products derived from this software
15677 + * without specific prior written permission.
15679 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15680 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15681 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15682 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
15683 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15684 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
15685 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15686 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
15687 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15688 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
15692 + * Copyright 2001, 2008 by the Massachusetts Institute of Technology.
15693 + * Copyright 1993 by OpenVision Technologies, Inc.
15695 + * Permission to use, copy, modify, distribute, and sell this software
15696 + * and its documentation for any purpose is hereby granted without fee,
15697 + * provided that the above copyright notice appears in all copies and
15698 + * that both that copyright notice and this permission notice appear in
15699 + * supporting documentation, and that the name of OpenVision not be used
15700 + * in advertising or publicity pertaining to distribution of the software
15701 + * without specific, written prior permission. OpenVision makes no
15702 + * representations about the suitability of this software for any
15703 + * purpose. It is provided "as is" without express or implied warranty.
15705 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
15707 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
15708 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
15709 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15710 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15711 + * PERFORMANCE OF THIS SOFTWARE.
15714 + * Copyright (C) 1998 by the FundsXpress, INC.
15716 + * All rights reserved.
15718 + * Export of this software from the United States of America may require
15719 + * a specific license from the United States Government. It is the
15720 + * responsibility of any person or organization contemplating export to
15721 + * obtain such a license before exporting.
15723 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15724 + * distribute this software and its documentation for any purpose and
15725 + * without fee is hereby granted, provided that the above copyright
15726 + * notice appear in all copies and that both that copyright notice and
15727 + * this permission notice appear in supporting documentation, and that
15728 + * the name of FundsXpress. not be used in advertising or publicity pertaining
15729 + * to distribution of the software without specific, written prior
15730 + * permission. FundsXpress makes no representations about the suitability of
15731 + * this software for any purpose. It is provided "as is" without express
15732 + * or implied warranty.
15734 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15735 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15736 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15740 + * Message protection services: cryptography helpers.
15743 +#include "gssapiP_eap.h"
15746 + * DCE_STYLE indicates actual RRC is EC + RRC
15747 + * EC is extra rotate count for DCE_STYLE, pad length otherwise
15748 + * RRC is rotate count.
15750 +static krb5_error_code
15751 +mapIov(krb5_context context, int dce_style, size_t ec, size_t rrc,
15752 +#ifdef HAVE_HEIMDAL_VERSION
15753 + krb5_crypto crypto,
15755 + krb5_keyblock *crypto,
15757 + gss_iov_buffer_desc *iov,
15758 + int iov_count, krb5_crypto_iov **pkiov,
15759 + size_t *pkiov_count)
15761 + gss_iov_buffer_t header;
15762 + gss_iov_buffer_t trailer;
15764 + size_t kiov_count;
15765 + krb5_crypto_iov *kiov;
15766 + size_t k5_headerlen = 0, k5_trailerlen = 0;
15767 + size_t gss_headerlen, gss_trailerlen;
15768 + krb5_error_code code;
15771 + *pkiov_count = 0;
15773 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
15774 + GSSEAP_ASSERT(header != NULL);
15776 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
15777 + GSSEAP_ASSERT(trailer == NULL || rrc == 0);
15779 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen);
15783 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen);
15787 + /* Check header and trailer sizes */
15788 + gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */
15789 + gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */
15791 + /* If we're caller without a trailer, we must rotate by trailer length */
15792 + if (trailer == NULL) {
15793 + size_t actual_rrc = rrc;
15796 + actual_rrc += ec; /* compensate for Windows bug */
15798 + if (actual_rrc != gss_trailerlen)
15799 + return KRB5_BAD_MSIZE;
15801 + gss_headerlen += gss_trailerlen;
15802 + gss_trailerlen = 0;
15804 + if (trailer->buffer.length != gss_trailerlen)
15805 + return KRB5_BAD_MSIZE;
15808 + if (header->buffer.length != gss_headerlen)
15809 + return KRB5_BAD_MSIZE;
15811 + kiov_count = 3 + iov_count;
15812 + kiov = (krb5_crypto_iov *)GSSEAP_MALLOC(kiov_count * sizeof(krb5_crypto_iov));
15813 + if (kiov == NULL)
15817 + * The krb5 header is located at the end of the GSS header.
15819 + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER;
15820 + kiov[i].data.length = k5_headerlen;
15821 + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen;
15824 + for (j = 0; j < iov_count; j++) {
15825 + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
15826 + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY)
15829 + kiov[i].data.length = iov[j].buffer.length;
15830 + kiov[i].data.data = (char *)iov[j].buffer.value;
15835 + * The EC and encrypted GSS header are placed in the trailer, which may
15836 + * be rotated directly after the plaintext header if no trailer buffer
15839 + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
15840 + kiov[i].data.length = ec + 16; /* E(Header) */
15841 + if (trailer == NULL)
15842 + kiov[i].data.data = (char *)header->buffer.value + 16;
15844 + kiov[i].data.data = (char *)trailer->buffer.value;
15848 + * The krb5 trailer is placed after the encrypted copy of the
15849 + * krb5 header (which may be in the GSS header or trailer).
15851 + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
15852 + kiov[i].data.length = k5_trailerlen;
15853 + kiov[i].data.data = (char *)kiov[i - 1].data.data + ec + 16; /* E(Header) */
15857 + *pkiov_count = i;
15863 +gssEapEncrypt(krb5_context context,
15867 +#ifdef HAVE_HEIMDAL_VERSION
15868 + krb5_crypto crypto,
15870 + krb5_keyblock *crypto,
15873 + gss_iov_buffer_desc *iov,
15876 + krb5_error_code code;
15877 + size_t kiov_count;
15878 + krb5_crypto_iov *kiov = NULL;
15880 + code = mapIov(context, dce_style, ec, rrc, crypto,
15881 + iov, iov_count, &kiov, &kiov_count);
15885 +#ifdef HAVE_HEIMDAL_VERSION
15886 + code = krb5_encrypt_iov_ivec(context, crypto, usage, kiov, kiov_count, NULL);
15888 + code = krb5_c_encrypt_iov(context, crypto, usage, NULL, kiov, kiov_count);
15894 + if (kiov != NULL)
15895 + GSSEAP_FREE(kiov);
15901 +gssEapDecrypt(krb5_context context,
15905 +#ifdef HAVE_HEIMDAL_VERSION
15906 + krb5_crypto crypto,
15908 + krb5_keyblock *crypto,
15911 + gss_iov_buffer_desc *iov,
15914 + krb5_error_code code;
15915 + size_t kiov_count;
15916 + krb5_crypto_iov *kiov;
15918 + code = mapIov(context, dce_style, ec, rrc, crypto,
15919 + iov, iov_count, &kiov, &kiov_count);
15923 +#ifdef HAVE_HEIMDAL_VERSION
15924 + code = krb5_decrypt_iov_ivec(context, crypto, usage, kiov, kiov_count, NULL);
15926 + code = krb5_c_decrypt_iov(context, crypto, usage, NULL, kiov, kiov_count);
15930 + if (kiov != NULL)
15931 + GSSEAP_FREE(kiov);
15937 +gssEapMapCryptoFlag(OM_uint32 type)
15941 + switch (GSS_IOV_BUFFER_TYPE(type)) {
15942 + case GSS_IOV_BUFFER_TYPE_DATA:
15943 + case GSS_IOV_BUFFER_TYPE_PADDING:
15944 + ktype = KRB5_CRYPTO_TYPE_DATA;
15946 + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
15947 + ktype = KRB5_CRYPTO_TYPE_SIGN_ONLY;
15950 + ktype = KRB5_CRYPTO_TYPE_EMPTY;
15958 +gssEapLocateIov(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)
15961 + gss_iov_buffer_t p = GSS_C_NO_IOV_BUFFER;
15963 + if (iov == GSS_C_NO_IOV_BUFFER)
15964 + return GSS_C_NO_IOV_BUFFER;
15966 + for (i = iov_count - 1; i >= 0; i--) {
15967 + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == type) {
15968 + if (p == GSS_C_NO_IOV_BUFFER)
15971 + return GSS_C_NO_IOV_BUFFER;
15979 +gssEapIovMessageLength(gss_iov_buffer_desc *iov,
15981 + size_t *data_length_p,
15982 + size_t *assoc_data_length_p)
15985 + size_t data_length = 0, assoc_data_length = 0;
15987 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
15989 + *data_length_p = *assoc_data_length_p = 0;
15991 + for (i = 0; i < iov_count; i++) {
15992 + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[i].type);
15994 + if (type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
15995 + assoc_data_length += iov[i].buffer.length;
15997 + if (type == GSS_IOV_BUFFER_TYPE_DATA ||
15998 + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
15999 + data_length += iov[i].buffer.length;
16002 + *data_length_p = data_length;
16003 + *assoc_data_length_p = assoc_data_length;
16007 +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count)
16010 + OM_uint32 min_stat;
16012 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16014 + for (i = 0; i < iov_count; i++) {
16015 + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
16016 + gss_release_buffer(&min_stat, &iov[i].buffer);
16017 + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
16023 +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count)
16026 + krb5_boolean has_conf_data = FALSE;
16028 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16030 + for (i = 0; i < iov_count; i++) {
16031 + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) {
16032 + has_conf_data = TRUE;
16037 + return (has_conf_data == FALSE);
16041 +gssEapAllocIov(gss_iov_buffer_t iov, size_t size)
16043 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16044 + GSSEAP_ASSERT(iov->type & GSS_IOV_BUFFER_FLAG_ALLOCATE);
16046 + iov->buffer.length = size;
16047 + iov->buffer.value = GSSEAP_MALLOC(size);
16048 + if (iov->buffer.value == NULL) {
16049 + iov->buffer.length = 0;
16053 + iov->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED;
16057 diff --git a/mech_eap/util_json.cpp b/mech_eap/util_json.cpp
16058 new file mode 100644
16059 index 0000000..97eb1ed
16061 +++ b/mech_eap/util_json.cpp
16064 + * Copyright (c) 2011, JANET(UK)
16065 + * All rights reserved.
16067 + * Redistribution and use in source and binary forms, with or without
16068 + * modification, are permitted provided that the following conditions
16071 + * 1. Redistributions of source code must retain the above copyright
16072 + * notice, this list of conditions and the following disclaimer.
16074 + * 2. Redistributions in binary form must reproduce the above copyright
16075 + * notice, this list of conditions and the following disclaimer in the
16076 + * documentation and/or other materials provided with the distribution.
16078 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16079 + * may be used to endorse or promote products derived from this software
16080 + * without specific prior written permission.
16082 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16083 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16084 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16085 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16086 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16087 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16088 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16089 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16090 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16091 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16096 + * JSONObject utilities.
16099 +#include "gssapiP_eap.h"
16101 +#include <typeinfo>
16103 +#include <sstream>
16104 +#include <exception>
16107 +#define JSON_INIT(obj) do { \
16108 + if ((obj) == NULL) \
16109 + throw std::bad_alloc(); \
16113 +#define JSON_CHECK_CONTAINER() do { \
16114 + if (!json_is_object(m_obj) && !json_is_array(m_obj)) { \
16115 + std::string s("JSONObject is not a container"); \
16116 + throw JSONException(m_obj); \
16120 +#define JSON_CHECK_OBJECT() do { \
16121 + if (!json_is_object(m_obj)) { \
16122 + std::string s("JSONObject is not a dictionary"); \
16123 + throw JSONException(m_obj, JSON_OBJECT); \
16127 +#define JSON_CHECK_ARRAY() do { \
16128 + if (!json_is_array(m_obj)) { \
16129 + throw JSONException(m_obj, JSON_ARRAY); \
16133 +#define JSON_CHECK(s) do { \
16135 + throw JSONException(); \
16139 +JSONObject::load(const char *input, size_t flags, json_error_t *error)
16143 + obj = json_loads(input, flags, error);
16145 + return JSONObject(obj, false);
16149 +JSONObject::load(FILE *fp, size_t flags, json_error_t *error)
16153 + obj = json_loadf(fp, flags, error);
16155 + return JSONObject(obj, false);
16159 +JSONObject::dump(size_t flags) const
16161 + char *s = json_dumps(m_obj, flags);
16164 + throw std::bad_alloc();
16170 +JSONObject::dump(FILE *fp, size_t flags) const
16172 + int r = json_dumpf(m_obj, fp, flags);
16175 + throw std::bad_alloc();
16179 +JSONObject::size(void) const
16181 + if (json_is_object(m_obj))
16182 + return json_object_size(m_obj);
16183 + else if (json_is_array(m_obj))
16184 + return json_array_size(m_obj);
16189 +JSONObject::JSONObject(json_t *obj, bool retain)
16192 + json_incref(obj);
16196 +JSONObject::JSONObject(const char *value)
16198 + json_t *obj = json_string(value);
16203 +JSONObject::JSONObject(json_int_t value)
16205 + json_t *obj = json_integer(value);
16210 +JSONObject::JSONObject(double value)
16212 + json_t *obj = json_real(value);
16217 +JSONObject::JSONObject(bool value)
16219 + json_t *obj = value ? json_true() : json_false();
16224 +JSONObject::JSONObject(void)
16226 + json_t *obj = json_object();
16232 +JSONObject::object(void)
16234 + return JSONObject();
16238 +JSONObject::null(void)
16240 + return JSONObject(json_null(), false);
16244 +JSONObject::array(void)
16246 + return JSONObject(json_array(), false);
16250 +JSONObject::set(const char *key, JSONObject &value)
16252 + JSON_CHECK_OBJECT();
16253 + JSON_CHECK(json_object_set_new(m_obj, key, value.get()));
16257 +JSONObject::set(const char *key, const char *value)
16259 + JSONObject jobj(value);
16264 +JSONObject::set(const char *key, json_int_t value)
16266 + JSONObject jobj(value);
16271 +JSONObject::del(const char *key)
16273 + json_object_del(m_obj, key);
16277 +JSONObject::get(const char *key) const
16281 + obj = json_object_get(m_obj, key);
16283 + return JSONObject::null();
16285 + return JSONObject(obj, true);
16289 +JSONObject::get(size_t index) const
16293 + obj = json_array_get(m_obj, index);
16295 + return JSONObject::null();
16297 + return JSONObject(obj, true);
16301 +JSONObject::update(JSONObject &value)
16303 + JSON_CHECK_OBJECT();
16304 + json_t *other = value.get();
16305 + JSON_CHECK(json_object_update(m_obj, other));
16306 + json_decref(other);
16310 +JSONObject::operator[](size_t index) const
16312 + return get(index);
16316 +JSONObject::operator[](const char *key) const
16322 +JSONObject::append(JSONObject &value)
16324 + JSON_CHECK_ARRAY();
16325 + JSON_CHECK(json_array_append_new(m_obj, value.get()));
16329 +JSONObject::insert(size_t index, JSONObject &value)
16331 + JSON_CHECK_ARRAY();
16332 + JSON_CHECK(json_array_insert_new(m_obj, index, value.get()));
16336 +JSONObject::remove(size_t index)
16338 + JSON_CHECK_ARRAY();
16339 + JSON_CHECK(json_array_remove(m_obj, index));
16343 +JSONObject::clear(void)
16345 + JSON_CHECK_CONTAINER();
16347 + if (json_is_object(m_obj)) {
16348 + JSON_CHECK(json_object_clear(m_obj));
16349 + } else if (json_is_array(m_obj)) {
16350 + JSON_CHECK(json_array_clear(m_obj));
16355 +JSONObject::extend(JSONObject &value)
16357 + JSON_CHECK_ARRAY();
16358 + json_t *other = value.get();
16359 + JSON_CHECK(json_array_extend(m_obj, other));
16360 + json_decref(other);
16364 +JSONObject::string(void) const
16366 + return json_string_value(m_obj);
16370 +JSONObject::integer(void) const
16372 + return json_integer_value(m_obj);
16376 +JSONObject::real(void) const
16378 + return json_real_value(m_obj);
16382 +JSONObject::number(void) const
16384 + return json_number_value(m_obj);
16387 +#ifdef HAVE_SHIBRESOLVER
16389 +JSONObject::ddf(DDF &ddf)
16391 + if (ddf.isstruct()) {
16392 + DDF elem = ddf.first();
16393 + JSONObject jobj = JSONObject::object();
16395 + while (!elem.isnull()) {
16396 + JSONObject jtmp = JSONObject::ddf(elem);
16397 + jobj.set(elem.name(), jtmp);
16398 + elem = ddf.next();
16402 + } else if (ddf.islist()) {
16403 + DDF elem = ddf.first();
16404 + JSONObject jobj = JSONObject::array();
16406 + while (!elem.isnull()) {
16407 + JSONObject jtmp = JSONObject::ddf(elem);
16408 + jobj.append(jtmp);
16409 + elem = ddf.next();
16413 + } else if (ddf.isstring()) {
16414 + return JSONObject(ddf.string());
16415 + } else if (ddf.isint()) {
16416 + return JSONObject((json_int_t)ddf.integer());
16417 + } else if (ddf.isfloat()) {
16418 + return JSONObject(ddf.floating());
16419 + } else if (ddf.isempty() || ddf.ispointer()) {
16420 + return JSONObject::object();
16421 + } else if (ddf.isnull()) {
16422 + return JSONObject::null();
16425 + std::string s("Unbridgeable DDF object");
16426 + throw JSONException();
16430 +JSONObject::ddf(void) const
16434 + switch (type()) {
16435 + case JSON_OBJECT: {
16436 + JSONIterator iter = iterator();
16439 + const char *key = iter.key();
16440 + DDF value = iter.value().ddf();
16441 + ddf.addmember(key).swap(value);
16442 + } while (iter.next());
16445 + case JSON_ARRAY: {
16446 + size_t i, nelems = size();
16448 + for (i = 0; i < nelems; i++) {
16449 + DDF value = get(i).ddf();
16454 + case JSON_STRING:
16455 + ddf.string(string());
16457 + case JSON_INTEGER:
16458 + ddf.integer(integer());
16461 + ddf.floating(real());
16475 +#endif /* HAVE_SHIBRESOLVER */
16477 +bool JSONObject::isObject(void) const
16479 + return json_is_object(m_obj);
16482 +bool JSONObject::isArray(void) const
16484 + return json_is_array(m_obj);
16487 +bool JSONObject::isString(void) const
16489 + return json_is_string(m_obj);
16492 +bool JSONObject::isInteger(void) const
16494 + return json_is_integer(m_obj);
16497 +bool JSONObject::isNumber(void) const
16499 + return json_is_number(m_obj);
16502 +bool JSONObject::isBoolean(void) const
16504 + return json_is_boolean(m_obj);
16507 +bool JSONObject::isNull(void) const
16509 + return json_is_null(m_obj);
16512 +JSONIterator::JSONIterator(const JSONObject &obj)
16514 + m_obj = obj.get();
16515 + m_iter = json_object_iter(m_obj);
16518 +JSONIterator::~JSONIterator(void)
16520 + json_decref(m_obj);
16524 +JSONIterator::key(void) const
16526 + return json_object_iter_key(m_iter);
16530 +JSONIterator::value(void) const
16532 + return JSONObject(json_object_iter_value(m_iter));
16536 +JSONIterator::next(void)
16538 + m_iter = json_object_iter_next(m_obj, m_iter);
16539 + return m_iter != NULL;
16542 +JSONException::JSONException(json_t *obj, json_type type)
16547 + m_obj = json_incref(obj);
16551 + s = json_dumps(m_obj, 0);
16554 + case JSON_OBJECT: t = "OBJECT"; break;
16555 + case JSON_ARRAY: t = "ARRAY"; break;
16556 + case JSON_STRING: t = "STRING"; break;
16557 + case JSON_INTEGER: t = "INTEGER"; break;
16558 + case JSON_REAL: t = "REAL"; break;
16559 + case JSON_TRUE: t = "TRUE"; break;
16560 + case JSON_FALSE: t = "FALSE"; break;
16561 + case JSON_NULL: t = "NULL"; break;
16562 + default: t = "UNKNOWN"; break;
16565 + if (obj != NULL) {
16566 + m_reason = "Invalid JSON object: " + std::string(s);
16567 + if (type != JSON_NULL)
16568 + m_reason += " (excepted type " + std::string(t) + ")";
16570 + m_reason = "Internal JSON error";
16576 diff --git a/mech_eap/util_json.h b/mech_eap/util_json.h
16577 new file mode 100644
16578 index 0000000..4ffecc8
16580 +++ b/mech_eap/util_json.h
16583 + * Copyright (c) 2011, JANET(UK)
16584 + * All rights reserved.
16586 + * Redistribution and use in source and binary forms, with or without
16587 + * modification, are permitted provided that the following conditions
16590 + * 1. Redistributions of source code must retain the above copyright
16591 + * notice, this list of conditions and the following disclaimer.
16593 + * 2. Redistributions in binary form must reproduce the above copyright
16594 + * notice, this list of conditions and the following disclaimer in the
16595 + * documentation and/or other materials provided with the distribution.
16597 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16598 + * may be used to endorse or promote products derived from this software
16599 + * without specific prior written permission.
16601 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16602 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16603 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16604 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16605 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16606 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16607 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16608 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16609 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16610 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16615 + * JSON object wrapper with not-entirely-toll-free DDF bridging.
16618 +#ifndef _UTIL_JSON_H_
16619 +#define _UTIL_JSON_H_ 1
16621 +#ifdef __cplusplus
16625 +#include <jansson.h>
16627 +#ifdef HAVE_SHIBRESOLVER
16628 +#include <shibsp/remoting/ddf.h>
16629 +using namespace shibsp;
16632 +namespace gss_eap_util {
16633 + class JSONObject;
16635 + class JSONException : public std::exception {
16637 + JSONException(json_t *obj = NULL, json_type type = JSON_NULL);
16639 + ~JSONException(void) throw() {
16640 + json_decref(m_obj);
16643 + virtual const char *what(void) const throw() {
16644 + return m_reason.c_str();
16649 + json_type m_type;
16650 + std::string m_reason;
16653 + class JSONIterator {
16655 + JSONIterator(const JSONObject &obj);
16656 + ~JSONIterator(void);
16657 + const char *key(void) const;
16658 + JSONObject value(void) const;
16666 + class JSONObject {
16668 + static JSONObject load(const char *input, size_t flags, json_error_t *error);
16669 + static JSONObject load(FILE *, size_t flags, json_error_t *error);
16671 + static JSONObject object(void);
16672 + static JSONObject array(void);
16673 + static JSONObject null(void);
16674 +#ifdef HAVE_SHIBRESOLVER
16675 + static JSONObject ddf(DDF &value);
16678 + char *dump(size_t flags = 0) const;
16679 + void dump(FILE *fp, size_t flags = JSON_INDENT(4)) const;
16681 + json_type type(void) const { return json_typeof(m_obj); }
16682 + size_t size(void) const;
16684 + JSONObject(void);
16685 + JSONObject(const char *value);
16686 + JSONObject(json_int_t value);
16687 + JSONObject(double value);
16688 + JSONObject(bool value);
16690 + void set(const char *key, JSONObject &value);
16691 + void set(const char *key, const char *value);
16692 + void set(const char *key, json_int_t value);
16693 + void del(const char *key);
16694 + void update(JSONObject &value);
16695 + JSONIterator iterator(void) const { return JSONIterator(*this); }
16696 + JSONObject get(const char *key) const;
16697 + JSONObject operator[](const char *key) const;
16699 + JSONObject get(size_t index) const;
16700 + JSONObject operator[](size_t index) const;
16701 + void append(JSONObject &value);
16702 + void insert(size_t index, JSONObject &value);
16703 + void remove(size_t index);
16704 + void clear(void);
16705 + void extend(JSONObject &value);
16707 + const char *string(void) const;
16708 + json_int_t integer(void) const;
16709 + double real(void) const;
16710 + double number(void) const;
16711 +#ifdef HAVE_SHIBRESOLVER
16712 + DDF ddf(void) const;
16715 + bool isObject(void) const;
16716 + bool isArray(void) const;
16717 + bool isString(void) const;
16718 + bool isInteger(void) const;
16719 + bool isNumber(void) const;
16720 + bool isBoolean(void) const;
16721 + bool isNull(void) const;
16723 + ~JSONObject(void)
16725 + if (m_obj != NULL)
16726 + json_decref(m_obj);
16729 + JSONObject(const JSONObject &obj)
16731 + m_obj = json_incref(obj.m_obj);
16734 + JSONObject& operator=(const JSONObject &obj)
16736 + if (this != &obj)
16742 + friend class JSONIterator;
16744 + json_t *get(void) const {
16745 + return json_incref(m_obj);
16748 + void set(json_t *obj) {
16749 + if (m_obj != obj) {
16750 + json_decref(m_obj);
16751 + m_obj = json_incref(m_obj);
16755 + JSONObject(json_t *obj, bool retain = true);
16761 +#endif /* __cplusplus */
16763 +#endif /* _UTIL_JSON_H_ */
16764 diff --git a/mech_eap/util_krb.c b/mech_eap/util_krb.c
16765 new file mode 100644
16766 index 0000000..5eaa31e
16768 +++ b/mech_eap/util_krb.c
16771 + * Copyright (c) 2011, JANET(UK)
16772 + * All rights reserved.
16774 + * Redistribution and use in source and binary forms, with or without
16775 + * modification, are permitted provided that the following conditions
16778 + * 1. Redistributions of source code must retain the above copyright
16779 + * notice, this list of conditions and the following disclaimer.
16781 + * 2. Redistributions in binary form must reproduce the above copyright
16782 + * notice, this list of conditions and the following disclaimer in the
16783 + * documentation and/or other materials provided with the distribution.
16785 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16786 + * may be used to endorse or promote products derived from this software
16787 + * without specific prior written permission.
16789 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16790 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16791 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16792 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16793 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16794 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16795 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16796 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16797 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16798 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16803 + * Kerberos 5 helpers.
16806 +#include "gssapiP_eap.h"
16809 +gssEapDestroyKrbContext(krb5_context context)
16811 + if (context != NULL)
16812 + krb5_free_context(context);
16815 +static krb5_error_code
16816 +initKrbContext(krb5_context *pKrbContext)
16818 + krb5_context krbContext;
16819 + krb5_error_code code;
16820 + char *defaultRealm = NULL;
16822 + *pKrbContext = NULL;
16824 + code = krb5_init_context(&krbContext);
16828 + krb5_appdefault_string(krbContext, "eap_gss",
16829 + NULL, "default_realm", "", &defaultRealm);
16831 + if (defaultRealm != NULL && defaultRealm[0] != '\0') {
16832 + code = krb5_set_default_realm(krbContext, defaultRealm);
16837 + *pKrbContext = krbContext;
16840 + krb5_free_default_realm(krbContext, defaultRealm);
16842 + if (code != 0 && krbContext != NULL)
16843 + krb5_free_context(krbContext);
16849 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context)
16851 + struct gss_eap_thread_local_data *tld;
16856 + tld = gssEapGetThreadLocalData();
16857 + if (tld != NULL) {
16858 + if (tld->krbContext == NULL) {
16859 + *minor = initKrbContext(&tld->krbContext);
16861 + tld->krbContext = NULL;
16863 + *context = tld->krbContext;
16865 + *minor = GSSEAP_GET_LAST_ERROR();
16868 + GSSEAP_ASSERT(*context != NULL || *minor != 0);
16870 + return (*minor == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
16874 + * Derive a key K for RFC 4121 use by using the following
16875 + * derivation function (based on RFC 4402);
16877 + * KMSK = random-to-key(MSK)
16878 + * Tn = pseudo-random(KMSK, n || "rfc4121-gss-eap")
16879 + * L = output key size
16880 + * K = truncate(L, T1 || T2 || .. || Tn)
16882 + * The output must be freed by krb5_free_keyblock_contents(),
16883 + * not GSSEAP_FREE().
16886 +gssEapDeriveRfc3961Key(OM_uint32 *minor,
16887 + const unsigned char *inputKey,
16888 + size_t inputKeyLength,
16889 + krb5_enctype encryptionType,
16890 + krb5_keyblock *pKey)
16892 + krb5_context krbContext;
16893 +#ifndef HAVE_HEIMDAL_VERSION
16896 + krb5_data ns, t, derivedKeyData;
16897 + krb5_keyblock kd;
16898 + krb5_error_code code;
16899 + size_t randomLength, keyLength, prfLength;
16900 + unsigned char constant[4 + sizeof("rfc4121-gss-eap") - 1], *p;
16901 + ssize_t i, remain;
16903 + GSSEAP_KRB_INIT(&krbContext);
16904 + GSSEAP_ASSERT(encryptionType != ENCTYPE_NULL);
16906 + KRB_KEY_INIT(pKey);
16907 + KRB_KEY_INIT(&kd);
16908 + KRB_KEY_TYPE(&kd) = encryptionType;
16910 + KRB_DATA_INIT(&ns);
16911 + KRB_DATA_INIT(&t);
16912 + KRB_DATA_INIT(&derivedKeyData);
16914 + code = krb5_c_keylengths(krbContext, encryptionType,
16915 + &randomLength, &keyLength);
16919 + /* Convert EAP MSK into a Kerberos key */
16921 +#ifdef HAVE_HEIMDAL_VERSION
16922 + code = krb5_random_to_key(krbContext, encryptionType, inputKey,
16923 + MIN(inputKeyLength, randomLength), &kd);
16925 + data.length = MIN(inputKeyLength, randomLength);
16926 + data.data = (char *)inputKey;
16928 + KRB_KEY_DATA(&kd) = KRB_MALLOC(keyLength);
16929 + if (KRB_KEY_DATA(&kd) == NULL) {
16933 + KRB_KEY_LENGTH(&kd) = keyLength;
16935 + code = krb5_c_random_to_key(krbContext, encryptionType, &data, &kd);
16936 +#endif /* HAVE_HEIMDAL_VERSION */
16940 + memset(&constant[0], 0, 4);
16941 + memcpy(&constant[4], "rfc4121-gss-eap", sizeof("rfc4121-gss-eap") - 1);
16943 + ns.length = sizeof(constant);
16944 + ns.data = (char *)constant;
16946 + /* Plug derivation constant and key into PRF */
16947 + code = krb5_c_prf_length(krbContext, encryptionType, &prfLength);
16951 +#ifndef HAVE_HEIMDAL_VERSION
16952 + /* Same API, but different allocation rules, unfortunately. */
16953 + t.length = prfLength;
16954 + t.data = GSSEAP_MALLOC(t.length);
16955 + if (t.data == NULL) {
16961 + derivedKeyData.length = randomLength;
16962 + derivedKeyData.data = GSSEAP_MALLOC(derivedKeyData.length);
16963 + if (derivedKeyData.data == NULL) {
16968 + for (i = 0, p = (unsigned char *)derivedKeyData.data, remain = randomLength;
16970 + p += t.length, remain -= t.length, i++)
16972 + store_uint32_be(i, ns.data);
16974 + code = krb5_c_prf(krbContext, &kd, &ns, &t);
16978 + memcpy(p, t.data, MIN(t.length, remain));
16981 + /* Finally, convert PRF output into a new key which we will return */
16982 +#ifdef HAVE_HEIMDAL_VERSION
16983 + krb5_free_keyblock_contents(krbContext, &kd);
16984 + KRB_KEY_INIT(&kd);
16986 + code = krb5_random_to_key(krbContext, encryptionType,
16987 + derivedKeyData.data, derivedKeyData.length, &kd);
16989 + code = krb5_c_random_to_key(krbContext, encryptionType,
16990 + &derivedKeyData, &kd);
16999 + krb5_free_keyblock_contents(krbContext, &kd);
17000 +#ifdef HAVE_HEIMDAL_VERSION
17001 + krb5_free_data_contents(krbContext, &t);
17003 + if (t.data != NULL) {
17004 + memset(t.data, 0, t.length);
17005 + GSSEAP_FREE(t.data);
17008 + if (derivedKeyData.data != NULL) {
17009 + memset(derivedKeyData.data, 0, derivedKeyData.length);
17010 + GSSEAP_FREE(derivedKeyData.data);
17015 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
17018 +#ifdef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17019 +extern krb5_error_code
17020 +krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
17024 +rfc3961ChecksumTypeForKey(OM_uint32 *minor,
17025 + krb5_keyblock *key,
17026 + krb5_cksumtype *cksumtype)
17028 + krb5_context krbContext;
17029 +#ifndef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17031 + krb5_checksum cksum;
17034 + GSSEAP_KRB_INIT(&krbContext);
17036 +#ifdef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17037 + *minor = krb5int_c_mandatory_cksumtype(krbContext, KRB_KEY_TYPE(key),
17040 + return GSS_S_FAILURE;
17042 + KRB_DATA_INIT(&data);
17044 + memset(&cksum, 0, sizeof(cksum));
17047 + * This is a complete hack but it's the only way to work with
17048 + * MIT Kerberos pre-1.9 without using private API, as it does
17049 + * not support passing in zero as the checksum type.
17051 + *minor = krb5_c_make_checksum(krbContext, 0, key, 0, &data, &cksum);
17053 + return GSS_S_FAILURE;
17055 +#ifdef HAVE_HEIMDAL_VERSION
17056 + *cksumtype = cksum.cksumtype;
17058 + *cksumtype = cksum.checksum_type;
17061 + krb5_free_checksum_contents(krbContext, &cksum);
17062 +#endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */
17064 + if (!krb5_c_is_keyed_cksum(*cksumtype)) {
17065 + *minor = (OM_uint32)KRB5KRB_AP_ERR_INAPP_CKSUM;
17066 + return GSS_S_FAILURE;
17069 + return GSS_S_COMPLETE;
17073 +krbCryptoLength(krb5_context krbContext,
17074 +#ifdef HAVE_HEIMDAL_VERSION
17075 + krb5_crypto krbCrypto,
17077 + krb5_keyblock *key,
17082 +#ifdef HAVE_HEIMDAL_VERSION
17083 + return krb5_crypto_length(krbContext, krbCrypto, type, length);
17085 + unsigned int len;
17086 + krb5_error_code code;
17088 + code = krb5_c_crypto_length(krbContext, KRB_KEY_TYPE(key), type, &len);
17090 + *length = (size_t)len;
17097 +krbPaddingLength(krb5_context krbContext,
17098 +#ifdef HAVE_HEIMDAL_VERSION
17099 + krb5_crypto krbCrypto,
17101 + krb5_keyblock *key,
17103 + size_t dataLength,
17104 + size_t *padLength)
17106 + krb5_error_code code;
17107 +#ifdef HAVE_HEIMDAL_VERSION
17108 + size_t headerLength, paddingLength;
17110 + code = krbCryptoLength(krbContext, krbCrypto,
17111 + KRB5_CRYPTO_TYPE_HEADER, &headerLength);
17115 + dataLength += headerLength;
17117 + code = krb5_crypto_length(krbContext, krbCrypto,
17118 + KRB5_CRYPTO_TYPE_PADDING, &paddingLength);
17122 + if (paddingLength != 0 && (dataLength % paddingLength) != 0)
17123 + *padLength = paddingLength - (dataLength % paddingLength);
17129 + unsigned int pad;
17131 + code = krb5_c_padding_length(krbContext, KRB_KEY_TYPE(key), dataLength, &pad);
17133 + *padLength = (size_t)pad;
17136 +#endif /* HAVE_HEIMDAL_VERSION */
17140 +krbBlockSize(krb5_context krbContext,
17141 +#ifdef HAVE_HEIMDAL_VERSION
17142 + krb5_crypto krbCrypto,
17144 + krb5_keyblock *key,
17146 + size_t *blockSize)
17148 +#ifdef HAVE_HEIMDAL_VERSION
17149 + return krb5_crypto_getblocksize(krbContext, krbCrypto, blockSize);
17151 + return krb5_c_block_size(krbContext, KRB_KEY_TYPE(key), blockSize);
17156 +krbEnctypeToString(
17157 +#ifdef HAVE_HEIMDAL_VERSION
17158 + krb5_context krbContext,
17160 + krb5_context krbContext GSSEAP_UNUSED,
17162 + krb5_enctype enctype,
17163 + const char *prefix,
17164 + gss_buffer_t string)
17166 + krb5_error_code code;
17167 +#ifdef HAVE_HEIMDAL_VERSION
17168 + char *enctypeBuf = NULL;
17170 + char enctypeBuf[128];
17172 + size_t prefixLength, enctypeLength;
17174 +#ifdef HAVE_HEIMDAL_VERSION
17175 + code = krb5_enctype_to_string(krbContext, enctype, &enctypeBuf);
17177 + code = krb5_enctype_to_name(enctype, 0, enctypeBuf, sizeof(enctypeBuf));
17182 + prefixLength = (prefix != NULL) ? strlen(prefix) : 0;
17183 + enctypeLength = strlen(enctypeBuf);
17185 + string->value = GSSEAP_MALLOC(prefixLength + enctypeLength + 1);
17186 + if (string->value == NULL) {
17187 +#ifdef HAVE_HEIMDAL_VERSION
17188 + krb5_xfree(enctypeBuf);
17193 + if (prefixLength != 0)
17194 + memcpy(string->value, prefix, prefixLength);
17195 + memcpy((char *)string->value + prefixLength, enctypeBuf, enctypeLength);
17197 + string->length = prefixLength + enctypeLength;
17198 + ((char *)string->value)[string->length] = '\0';
17200 +#ifdef HAVE_HEIMDAL_VERSION
17201 + krb5_xfree(enctypeBuf);
17208 +krbMakeAuthDataKdcIssued(krb5_context context,
17209 + const krb5_keyblock *key,
17210 + krb5_const_principal issuer,
17211 +#ifdef HAVE_HEIMDAL_VERSION
17212 + const AuthorizationData *authdata,
17213 + AuthorizationData *adKdcIssued
17215 + krb5_authdata *const *authdata,
17216 + krb5_authdata ***adKdcIssued
17220 +#ifdef HAVE_HEIMDAL_VERSION
17221 + krb5_error_code code;
17222 + AD_KDCIssued kdcIssued;
17223 + AuthorizationDataElement adDatum;
17224 + unsigned char *buf;
17225 + size_t buf_size, len;
17226 + krb5_crypto crypto = NULL;
17228 + memset(&kdcIssued, 0, sizeof(kdcIssued));
17229 + memset(adKdcIssued, 0, sizeof(*adKdcIssued));
17231 + kdcIssued.i_realm = issuer->realm != NULL ? (Realm *)&issuer->realm : NULL;
17232 + kdcIssued.i_sname = (PrincipalName *)&issuer->name;
17233 + kdcIssued.elements = *authdata;
17235 + ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata, &len, code);
17239 + code = krb5_crypto_init(context, key, 0, &crypto);
17243 + code = krb5_create_checksum(context, crypto, KRB5_KU_AD_KDC_ISSUED,
17244 + 0, buf, buf_size, &kdcIssued.ad_checksum);
17248 + free(buf); /* match ASN1_MALLOC_ENCODE */
17251 + ASN1_MALLOC_ENCODE(AD_KDCIssued, buf, buf_size, &kdcIssued, &len, code);
17255 + adDatum.ad_type = KRB5_AUTHDATA_KDC_ISSUED;
17256 + adDatum.ad_data.length = buf_size;
17257 + adDatum.ad_data.data = buf;
17259 + code = add_AuthorizationData(adKdcIssued, &adDatum);
17265 + free(buf); /* match ASN1_MALLOC_ENCODE */
17266 + if (crypto != NULL)
17267 + krb5_crypto_destroy(context, crypto);
17268 + free_Checksum(&kdcIssued.ad_checksum);
17272 + return krb5_make_authdata_kdc_issued(context, key, issuer, authdata,
17274 +#endif /* HAVE_HEIMDAL_VERSION */
17278 +krbMakeCred(krb5_context krbContext,
17279 + krb5_auth_context authContext,
17280 + krb5_creds *creds,
17283 + krb5_error_code code;
17284 +#ifdef HAVE_HEIMDAL_VERSION
17285 + KRB_CRED krbCred;
17286 + KrbCredInfo krbCredInfo;
17287 + EncKrbCredPart encKrbCredPart;
17288 + krb5_keyblock *key;
17289 + krb5_crypto krbCrypto = NULL;
17290 + krb5_data encKrbCredPartData;
17291 + krb5_replay_data rdata;
17294 + krb5_data *d = NULL;
17297 + memset(data, 0, sizeof(*data));
17298 +#ifdef HAVE_HEIMDAL_VERSION
17299 + memset(&krbCred, 0, sizeof(krbCred));
17300 + memset(&krbCredInfo, 0, sizeof(krbCredInfo));
17301 + memset(&encKrbCredPart, 0, sizeof(encKrbCredPart));
17302 + memset(&rdata, 0, sizeof(rdata));
17304 + if (authContext->local_subkey)
17305 + key = authContext->local_subkey;
17306 + else if (authContext->remote_subkey)
17307 + key = authContext->remote_subkey;
17309 + key = authContext->keyblock;
17311 + krbCred.pvno = 5;
17312 + krbCred.msg_type = krb_cred;
17313 + krbCred.tickets.val = (Ticket *)GSSEAP_CALLOC(1, sizeof(Ticket));
17314 + if (krbCred.tickets.val == NULL) {
17318 + krbCred.tickets.len = 1;
17320 + code = decode_Ticket(creds->ticket.data,
17321 + creds->ticket.length,
17322 + krbCred.tickets.val, &len);
17326 + krbCredInfo.key = creds->session;
17327 + krbCredInfo.prealm = &creds->client->realm;
17328 + krbCredInfo.pname = &creds->client->name;
17329 + krbCredInfo.flags = &creds->flags.b;
17330 + krbCredInfo.authtime = &creds->times.authtime;
17331 + krbCredInfo.starttime = &creds->times.starttime;
17332 + krbCredInfo.endtime = &creds->times.endtime;
17333 + krbCredInfo.renew_till = &creds->times.renew_till;
17334 + krbCredInfo.srealm = &creds->server->realm;
17335 + krbCredInfo.sname = &creds->server->name;
17336 + krbCredInfo.caddr = creds->addresses.len ? &creds->addresses : NULL;
17338 + encKrbCredPart.ticket_info.len = 1;
17339 + encKrbCredPart.ticket_info.val = &krbCredInfo;
17340 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
17341 + rdata.seq = authContext->local_seqnumber;
17342 + encKrbCredPart.nonce = (int32_t *)&rdata.seq;
17344 + encKrbCredPart.nonce = NULL;
17346 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
17347 + krb5_us_timeofday(krbContext, &rdata.timestamp, &rdata.usec);
17348 + encKrbCredPart.timestamp = &rdata.timestamp;
17349 + encKrbCredPart.usec = &rdata.usec;
17351 + encKrbCredPart.timestamp = NULL;
17352 + encKrbCredPart.usec = NULL;
17354 + encKrbCredPart.s_address = authContext->local_address;
17355 + encKrbCredPart.r_address = authContext->remote_address;
17357 + ASN1_MALLOC_ENCODE(EncKrbCredPart, encKrbCredPartData.data,
17358 + encKrbCredPartData.length, &encKrbCredPart,
17363 + code = krb5_crypto_init(krbContext, key, 0, &krbCrypto);
17367 + code = krb5_encrypt_EncryptedData(krbContext,
17369 + KRB5_KU_KRB_CRED,
17370 + encKrbCredPartData.data,
17371 + encKrbCredPartData.length,
17373 + &krbCred.enc_part);
17377 + ASN1_MALLOC_ENCODE(KRB_CRED, data->data, data->length,
17378 + &krbCred, &len, code);
17382 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
17383 + authContext->local_seqnumber++;
17386 + if (krbCrypto != NULL)
17387 + krb5_crypto_destroy(krbContext, krbCrypto);
17388 + free_KRB_CRED(&krbCred);
17389 + krb5_data_free(&encKrbCredPartData);
17393 + code = krb5_mk_1cred(krbContext, authContext, creds, &d, NULL);
17400 +#endif /* HAVE_HEIMDAL_VERSION */
17402 diff --git a/mech_eap/util_lucid.c b/mech_eap/util_lucid.c
17403 new file mode 100644
17404 index 0000000..f9e9941
17406 +++ b/mech_eap/util_lucid.c
17409 + * Copyright (c) 2011, JANET(UK)
17410 + * All rights reserved.
17412 + * Redistribution and use in source and binary forms, with or without
17413 + * modification, are permitted provided that the following conditions
17416 + * 1. Redistributions of source code must retain the above copyright
17417 + * notice, this list of conditions and the following disclaimer.
17419 + * 2. Redistributions in binary form must reproduce the above copyright
17420 + * notice, this list of conditions and the following disclaimer in the
17421 + * documentation and/or other materials provided with the distribution.
17423 + * 3. Neither the name of JANET(UK) nor the names of its contributors
17424 + * may be used to endorse or promote products derived from this software
17425 + * without specific prior written permission.
17427 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17428 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17429 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17430 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17431 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17432 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17433 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17434 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17435 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17436 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17441 + * "Lucid" security context export routine (called by MIT Kerberos mechanism).
17444 +#include "gssapiP_eap.h"
17447 +gssEapExportLucidSecContext(OM_uint32 *minor,
17448 + gss_ctx_id_t ctx,
17449 + const gss_OID desiredObject GSSEAP_UNUSED,
17450 + gss_buffer_set_t *data_set)
17452 + OM_uint32 major = GSS_S_COMPLETE;
17453 + int haveAcceptorSubkey =
17454 + ((rfc4121Flags(ctx, 0) & TOK_FLAG_ACCEPTOR_SUBKEY) != 0);
17455 + gss_buffer_desc rep;
17456 +#ifdef HAVE_HEIMDAL_VERSION
17457 + krb5_error_code code;
17458 + krb5_storage *sp;
17459 + krb5_data data = { 0 };
17461 + sp = krb5_storage_emem();
17462 + if (sp == NULL) {
17467 + code = krb5_store_int32(sp, 1); /* version */
17471 + code = krb5_store_int32(sp, CTX_IS_INITIATOR(ctx));
17475 + code = krb5_store_int32(sp, ctx->expiryTime);
17479 + code = krb5_store_int32(sp, 0);
17483 + code = krb5_store_int32(sp, ctx->sendSeq);
17487 + code = krb5_store_int32(sp, 0);
17491 + code = krb5_store_int32(sp, ctx->recvSeq);
17495 + code = krb5_store_int32(sp, 1); /* is_cfx */
17499 + code = krb5_store_int32(sp, haveAcceptorSubkey);
17503 + code = krb5_store_keyblock(sp, ctx->rfc3961Key);
17507 + if (haveAcceptorSubkey) {
17508 + code = krb5_store_keyblock(sp, ctx->rfc3961Key);
17513 + code = krb5_storage_to_data(sp, &data);
17517 + rep.length = data.length;
17518 + rep.value = data.data;
17520 + major = gss_add_buffer_set_member(minor, &rep, data_set);
17521 + if (GSS_ERROR(major))
17525 + krb5_data_free(&data);
17527 + if (major == GSS_S_COMPLETE) {
17529 + major = (code != 0) ? GSS_S_FAILURE : GSS_S_COMPLETE;
17534 + gss_krb5_lucid_context_v1_t *lctx;
17535 + gss_krb5_lucid_key_t *lkey = NULL;
17537 + lctx = (gss_krb5_lucid_context_v1_t *)GSSEAP_CALLOC(1, sizeof(*lctx));
17538 + if (lctx == NULL) {
17539 + major = GSS_S_FAILURE;
17544 + lctx->version = 1;
17545 + lctx->initiate = CTX_IS_INITIATOR(ctx);
17546 + if (ctx->expiryTime == 0)
17547 + lctx->endtime = KRB_TIME_FOREVER;
17549 + lctx->endtime = ctx->expiryTime;
17550 + lctx->send_seq = ctx->sendSeq;
17551 + lctx->recv_seq = ctx->recvSeq;
17552 + lctx->protocol = 1;
17554 + lctx->cfx_kd.have_acceptor_subkey = haveAcceptorSubkey;
17556 + lkey = haveAcceptorSubkey
17557 + ? &lctx->cfx_kd.acceptor_subkey
17558 + : &lctx->cfx_kd.ctx_key;
17560 + lkey->type = KRB_KEY_TYPE(&ctx->rfc3961Key);
17561 + lkey->data = GSSEAP_MALLOC(KRB_KEY_LENGTH(&ctx->rfc3961Key));
17562 + if (lkey->data == NULL) {
17563 + major = GSS_S_FAILURE;
17567 + lkey->length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
17568 + memcpy(lkey->data, KRB_KEY_DATA(&ctx->rfc3961Key), lkey->length);
17570 + rep.value = &lctx;
17571 + rep.length = sizeof(void *);
17573 + major = gss_add_buffer_set_member(minor, &rep, data_set);
17574 + if (GSS_ERROR(major))
17578 + if (GSS_ERROR(major)) {
17579 + if (lctx != NULL) {
17580 + if (lkey != NULL && lkey->data != NULL) {
17581 + memset(lkey->data, 0, lkey->length);
17582 + GSSEAP_FREE(lkey->data);
17584 + GSSEAP_FREE(lctx);
17589 +#endif /* HAVE_HEIMDAL_VERSION */
17591 diff --git a/mech_eap/util_mech.c b/mech_eap/util_mech.c
17592 new file mode 100644
17593 index 0000000..958e43d
17595 +++ b/mech_eap/util_mech.c
17598 + * Copyright (c) 2011, JANET(UK)
17599 + * All rights reserved.
17601 + * Redistribution and use in source and binary forms, with or without
17602 + * modification, are permitted provided that the following conditions
17605 + * 1. Redistributions of source code must retain the above copyright
17606 + * notice, this list of conditions and the following disclaimer.
17608 + * 2. Redistributions in binary form must reproduce the above copyright
17609 + * notice, this list of conditions and the following disclaimer in the
17610 + * documentation and/or other materials provided with the distribution.
17612 + * 3. Neither the name of JANET(UK) nor the names of its contributors
17613 + * may be used to endorse or promote products derived from this software
17614 + * without specific prior written permission.
17616 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17617 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17618 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17619 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17620 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17621 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17622 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17623 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17624 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17625 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17630 + * General mechanism utility routines.
17633 +#include "gssapiP_eap.h"
17636 + * 1.3.6.1.4.1.5322(padl)
17639 + * eap-aes128-cts-hmac-sha1-96(17)
17640 + * eap-aes256-cts-hmac-sha1-96(18)
17642 + * apiExtensions(3)
17643 + * inquireSecContextByOid(1)
17644 + * inquireCredByOid(2)
17645 + * setSecContextOption(3)
17646 + * setCredOption(4)
17651 + * Note: the enctype-less OID is used as the mechanism OID in non-
17652 + * canonicalized exported names.
17654 +static gss_OID_desc gssEapMechOids[] = {
17655 + /* 1.3.6.1.4.1.5322.22.1 */
17656 + { 9, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01" },
17657 + /* 1.3.6.1.4.1.5322.22.1.17 */
17658 + { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x11" },
17659 + /* 1.3.6.1.4.1.5322.22.1.18 */
17660 + { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x12" }
17663 +gss_OID GSS_EAP_MECHANISM = &gssEapMechOids[0];
17664 +gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[1];
17665 +gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[2];
17668 +internalizeOid(const gss_OID oid,
17669 + gss_OID *const pInternalizedOid);
17672 + * Returns TRUE is the OID is a concrete mechanism OID, that is, one
17673 + * with a Kerberos enctype as the last element.
17676 +gssEapIsConcreteMechanismOid(const gss_OID oid)
17678 + return oid->length > GSS_EAP_MECHANISM->length &&
17679 + memcmp(oid->elements, GSS_EAP_MECHANISM->elements,
17680 + GSS_EAP_MECHANISM->length) == 0;
17684 +gssEapIsMechanismOid(const gss_OID oid)
17686 + return oid == GSS_C_NO_OID ||
17687 + oidEqual(oid, GSS_EAP_MECHANISM) ||
17688 + gssEapIsConcreteMechanismOid(oid);
17692 + * Validate that all elements are concrete mechanism OIDs.
17695 +gssEapValidateMechs(OM_uint32 *minor,
17696 + const gss_OID_set mechs)
17702 + if (mechs == GSS_C_NO_OID_SET) {
17703 + return GSS_S_COMPLETE;
17706 + for (i = 0; i < mechs->count; i++) {
17707 + gss_OID oid = &mechs->elements[i];
17709 + if (!gssEapIsConcreteMechanismOid(oid)) {
17710 + *minor = GSSEAP_WRONG_MECH;
17711 + return GSS_S_BAD_MECH;
17715 + return GSS_S_COMPLETE;
17719 +gssEapOidToEnctype(OM_uint32 *minor,
17720 + const gss_OID oid,
17721 + krb5_enctype *enctype)
17726 + major = decomposeOid(minor,
17727 + GSS_EAP_MECHANISM->elements,
17728 + GSS_EAP_MECHANISM->length,
17731 + if (major == GSS_S_COMPLETE)
17732 + *enctype = suffix;
17738 +gssEapEnctypeToOid(OM_uint32 *minor,
17739 + krb5_enctype enctype,
17747 + oid = (gss_OID)GSSEAP_MALLOC(sizeof(*oid));
17748 + if (oid == NULL) {
17750 + return GSS_S_FAILURE;
17753 + oid->length = GSS_EAP_MECHANISM->length + 1;
17754 + oid->elements = GSSEAP_MALLOC(oid->length);
17755 + if (oid->elements == NULL) {
17757 + GSSEAP_FREE(oid);
17758 + return GSS_S_FAILURE;
17761 + major = composeOid(minor,
17762 + GSS_EAP_MECHANISM->elements,
17763 + GSS_EAP_MECHANISM->length,
17766 + if (major == GSS_S_COMPLETE) {
17767 + internalizeOid(oid, pOid);
17770 + GSSEAP_FREE(oid->elements);
17771 + GSSEAP_FREE(oid);
17778 +gssEapIndicateMechs(OM_uint32 *minor,
17779 + gss_OID_set *mechs)
17781 + krb5_context krbContext;
17783 + krb5_enctype *etypes;
17786 + GSSEAP_KRB_INIT(&krbContext);
17788 + *minor = krb5_get_permitted_enctypes(krbContext, &etypes);
17789 + if (*minor != 0) {
17790 + return GSS_S_FAILURE;
17793 + major = gss_create_empty_oid_set(minor, mechs);
17794 + if (GSS_ERROR(major)) {
17795 + GSSEAP_FREE(etypes);
17799 + for (i = 0; etypes[i] != ENCTYPE_NULL; i++) {
17801 +#ifndef HAVE_HEIMDAL_VERSION
17802 + OM_uint32 tmpMinor;
17805 + /* XXX currently we aren't equipped to encode these enctypes */
17806 + if (etypes[i] < 0 || etypes[i] > 127)
17809 + major = gssEapEnctypeToOid(minor, etypes[i], &mechOid);
17810 + if (GSS_ERROR(major))
17813 + major = gss_add_oid_set_member(minor, mechOid, mechs);
17814 + if (GSS_ERROR(major))
17817 +#ifndef HAVE_HEIMDAL_VERSION
17818 + gss_release_oid(&tmpMinor, &mechOid);
17822 + GSSEAP_FREE(etypes);
17829 +gssEapDefaultMech(OM_uint32 *minor,
17832 + gss_OID_set mechs;
17833 + OM_uint32 major, tmpMinor;
17835 + major = gssEapIndicateMechs(minor, &mechs);
17836 + if (GSS_ERROR(major)) {
17840 + if (mechs->count == 0) {
17841 + gss_release_oid_set(&tmpMinor, &mechs);
17842 + return GSS_S_BAD_MECH;
17845 + if (!internalizeOid(&mechs->elements[0], oid)) {
17846 + /* don't double-free if we didn't internalize it */
17847 + mechs->elements[0].length = 0;
17848 + mechs->elements[0].elements = NULL;
17851 + gss_release_oid_set(&tmpMinor, &mechs);
17854 + return GSS_S_COMPLETE;
17858 +internalizeOid(const gss_OID oid,
17859 + gss_OID *const pInternalizedOid)
17863 + *pInternalizedOid = GSS_C_NO_OID;
17866 + i < sizeof(gssEapMechOids) / sizeof(gssEapMechOids[0]);
17868 + if (oidEqual(oid, &gssEapMechOids[i])) {
17869 + *pInternalizedOid = (const gss_OID)&gssEapMechOids[i];
17874 + if (*pInternalizedOid == GSS_C_NO_OID) {
17875 + if (oidEqual(oid, GSS_EAP_NT_EAP_NAME))
17876 + *pInternalizedOid = (const gss_OID)GSS_EAP_NT_EAP_NAME;
17879 + if (*pInternalizedOid == GSS_C_NO_OID) {
17880 + *pInternalizedOid = oid;
17888 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid)
17890 + gss_OID internalizedOid = GSS_C_NO_OID;
17894 + if (internalizeOid(*oid, &internalizedOid)) {
17895 + /* OID was internalized, so we can mark it as "freed" */
17896 + *oid = GSS_C_NO_OID;
17897 + return GSS_S_COMPLETE;
17900 + /* we don't know about this OID */
17901 + return GSS_S_CONTINUE_NEEDED;
17905 +gssEapCanonicalizeOid(OM_uint32 *minor,
17906 + const gss_OID oid,
17911 + int mapToNull = 0;
17913 + major = GSS_S_COMPLETE;
17915 + *pOid = GSS_C_NULL_OID;
17917 + if (oid == GSS_C_NULL_OID) {
17918 + if ((flags & OID_FLAG_NULL_VALID) == 0) {
17919 + *minor = GSSEAP_WRONG_MECH;
17920 + return GSS_S_BAD_MECH;
17921 + } else if (flags & OID_FLAG_MAP_NULL_TO_DEFAULT_MECH) {
17922 + return gssEapDefaultMech(minor, pOid);
17926 + } else if (oidEqual(oid, GSS_EAP_MECHANISM)) {
17927 + if ((flags & OID_FLAG_FAMILY_MECH_VALID) == 0) {
17928 + *minor = GSSEAP_WRONG_MECH;
17929 + return GSS_S_BAD_MECH;
17930 + } else if (flags & OID_FLAG_MAP_FAMILY_MECH_TO_NULL) {
17933 + } else if (!gssEapIsConcreteMechanismOid(oid)) {
17934 + *minor = GSSEAP_WRONG_MECH;
17935 + return GSS_S_BAD_MECH;
17938 + if (!mapToNull) {
17939 + if (!internalizeOid(oid, pOid))
17940 + major = duplicateOid(minor, oid, pOid);
17946 +static gss_buffer_desc gssEapSaslMechs[] = {
17947 + { sizeof("EAP") - 1, "EAP", }, /* not used */
17948 + { sizeof("EAP-AES128") - 1, "EAP-AES128" },
17949 + { sizeof("EAP-AES256") - 1, "EAP-AES256" },
17953 +gssEapOidToSaslName(const gss_OID oid)
17957 + for (i = 1; i < sizeof(gssEapMechOids)/sizeof(gssEapMechOids[0]); i++) {
17958 + if (oidEqual(&gssEapMechOids[i], oid))
17959 + return &gssEapSaslMechs[i];
17962 + return GSS_C_NO_BUFFER;
17966 +gssEapSaslNameToOid(const gss_buffer_t name)
17970 + for (i = 1; i < sizeof(gssEapSaslMechs)/sizeof(gssEapSaslMechs[0]); i++) {
17971 + if (bufferEqual(&gssEapSaslMechs[i], name))
17972 + return &gssEapMechOids[i];
17975 + return GSS_C_NO_OID;
17977 diff --git a/mech_eap/util_moonshot.c b/mech_eap/util_moonshot.c
17978 new file mode 100644
17979 index 0000000..dc0c35e
17981 +++ b/mech_eap/util_moonshot.c
17984 + * Copyright (c) 2011, JANET(UK)
17985 + * All rights reserved.
17987 + * Redistribution and use in source and binary forms, with or without
17988 + * modification, are permitted provided that the following conditions
17991 + * 1. Redistributions of source code must retain the above copyright
17992 + * notice, this list of conditions and the following disclaimer.
17994 + * 2. Redistributions in binary form must reproduce the above copyright
17995 + * notice, this list of conditions and the following disclaimer in the
17996 + * documentation and/or other materials provided with the distribution.
17998 + * 3. Neither the name of JANET(UK) nor the names of its contributors
17999 + * may be used to endorse or promote products derived from this software
18000 + * without specific prior written permission.
18002 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18003 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18004 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18005 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18006 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18007 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18008 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18009 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18010 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18011 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18015 +#include "gssapiP_eap.h"
18017 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
18018 +#include <libmoonshot.h>
18021 +libMoonshotMapError(OM_uint32 *minor,
18022 + MoonshotError **pError)
18024 + MoonshotError *error = *pError;
18026 + GSSEAP_ASSERT(error != NULL);
18028 + switch (error->code) {
18029 + case MOONSHOT_ERROR_UNABLE_TO_START_SERVICE:
18030 + *minor = GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE;
18032 + case MOONSHOT_ERROR_NO_IDENTITY_SELECTED:
18033 + *minor = GSSEAP_NO_IDENTITY_SELECTED;
18035 + case MOONSHOT_ERROR_INSTALLATION_ERROR:
18036 + *minor = GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR;
18038 + case MOONSHOT_ERROR_OS_ERROR:
18039 + *minor = GSSEAP_IDENTITY_SERVICE_OS_ERROR;
18041 + case MOONSHOT_ERROR_IPC_ERROR:
18042 + *minor = GSSEAP_IDENTITY_SERVICE_IPC_ERROR;
18045 + *minor = GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR;
18049 + gssEapSaveStatusInfo(*minor, error->message);
18050 + moonshot_error_free(error);
18053 + return GSS_S_CRED_UNAVAIL;
18057 +libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
18058 + const gss_cred_id_t cred,
18059 + gss_name_t *pName)
18061 + OM_uint32 major, tmpMinor;
18062 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
18063 + gss_name_t name = GSS_C_NO_NAME;
18064 + gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
18065 + char *nai = NULL;
18066 + char *password = NULL;
18067 + char *serverCertificateHash = NULL;
18068 + char *caCertificate = NULL;
18069 + char *subjectNameConstraint = NULL;
18070 + char *subjectAltNameConstraint = NULL;
18071 + MoonshotError *error = NULL;
18073 + *pName = GSS_C_NO_NAME;
18075 + if (!moonshot_get_default_identity(&nai,
18077 + &serverCertificateHash,
18079 + &subjectNameConstraint,
18080 + &subjectAltNameConstraint,
18082 + if (error->code == MOONSHOT_ERROR_NO_IDENTITY_SELECTED) {
18083 + major = GSS_S_CRED_UNAVAIL;
18084 + *minor = GSSEAP_NO_DEFAULT_IDENTITY;
18085 + moonshot_error_free(error);
18087 + major = libMoonshotMapError(minor, &error);
18091 + tmpBuffer.value = nai;
18092 + tmpBuffer.length = strlen(nai);
18094 + major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME, nameMech, &name);
18095 + if (GSS_ERROR(major))
18099 + name = GSS_C_NO_NAME;
18102 + moonshot_free(nai);
18103 + moonshot_free(password);
18104 + moonshot_free(serverCertificateHash);
18105 + moonshot_free(caCertificate);
18106 + moonshot_free(subjectNameConstraint);
18107 + moonshot_free(subjectAltNameConstraint);
18109 + gssEapReleaseName(&tmpMinor, &name);
18115 +libMoonshotResolveInitiatorCred(OM_uint32 *minor,
18116 + gss_cred_id_t cred,
18117 + const gss_name_t targetName)
18119 + OM_uint32 major, tmpMinor;
18120 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
18121 + gss_buffer_desc initiator = GSS_C_EMPTY_BUFFER;
18122 + gss_buffer_desc target = GSS_C_EMPTY_BUFFER;
18123 + gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
18124 + char *nai = NULL;
18125 + char *password = NULL;
18126 + char *serverCertificateHash = NULL;
18127 + char *caCertificate = NULL;
18128 + char *subjectNameConstraint = NULL;
18129 + char *subjectAltNameConstraint = NULL;
18130 + MoonshotError *error = NULL;
18132 + if (cred->name != GSS_C_NO_NAME) {
18133 + major = gssEapExportName(minor, cred->name, &initiator);
18134 + if (GSS_ERROR(major))
18138 + if (targetName != GSS_C_NO_NAME) {
18139 + major = gssEapExportName(minor, targetName, &target);
18140 + if (GSS_ERROR(major))
18144 + if (!moonshot_get_identity((const char *)initiator.value,
18145 + (const char *)cred->password.value,
18146 + (const char *)target.value,
18149 + &serverCertificateHash,
18151 + &subjectNameConstraint,
18152 + &subjectAltNameConstraint,
18154 + major = libMoonshotMapError(minor, &error);
18158 + gssEapReleaseName(&tmpMinor, &cred->name);
18160 + tmpBuffer.value = nai;
18161 + tmpBuffer.length = strlen(nai);
18163 + major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME,
18164 + nameMech, &cred->name);
18165 + if (GSS_ERROR(major))
18168 + tmpBuffer.value = password;
18169 + tmpBuffer.length = strlen(password);
18171 + major = gssEapSetCredPassword(minor, cred, &tmpBuffer);
18172 + if (GSS_ERROR(major))
18175 + gss_release_buffer(&tmpMinor, &cred->caCertificate);
18176 + gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
18177 + gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
18179 + if (serverCertificateHash != NULL) {
18180 + size_t len = strlen(serverCertificateHash);
18182 + #define HASH_PREFIX "hash://server/sha256/"
18183 + #define HASH_PREFIX_LEN (sizeof(HASH_PREFIX) - 1)
18185 + cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
18186 + if (cred->caCertificate.value == NULL) {
18187 + major = GSS_S_FAILURE;
18192 + memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
18193 + memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
18195 + ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
18197 + cred->caCertificate.length = HASH_PREFIX_LEN + len;
18198 + } else if (caCertificate != NULL) {
18199 + makeStringBufferOrCleanup(caCertificate, &cred->caCertificate);
18202 + if (subjectNameConstraint != NULL)
18203 + makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
18204 + if (subjectAltNameConstraint != NULL)
18205 + makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
18208 + moonshot_free(nai);
18209 + moonshot_free(password);
18210 + moonshot_free(serverCertificateHash);
18211 + moonshot_free(caCertificate);
18212 + moonshot_free(subjectNameConstraint);
18213 + moonshot_free(subjectAltNameConstraint);
18215 + gss_release_buffer(&tmpMinor, &initiator);
18216 + gss_release_buffer(&tmpMinor, &target);
18220 +#endif /* HAVE_MOONSHOT_GET_IDENTITY */
18221 diff --git a/mech_eap/util_name.c b/mech_eap/util_name.c
18222 new file mode 100644
18223 index 0000000..6045724
18225 +++ b/mech_eap/util_name.c
18228 + * Copyright (c) 2011, JANET(UK)
18229 + * All rights reserved.
18231 + * Redistribution and use in source and binary forms, with or without
18232 + * modification, are permitted provided that the following conditions
18235 + * 1. Redistributions of source code must retain the above copyright
18236 + * notice, this list of conditions and the following disclaimer.
18238 + * 2. Redistributions in binary form must reproduce the above copyright
18239 + * notice, this list of conditions and the following disclaimer in the
18240 + * documentation and/or other materials provided with the distribution.
18242 + * 3. Neither the name of JANET(UK) nor the names of its contributors
18243 + * may be used to endorse or promote products derived from this software
18244 + * without specific prior written permission.
18246 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18247 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18248 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18249 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18250 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18251 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18252 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18253 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18254 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18255 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18259 + * Portions Copyright 2009 by the Massachusetts Institute of Technology.
18260 + * All Rights Reserved.
18262 + * Export of this software from the United States of America may
18263 + * require a specific license from the United States Government.
18264 + * It is the responsibility of any person or organization contemplating
18265 + * export to obtain such a license before exporting.
18267 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18268 + * distribute this software and its documentation for any purpose and
18269 + * without fee is hereby granted, provided that the above copyright
18270 + * notice appear in all copies and that both that copyright notice and
18271 + * this permission notice appear in supporting documentation, and that
18272 + * the name of M.I.T. not be used in advertising or publicity pertaining
18273 + * to distribution of the software without specific, written prior
18274 + * permission. Furthermore if you modify this software you must label
18275 + * your software as modified software and not distribute it in such a
18276 + * fashion that it might be confused with the original M.I.T. software.
18277 + * M.I.T. makes no representations about the suitability of
18278 + * this software for any purpose. It is provided "as is" without express
18279 + * or implied warranty.
18283 + * Name utility routines.
18286 +#include "gssapiP_eap.h"
18288 +static gss_OID_desc gssEapNtEapName = {
18289 + /* 1.3.6.1.4.1.5322.22.2.1 */
18290 + 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x02\x01"
18293 +gss_OID GSS_EAP_NT_EAP_NAME = &gssEapNtEapName;
18296 +gssEapAllocName(OM_uint32 *minor, gss_name_t *pName)
18298 + OM_uint32 tmpMinor;
18301 + *pName = GSS_C_NO_NAME;
18303 + name = (gss_name_t)GSSEAP_CALLOC(1, sizeof(*name));
18304 + if (name == NULL) {
18306 + return GSS_S_FAILURE;
18309 + if (GSSEAP_MUTEX_INIT(&name->mutex) != 0) {
18310 + *minor = GSSEAP_GET_LAST_ERROR();
18311 + gssEapReleaseName(&tmpMinor, &name);
18312 + return GSS_S_FAILURE;
18317 + return GSS_S_COMPLETE;
18321 +gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName)
18324 + krb5_context krbContext = NULL;
18325 + OM_uint32 tmpMinor;
18329 + if (pName == NULL) {
18330 + return GSS_S_COMPLETE;
18334 + if (name == GSS_C_NO_NAME) {
18335 + return GSS_S_COMPLETE;
18338 + GSSEAP_KRB_INIT(&krbContext);
18339 + krb5_free_principal(krbContext, name->krbPrincipal);
18340 + gssEapReleaseOid(&tmpMinor, &name->mechanismUsed);
18341 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18342 + gssEapReleaseAttrContext(&tmpMinor, name);
18345 + GSSEAP_MUTEX_DESTROY(&name->mutex);
18346 + GSSEAP_FREE(name);
18349 + return GSS_S_COMPLETE;
18353 +krbPrincipalToName(OM_uint32 *minor,
18354 + krb5_principal *principal,
18355 + gss_name_t *pName)
18360 + major = gssEapAllocName(minor, &name);
18361 + if (GSS_ERROR(major))
18364 + name->krbPrincipal = *principal;
18365 + *principal = NULL;
18367 + if (KRB_PRINC_LENGTH(name->krbPrincipal) > 1) {
18368 + name->flags |= NAME_FLAG_SERVICE;
18370 + name->flags |= NAME_FLAG_NAI;
18376 + return GSS_S_COMPLETE;
18380 +gssEapGetDefaultRealm(krb5_context krbContext)
18382 + char *defaultRealm = NULL;
18384 + krb5_appdefault_string(krbContext, "eap_gss",
18385 + NULL, "default_realm", "", &defaultRealm);
18387 + return defaultRealm;
18391 +importServiceName(OM_uint32 *minor,
18392 + const gss_buffer_t nameBuffer,
18393 + gss_name_t *pName)
18396 + krb5_error_code code;
18397 + krb5_context krbContext;
18398 + krb5_principal krbPrinc;
18399 + char *service, *host, *realm = NULL;
18401 + GSSEAP_KRB_INIT(&krbContext);
18403 + major = bufferToString(minor, nameBuffer, &service);
18404 + if (GSS_ERROR(major))
18407 + host = strchr(service, '@');
18408 + if (host != NULL) {
18413 + realm = gssEapGetDefaultRealm(krbContext);
18415 + code = krb5_build_principal(krbContext,
18417 + realm != NULL ? strlen(realm) : 0,
18418 + realm != NULL ? realm : "",
18424 + KRB_PRINC_TYPE(krbPrinc) = KRB5_NT_SRV_HST;
18426 + major = krbPrincipalToName(minor, &krbPrinc, pName);
18427 + if (GSS_ERROR(major))
18428 + krb5_free_principal(krbContext, krbPrinc);
18430 + major = GSS_S_FAILURE;
18431 + *minor = GSSEAP_BAD_SERVICE_NAME;
18434 + if (realm != NULL)
18435 + krb5_free_default_realm(krbContext, realm);
18436 + GSSEAP_FREE(service);
18441 +#define IMPORT_FLAG_DEFAULT_REALM 0x1
18444 + * Import an EAP name, possibly appending the default GSS EAP realm,
18447 +importEapNameFlags(OM_uint32 *minor,
18448 + const gss_buffer_t nameBuffer,
18449 + OM_uint32 importFlags,
18450 + gss_name_t *pName)
18453 + krb5_context krbContext;
18454 + krb5_principal krbPrinc = NULL;
18455 + krb5_error_code code;
18456 + char *nameString;
18458 + GSSEAP_KRB_INIT(&krbContext);
18460 + if (nameBuffer == GSS_C_NO_BUFFER) {
18462 + code = KRB5_PARSE_MALFORMED;
18464 + major = bufferToString(minor, nameBuffer, &nameString);
18465 + if (GSS_ERROR(major))
18469 + * First, attempt to parse the name on the assumption that it includes
18470 + * a qualifying realm. This allows us to avoid accidentally appending
18471 + * the default Kerberos realm to an unqualified name. (A bug in MIT
18472 + * Kerberos prevents the default realm being set to an empty value.)
18474 + code = krb5_parse_name_flags(krbContext, nameString,
18475 + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &krbPrinc);
18478 + if (code == KRB5_PARSE_MALFORMED) {
18479 + char *defaultRealm = NULL;
18480 + int parseFlags = 0;
18482 + /* Possibly append the default EAP realm if required */
18483 + if (importFlags & IMPORT_FLAG_DEFAULT_REALM)
18484 + defaultRealm = gssEapGetDefaultRealm(krbContext);
18486 + /* If no default realm, leave the realm empty in the parsed name */
18487 + if (defaultRealm == NULL || defaultRealm[0] == '\0')
18488 + parseFlags |= KRB5_PRINCIPAL_PARSE_NO_REALM;
18490 + code = krb5_parse_name_flags(krbContext, nameString, parseFlags, &krbPrinc);
18492 +#ifdef HAVE_HEIMDAL_VERSION
18493 + if (code == 0 && KRB_PRINC_REALM(krbPrinc) == NULL) {
18494 + KRB_PRINC_REALM(krbPrinc) = KRB_CALLOC(1, sizeof(char));
18495 + if (KRB_PRINC_REALM(krbPrinc) == NULL)
18500 + if (defaultRealm != NULL)
18501 + krb5_free_default_realm(krbContext, defaultRealm);
18504 + if (nameBuffer != GSS_C_NO_BUFFER)
18505 + GSSEAP_FREE(nameString);
18509 + return GSS_S_FAILURE;
18512 + GSSEAP_ASSERT(krbPrinc != NULL);
18514 + major = krbPrincipalToName(minor, &krbPrinc, pName);
18515 + if (GSS_ERROR(major))
18516 + krb5_free_principal(krbContext, krbPrinc);
18522 +importEapName(OM_uint32 *minor,
18523 + const gss_buffer_t nameBuffer,
18524 + gss_name_t *pName)
18526 + return importEapNameFlags(minor, nameBuffer, 0, pName);
18530 +importUserName(OM_uint32 *minor,
18531 + const gss_buffer_t nameBuffer,
18532 + gss_name_t *pName)
18534 + return importEapNameFlags(minor, nameBuffer, IMPORT_FLAG_DEFAULT_REALM, pName);
18538 +importAnonymousName(OM_uint32 *minor,
18539 + const gss_buffer_t nameBuffer GSSEAP_UNUSED,
18540 + gss_name_t *pName)
18542 + return importEapNameFlags(minor, GSS_C_NO_BUFFER, 0, pName);
18545 +#define UPDATE_REMAIN(n) do { \
18550 +#define CHECK_REMAIN(n) do { \
18551 + if (remain < (n)) { \
18552 + major = GSS_S_BAD_NAME; \
18553 + *minor = GSSEAP_TOK_TRUNC; \
18559 +gssEapImportNameInternal(OM_uint32 *minor,
18560 + const gss_buffer_t nameBuffer,
18561 + gss_name_t *pName,
18564 + OM_uint32 major, tmpMinor;
18565 + krb5_context krbContext;
18566 + unsigned char *p;
18567 + size_t len, remain;
18568 + gss_buffer_desc buf;
18569 + gss_name_t name = GSS_C_NO_NAME;
18570 + gss_OID mechanismUsed = GSS_C_NO_OID;
18572 + GSSEAP_KRB_INIT(&krbContext);
18574 + p = (unsigned char *)nameBuffer->value;
18575 + remain = nameBuffer->length;
18577 + if (flags & EXPORT_NAME_FLAG_OID) {
18578 + gss_OID_desc mech;
18579 + enum gss_eap_token_type tokType;
18580 + uint16_t wireTokType;
18582 + /* TOK_ID || MECH_OID_LEN || MECH_OID */
18583 + if (remain < 6) {
18584 + *minor = GSSEAP_BAD_NAME_TOKEN;
18585 + return GSS_S_BAD_NAME;
18588 + if (flags & EXPORT_NAME_FLAG_COMPOSITE)
18589 + tokType = TOK_TYPE_EXPORT_NAME_COMPOSITE;
18591 + tokType = TOK_TYPE_EXPORT_NAME;
18594 + wireTokType = load_uint16_be(p);
18596 + if ((flags & EXPORT_NAME_FLAG_ALLOW_COMPOSITE) &&
18597 + wireTokType == TOK_TYPE_EXPORT_NAME_COMPOSITE) {
18598 + tokType = TOK_TYPE_EXPORT_NAME_COMPOSITE;
18599 + flags |= EXPORT_NAME_FLAG_COMPOSITE;
18602 + if (wireTokType != tokType) {
18603 + *minor = GSSEAP_WRONG_TOK_ID;
18604 + return GSS_S_BAD_NAME;
18606 + UPDATE_REMAIN(2);
18608 + /* MECH_OID_LEN */
18609 + len = load_uint16_be(p);
18611 + *minor = GSSEAP_BAD_NAME_TOKEN;
18612 + return GSS_S_BAD_NAME;
18614 + UPDATE_REMAIN(2);
18617 + if (p[0] != 0x06) {
18618 + *minor = GSSEAP_BAD_NAME_TOKEN;
18619 + return GSS_S_BAD_NAME;
18622 + mech.length = p[1];
18623 + mech.elements = &p[2];
18625 + CHECK_REMAIN(mech.length);
18627 + major = gssEapCanonicalizeOid(minor,
18629 + OID_FLAG_FAMILY_MECH_VALID |
18630 + OID_FLAG_MAP_FAMILY_MECH_TO_NULL,
18632 + if (GSS_ERROR(major))
18635 + UPDATE_REMAIN(2 + mech.length);
18640 + len = load_uint32_be(p);
18641 + UPDATE_REMAIN(4);
18644 + CHECK_REMAIN(len);
18645 + buf.length = len;
18647 + UPDATE_REMAIN(len);
18649 + major = importEapNameFlags(minor, &buf, 0, &name);
18650 + if (GSS_ERROR(major))
18653 + name->mechanismUsed = mechanismUsed;
18654 + mechanismUsed = GSS_C_NO_OID;
18656 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18657 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18658 + gss_buffer_desc buf;
18660 + buf.length = remain;
18663 + major = gssEapImportAttrContext(minor, &buf, name);
18664 + if (GSS_ERROR(major))
18669 + major = GSS_S_COMPLETE;
18673 + if (GSS_ERROR(major)) {
18674 + gssEapReleaseOid(&tmpMinor, &mechanismUsed);
18675 + gssEapReleaseName(&tmpMinor, &name);
18684 +importExportName(OM_uint32 *minor,
18685 + const gss_buffer_t nameBuffer,
18686 + gss_name_t *name)
18688 + return gssEapImportNameInternal(minor, nameBuffer, name,
18689 + EXPORT_NAME_FLAG_OID |
18690 + EXPORT_NAME_FLAG_ALLOW_COMPOSITE);
18693 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
18695 +importCompositeExportName(OM_uint32 *minor,
18696 + const gss_buffer_t nameBuffer,
18697 + gss_name_t *name)
18699 + return gssEapImportNameInternal(minor, nameBuffer, name,
18700 + EXPORT_NAME_FLAG_OID |
18701 + EXPORT_NAME_FLAG_COMPOSITE);
18705 +struct gss_eap_name_import_provider {
18706 + gss_const_OID oid;
18707 + OM_uint32 (*import)(OM_uint32 *, const gss_buffer_t, gss_name_t *);
18711 +gssEapImportName(OM_uint32 *minor,
18712 + const gss_buffer_t nameBuffer,
18713 + const gss_OID nameType,
18714 + const gss_OID mechType,
18715 + gss_name_t *pName)
18717 + struct gss_eap_name_import_provider nameTypes[] = {
18718 + { GSS_EAP_NT_EAP_NAME, importEapName },
18719 + { GSS_C_NT_USER_NAME, importUserName },
18720 + { GSS_C_NT_HOSTBASED_SERVICE, importServiceName },
18721 + { GSS_C_NT_HOSTBASED_SERVICE_X, importServiceName },
18722 + { GSS_C_NT_ANONYMOUS, importAnonymousName },
18723 + { GSS_C_NT_EXPORT_NAME, importExportName },
18724 + { GSS_KRB5_NT_PRINCIPAL_NAME, importUserName },
18725 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
18726 + { GSS_C_NT_COMPOSITE_EXPORT, importCompositeExportName },
18730 + OM_uint32 major = GSS_S_BAD_NAMETYPE;
18731 + OM_uint32 tmpMinor;
18732 + gss_name_t name = GSS_C_NO_NAME;
18734 + for (i = 0; i < sizeof(nameTypes) / sizeof(nameTypes[0]); i++) {
18735 + if (oidEqual(nameTypes[i].oid,
18736 + nameType == GSS_C_NO_OID ? GSS_EAP_NT_EAP_NAME : nameType)) {
18737 + major = nameTypes[i].import(minor, nameBuffer, &name);
18742 + if (major == GSS_S_COMPLETE &&
18743 + mechType != GSS_C_NO_OID) {
18744 + GSSEAP_ASSERT(gssEapIsConcreteMechanismOid(mechType));
18745 + GSSEAP_ASSERT(name->mechanismUsed == GSS_C_NO_OID);
18747 + major = gssEapCanonicalizeOid(minor, mechType, 0, &name->mechanismUsed);
18750 + if (GSS_ERROR(major))
18751 + gssEapReleaseName(&tmpMinor, &name);
18759 +gssEapExportName(OM_uint32 *minor,
18760 + const gss_name_t name,
18761 + gss_buffer_t exportedName)
18763 + return gssEapExportNameInternal(minor, name, exportedName,
18764 + EXPORT_NAME_FLAG_OID);
18768 +gssEapExportNameInternal(OM_uint32 *minor,
18769 + const gss_name_t name,
18770 + gss_buffer_t exportedName,
18773 + OM_uint32 major = GSS_S_FAILURE, tmpMinor;
18774 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
18775 + size_t exportedNameLen;
18776 + unsigned char *p;
18777 + gss_buffer_desc attrs = GSS_C_EMPTY_BUFFER;
18780 + exportedName->length = 0;
18781 + exportedName->value = NULL;
18783 + if (name->mechanismUsed != GSS_C_NO_OID)
18784 + mech = name->mechanismUsed;
18786 + mech = GSS_EAP_MECHANISM;
18788 + major = gssEapDisplayName(minor, name, &nameBuf, NULL);
18789 + if (GSS_ERROR(major))
18792 + exportedNameLen = 0;
18793 + if (flags & EXPORT_NAME_FLAG_OID) {
18794 + exportedNameLen += 6 + mech->length;
18796 + exportedNameLen += 4 + nameBuf.length;
18797 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18798 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18799 + major = gssEapExportAttrContext(minor, name, &attrs);
18800 + if (GSS_ERROR(major))
18802 + exportedNameLen += attrs.length;
18806 + exportedName->value = GSSEAP_MALLOC(exportedNameLen);
18807 + if (exportedName->value == NULL) {
18808 + major = GSS_S_FAILURE;
18812 + exportedName->length = exportedNameLen;
18814 + p = (unsigned char *)exportedName->value;
18816 + if (flags & EXPORT_NAME_FLAG_OID) {
18817 + /* TOK | MECH_OID_LEN */
18818 + store_uint16_be((flags & EXPORT_NAME_FLAG_COMPOSITE)
18819 + ? TOK_TYPE_EXPORT_NAME_COMPOSITE
18820 + : TOK_TYPE_EXPORT_NAME,
18823 + store_uint16_be(mech->length + 2, p);
18828 + *p++ = mech->length & 0xff;
18829 + memcpy(p, mech->elements, mech->length);
18830 + p += mech->length;
18834 + store_uint32_be(nameBuf.length, p);
18838 + memcpy(p, nameBuf.value, nameBuf.length);
18839 + p += nameBuf.length;
18841 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18842 + memcpy(p, attrs.value, attrs.length);
18843 + p += attrs.length;
18846 + GSSEAP_ASSERT(p == (unsigned char *)exportedName->value + exportedNameLen);
18848 + major = GSS_S_COMPLETE;
18852 + gss_release_buffer(&tmpMinor, &attrs);
18853 + gss_release_buffer(&tmpMinor, &nameBuf);
18854 + if (GSS_ERROR(major))
18855 + gss_release_buffer(&tmpMinor, exportedName);
18861 +gssEapCanonicalizeName(OM_uint32 *minor,
18862 + const gss_name_t input_name,
18863 + const gss_OID mech_type,
18864 + gss_name_t *dest_name)
18866 + OM_uint32 major, tmpMinor;
18867 + krb5_context krbContext;
18869 + gss_OID mech_used;
18871 + if (input_name == GSS_C_NO_NAME) {
18873 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
18876 + GSSEAP_KRB_INIT(&krbContext);
18878 + major = gssEapAllocName(minor, &name);
18879 + if (GSS_ERROR(major)) {
18883 + if (mech_type != GSS_C_NO_OID)
18884 + mech_used = mech_type;
18886 + mech_used = input_name->mechanismUsed;
18888 + major = gssEapCanonicalizeOid(minor,
18890 + OID_FLAG_NULL_VALID,
18891 + &name->mechanismUsed);
18892 + if (GSS_ERROR(major))
18895 + name->flags = input_name->flags;
18897 + *minor = krb5_copy_principal(krbContext, input_name->krbPrincipal,
18898 + &name->krbPrincipal);
18899 + if (*minor != 0) {
18900 + major = GSS_S_FAILURE;
18904 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18905 + if (input_name->attrCtx != NULL) {
18906 + major = gssEapDuplicateAttrContext(minor, input_name, name);
18907 + if (GSS_ERROR(major))
18912 + *dest_name = name;
18915 + if (GSS_ERROR(major)) {
18916 + gssEapReleaseName(&tmpMinor, &name);
18923 +gssEapDuplicateName(OM_uint32 *minor,
18924 + const gss_name_t input_name,
18925 + gss_name_t *dest_name)
18927 + return gssEapCanonicalizeName(minor, input_name,
18928 + GSS_C_NO_OID, dest_name);
18932 +gssEapDisplayName(OM_uint32 *minor,
18934 + gss_buffer_t output_name_buffer,
18935 + gss_OID *output_name_type)
18938 + krb5_context krbContext;
18940 + gss_OID name_type;
18943 + GSSEAP_KRB_INIT(&krbContext);
18945 + output_name_buffer->length = 0;
18946 + output_name_buffer->value = NULL;
18948 + if (name == GSS_C_NO_NAME) {
18950 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
18954 + * According to draft-ietf-abfab-gss-eap-01, when the realm is
18955 + * absent the trailing '@' is not included.
18957 +#ifdef HAVE_HEIMDAL_VERSION
18958 + if (KRB_PRINC_REALM(name->krbPrincipal) == NULL ||
18959 + KRB_PRINC_REALM(name->krbPrincipal)[0] == '\0')
18961 + if (KRB_PRINC_REALM(name->krbPrincipal)->length == 0)
18963 + flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
18965 + *minor = krb5_unparse_name_flags(krbContext, name->krbPrincipal,
18966 + flags, &krbName);
18967 + if (*minor != 0) {
18968 + return GSS_S_FAILURE;
18971 + major = makeStringBuffer(minor, krbName, output_name_buffer);
18972 + if (GSS_ERROR(major)) {
18973 + krb5_free_unparsed_name(krbContext, krbName);
18977 + krb5_free_unparsed_name(krbContext, krbName);
18979 + if (output_name_buffer->length == 0) {
18980 + name_type = GSS_C_NT_ANONYMOUS;
18981 + } else if (name->flags & NAME_FLAG_NAI) {
18982 + name_type = GSS_C_NT_USER_NAME;
18984 + name_type = GSS_EAP_NT_EAP_NAME;
18987 + if (output_name_type != NULL)
18988 + *output_name_type = name_type;
18990 + return GSS_S_COMPLETE;
18994 +gssEapCompareName(OM_uint32 *minor,
18995 + gss_name_t name1,
18996 + gss_name_t name2,
18999 + krb5_context krbContext;
19003 + if (name1 == GSS_C_NO_NAME && name2 == GSS_C_NO_NAME) {
19005 + } else if (name1 != GSS_C_NO_NAME && name2 != GSS_C_NO_NAME) {
19006 + GSSEAP_KRB_INIT(&krbContext);
19008 + /* krbPrincipal is immutable, so lock not required */
19009 + *name_equal = krb5_principal_compare(krbContext,
19010 + name1->krbPrincipal,
19011 + name2->krbPrincipal);
19014 + return GSS_S_COMPLETE;
19016 diff --git a/mech_eap/util_oid.c b/mech_eap/util_oid.c
19017 new file mode 100644
19018 index 0000000..096c9f8
19020 +++ b/mech_eap/util_oid.c
19023 + * Copyright (c) 2011, JANET(UK)
19024 + * All rights reserved.
19026 + * Redistribution and use in source and binary forms, with or without
19027 + * modification, are permitted provided that the following conditions
19030 + * 1. Redistributions of source code must retain the above copyright
19031 + * notice, this list of conditions and the following disclaimer.
19033 + * 2. Redistributions in binary form must reproduce the above copyright
19034 + * notice, this list of conditions and the following disclaimer in the
19035 + * documentation and/or other materials provided with the distribution.
19037 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19038 + * may be used to endorse or promote products derived from this software
19039 + * without specific prior written permission.
19041 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19042 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19043 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19044 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19045 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19046 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19047 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19048 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19049 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19050 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19054 + * Copyright 1995-2010 by the Massachusetts Institute of Technology.
19055 + * All Rights Reserved.
19057 + * Export of this software from the United States of America may
19058 + * require a specific license from the United States Government.
19059 + * It is the responsibility of any person or organization contemplating
19060 + * export to obtain such a license before exporting.
19062 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19063 + * distribute this software and its documentation for any purpose and
19064 + * without fee is hereby granted, provided that the above copyright
19065 + * notice appear in all copies and that both that copyright notice and
19066 + * this permission notice appear in supporting documentation, and that
19067 + * the name of M.I.T. not be used in advertising or publicity pertaining
19068 + * to distribution of the software without specific, written prior
19069 + * permission. Furthermore if you modify this software you must label
19070 + * your software as modified software and not distribute it in such a
19071 + * fashion that it might be confused with the original M.I.T. software.
19072 + * M.I.T. makes no representations about the suitability of
19073 + * this software for any purpose. It is provided "as is" without express
19074 + * or implied warranty.
19079 + * OID utility routines.
19082 +#include "gssapiP_eap.h"
19085 +duplicateOid(OM_uint32 *minor,
19086 + const gss_OID_desc * const oid,
19091 + *newOid = GSS_C_NO_OID;
19093 + p = (gss_OID)GSSEAP_MALLOC(sizeof(*p));
19096 + return GSS_S_FAILURE;
19098 + p->length = oid->length;
19099 + p->elements = GSSEAP_MALLOC(p->length);
19100 + if (p->elements == NULL) {
19103 + return GSS_S_FAILURE;
19106 + memcpy(p->elements, oid->elements, p->length);
19110 + return GSS_S_COMPLETE;
19113 +/* Compose an OID of a prefix and an integer suffix */
19115 +composeOid(OM_uint32 *minor,
19116 + const char *prefix,
19117 + size_t prefix_len,
19119 + gss_OID_desc *oid)
19123 + unsigned char *op;
19125 + if (oid == GSS_C_NO_OID) {
19127 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_FAILURE;
19130 + if (oid->length < prefix_len) {
19131 + *minor = GSSEAP_WRONG_SIZE;
19132 + return GSS_S_FAILURE;
19135 + memcpy(oid->elements, prefix, prefix_len);
19138 + osuffix = suffix;
19143 + suffix = osuffix;
19145 + if (oid->length < prefix_len + nbytes) {
19146 + *minor = GSSEAP_WRONG_SIZE;
19147 + return GSS_S_FAILURE;
19150 + op = (unsigned char *) oid->elements + prefix_len + nbytes;
19153 + op[i] = (unsigned char)suffix & 0x7f;
19160 + oid->length = prefix_len + nbytes;
19163 + return GSS_S_COMPLETE;
19167 +decomposeOid(OM_uint32 *minor,
19168 + const char *prefix,
19169 + size_t prefix_len,
19170 + gss_OID_desc *oid,
19174 + unsigned char *op;
19176 + if (oid->length < prefix_len ||
19177 + memcmp(oid->elements, prefix, prefix_len) != 0) {
19178 + return GSS_S_BAD_MECH;
19181 + op = (unsigned char *) oid->elements + prefix_len;
19185 + slen = oid->length - prefix_len;
19187 + for (i = 0; i < slen; i++) {
19188 + *suffix = (*suffix << 7) | (op[i] & 0x7f);
19189 + if (i + 1 != slen && (op[i] & 0x80) == 0) {
19190 + *minor = GSSEAP_WRONG_SIZE;
19191 + return GSS_S_FAILURE;
19195 + return GSS_S_COMPLETE;
19199 +duplicateOidSet(OM_uint32 *minor,
19200 + const gss_OID_set src,
19201 + gss_OID_set *dst)
19203 + OM_uint32 major, tmpMinor;
19206 + if (src == GSS_C_NO_OID_SET) {
19207 + *dst = GSS_C_NO_OID_SET;
19208 + return GSS_S_COMPLETE;
19211 + major = gss_create_empty_oid_set(minor, dst);
19212 + if (GSS_ERROR(major))
19215 + for (i = 0; i < src->count; i++) {
19216 + gss_OID oid = &src->elements[i];
19218 + major = gss_add_oid_set_member(minor, oid, dst);
19219 + if (GSS_ERROR(major))
19223 + if (GSS_ERROR(major))
19224 + gss_release_oid_set(&tmpMinor, dst);
19228 diff --git a/mech_eap/util_ordering.c b/mech_eap/util_ordering.c
19229 new file mode 100644
19230 index 0000000..71ebfb5
19232 +++ b/mech_eap/util_ordering.c
19235 + * Copyright (c) 2011, JANET(UK)
19236 + * All rights reserved.
19238 + * Redistribution and use in source and binary forms, with or without
19239 + * modification, are permitted provided that the following conditions
19242 + * 1. Redistributions of source code must retain the above copyright
19243 + * notice, this list of conditions and the following disclaimer.
19245 + * 2. Redistributions in binary form must reproduce the above copyright
19246 + * notice, this list of conditions and the following disclaimer in the
19247 + * documentation and/or other materials provided with the distribution.
19249 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19250 + * may be used to endorse or promote products derived from this software
19251 + * without specific prior written permission.
19253 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19254 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19255 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19256 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19257 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19258 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19259 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19260 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19261 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19262 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19266 + * Copyright 1993 by OpenVision Technologies, Inc.
19268 + * Permission to use, copy, modify, distribute, and sell this software
19269 + * and its documentation for any purpose is hereby granted without fee,
19270 + * provided that the above copyright notice appears in all copies and
19271 + * that both that copyright notice and this permission notice appear in
19272 + * supporting documentation, and that the name of OpenVision not be used
19273 + * in advertising or publicity pertaining to distribution of the software
19274 + * without specific, written prior permission. OpenVision makes no
19275 + * representations about the suitability of this software for any
19276 + * purpose. It is provided "as is" without express or implied warranty.
19278 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19279 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19280 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19281 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19282 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19283 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19284 + * PERFORMANCE OF THIS SOFTWARE.
19288 + * Functions to check sequence numbers for replay and sequencing
19291 +#include "gssapiP_eap.h"
19293 +#define QUEUE_LENGTH 20
19295 +typedef struct _queue {
19300 + uint64_t firstnum;
19301 + /* Stored as deltas from firstnum. This way, the high bit won't
19302 + overflow unless we've actually gone through 2**n messages, or
19303 + gotten something *way* out of sequence. */
19304 + uint64_t elem[QUEUE_LENGTH];
19305 + /* All ones for 64-bit sequence numbers; 32 ones for 32-bit
19306 + sequence numbers. */
19311 + * - the queue is a circular queue. The first element (q->elem[q->start])
19312 + * is the oldest. The last element is the newest.
19315 +#define QSIZE(q) (sizeof((q)->elem)/sizeof((q)->elem[0]))
19316 +#define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)])
19319 +queue_insert(queue *q, int after, uint64_t seqnum)
19321 + /* insert. this is not the fastest way, but it's easy, and it's
19322 + optimized for insert at end, which is the common case */
19325 + /* common case: at end, after == q->start+q->length-1 */
19327 + /* move all the elements (after,last] up one slot */
19329 + for (i = q->start + q->length - 1; i > after; i--)
19330 + QELEM(q,i+1) = QELEM(q,i);
19332 + /* fill in slot after+1 */
19334 + QELEM(q,after+1) = seqnum;
19336 + /* Either increase the length by one, or move the starting point up
19337 + one (deleting the first element, which got bashed above), as
19340 + if (q->length == QSIZE(q)) {
19342 + if (q->start == QSIZE(q))
19350 +sequenceInit(OM_uint32 *minor,
19359 + q = (queue *)GSSEAP_CALLOC(1, sizeof(queue));
19362 + return GSS_S_FAILURE;
19365 + q->do_replay = do_replay;
19366 + q->do_sequence = do_sequence;
19367 + q->mask = wide_nums ? ~(uint64_t)0 : 0xffffffffUL;
19371 + q->firstnum = seqnum;
19372 + q->elem[q->start] = ((uint64_t)0 - 1) & q->mask;
19374 + *vqueue = (void *)q;
19376 + return GSS_S_COMPLETE;
19380 +sequenceCheck(OM_uint32 *minor,
19386 + uint64_t expected;
19390 + q = (queue *) (*vqueue);
19392 + if (!q->do_replay && !q->do_sequence)
19393 + return GSS_S_COMPLETE;
19395 + /* All checks are done relative to the initial sequence number, to
19396 + avoid (or at least put off) the pain of wrapping. */
19397 + seqnum -= q->firstnum;
19398 + /* If we're only doing 32-bit values, adjust for that again.
19400 + Note that this will probably be the wrong thing to if we get
19401 + 2**32 messages sent with 32-bit sequence numbers. */
19402 + seqnum &= q->mask;
19404 + /* rule 1: expected sequence number */
19406 + expected = (QELEM(q,q->start+q->length-1)+1) & q->mask;
19407 + if (seqnum == expected) {
19408 + queue_insert(q, q->start+q->length-1, seqnum);
19409 + return GSS_S_COMPLETE;
19412 + /* rule 2: > expected sequence number */
19414 + if ((seqnum > expected)) {
19415 + queue_insert(q, q->start+q->length-1, seqnum);
19416 + if (q->do_replay && !q->do_sequence)
19417 + return GSS_S_COMPLETE;
19419 + return GSS_S_GAP_TOKEN;
19422 + /* rule 3: seqnum < seqnum(first) */
19424 + if ((seqnum < QELEM(q,q->start)) &&
19425 + /* Is top bit of whatever width we're using set?
19427 + We used to check for greater than or equal to firstnum, but
19428 + (1) we've since switched to compute values relative to
19429 + firstnum, so the lowest we can have is 0, and (2) the effect
19430 + of the original scheme was highly dependent on whether
19431 + firstnum was close to either side of 0. (Consider
19432 + firstnum==0xFFFFFFFE and we miss three packets; the next
19433 + packet is *new* but would look old.)
19435 + This check should give us 2**31 or 2**63 messages "new", and
19436 + just as many "old". That's not quite right either. */
19437 + (seqnum & (1 + (q->mask >> 1)))
19439 + if (q->do_replay && !q->do_sequence)
19440 + return GSS_S_OLD_TOKEN;
19442 + return GSS_S_UNSEQ_TOKEN;
19445 + /* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */
19448 + if (seqnum == QELEM(q,q->start+q->length - 1))
19449 + return GSS_S_DUPLICATE_TOKEN;
19451 + for (i = q->start; i < q->start + q->length - 1; i++) {
19452 + if (seqnum == QELEM(q,i))
19453 + return GSS_S_DUPLICATE_TOKEN;
19454 + if ((seqnum > QELEM(q,i)) && (seqnum < QELEM(q,i+1))) {
19455 + queue_insert(q, i, seqnum);
19456 + if (q->do_replay && !q->do_sequence)
19457 + return GSS_S_COMPLETE;
19459 + return GSS_S_UNSEQ_TOKEN;
19464 + /* this should never happen */
19465 + return GSS_S_FAILURE;
19469 +sequenceFree(OM_uint32 *minor, void **vqueue)
19473 + q = (queue *) (*vqueue);
19480 + return GSS_S_COMPLETE;
19484 + * These support functions are for the serialization routines
19487 +sequenceSize(void *vqueue GSSEAP_UNUSED)
19489 + return sizeof(queue);
19493 +sequenceExternalize(OM_uint32 *minor,
19495 + unsigned char **buf,
19496 + size_t *lenremain)
19498 + if (*lenremain < sizeof(queue)) {
19499 + *minor = GSSEAP_WRONG_SIZE;
19500 + return GSS_S_FAILURE;
19502 + memcpy(*buf, vqueue, sizeof(queue));
19503 + *buf += sizeof(queue);
19504 + *lenremain -= sizeof(queue);
19510 +sequenceInternalize(OM_uint32 *minor,
19512 + unsigned char **buf,
19513 + size_t *lenremain)
19517 + if (*lenremain < sizeof(queue)) {
19518 + *minor = GSSEAP_TOK_TRUNC;
19519 + return GSS_S_DEFECTIVE_TOKEN;
19522 + q = GSSEAP_MALLOC(sizeof(queue));
19525 + return GSS_S_FAILURE;
19528 + memcpy(q, *buf, sizeof(queue));
19529 + *buf += sizeof(queue);
19530 + *lenremain -= sizeof(queue);
19534 + return GSS_S_COMPLETE;
19536 diff --git a/mech_eap/util_radius.cpp b/mech_eap/util_radius.cpp
19537 new file mode 100644
19538 index 0000000..9111e20
19540 +++ b/mech_eap/util_radius.cpp
19543 + * Copyright (c) 2011, JANET(UK)
19544 + * All rights reserved.
19546 + * Redistribution and use in source and binary forms, with or without
19547 + * modification, are permitted provided that the following conditions
19550 + * 1. Redistributions of source code must retain the above copyright
19551 + * notice, this list of conditions and the following disclaimer.
19553 + * 2. Redistributions in binary form must reproduce the above copyright
19554 + * notice, this list of conditions and the following disclaimer in the
19555 + * documentation and/or other materials provided with the distribution.
19557 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19558 + * may be used to endorse or promote products derived from this software
19559 + * without specific prior written permission.
19561 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19562 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19563 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19564 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19565 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19566 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19567 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19568 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19569 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19570 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19575 + * RADIUS attribute provider implementation.
19578 +#include "gssapiP_eap.h"
19580 +/* stuff that should be provided by libradsec/libfreeradius-radius */
19581 +#define VENDORATTR(vendor, attr) (((vendor) << 16) | (attr))
19584 +#define ATTRID(attr) ((attr) & 0xFFFF)
19587 +static gss_buffer_desc radiusUrnPrefix = {
19588 + sizeof("urn:x-radius:") - 1,
19589 + (void *)"urn:x-radius:"
19592 +static VALUE_PAIR *copyAvps(const VALUE_PAIR *src);
19594 +gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(void)
19597 + m_authenticated = false;
19600 +gss_eap_radius_attr_provider::~gss_eap_radius_attr_provider(void)
19602 + if (m_vps != NULL)
19603 + pairfree(&m_vps);
19607 +gss_eap_radius_attr_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
19608 + const gss_eap_attr_provider *ctx)
19610 + const gss_eap_radius_attr_provider *radius;
19612 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx))
19615 + radius = static_cast<const gss_eap_radius_attr_provider *>(ctx);
19617 + if (radius->m_vps != NULL)
19618 + m_vps = copyAvps(const_cast<VALUE_PAIR *>(radius->getAvps()));
19620 + m_authenticated = radius->m_authenticated;
19626 +gss_eap_radius_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
19627 + const gss_cred_id_t gssCred,
19628 + const gss_ctx_id_t gssCtx)
19630 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
19633 + if (gssCtx != GSS_C_NO_CONTEXT) {
19634 + if (gssCtx->acceptorCtx.vps != NULL) {
19635 + m_vps = copyAvps(gssCtx->acceptorCtx.vps);
19636 + if (m_vps == NULL)
19639 + /* We assume libradsec validated this for us */
19640 + GSSEAP_ASSERT(pairfind(m_vps, PW_MESSAGE_AUTHENTICATOR) != NULL);
19641 + m_authenticated = true;
19649 +alreadyAddedAttributeP(std::vector <std::string> &attrs, VALUE_PAIR *vp)
19651 + for (std::vector<std::string>::const_iterator a = attrs.begin();
19652 + a != attrs.end();
19654 + if (strcmp(vp->name, (*a).c_str()) == 0)
19662 +isSecretAttributeP(uint16_t attrid, uint16_t vendor)
19664 + bool bSecretAttribute = false;
19666 + switch (vendor) {
19667 + case VENDORPEC_MS:
19668 + switch (attrid) {
19669 + case PW_MS_MPPE_SEND_KEY:
19670 + case PW_MS_MPPE_RECV_KEY:
19671 + bSecretAttribute = true;
19680 + return bSecretAttribute;
19684 +isSecretAttributeP(uint32_t attribute)
19686 + return isSecretAttributeP(ATTRID(attribute), VENDOR(attribute));
19690 +isInternalAttributeP(uint16_t attrid, uint16_t vendor)
19692 + bool bInternalAttribute = false;
19694 + /* should have been filtered */
19695 + GSSEAP_ASSERT(!isSecretAttributeP(attrid, vendor));
19697 + switch (vendor) {
19698 + case VENDORPEC_UKERNA:
19699 + switch (attrid) {
19700 + case PW_GSS_ACCEPTOR_SERVICE_NAME:
19701 + case PW_GSS_ACCEPTOR_HOST_NAME:
19702 + case PW_GSS_ACCEPTOR_SERVICE_SPECIFIC:
19703 + case PW_GSS_ACCEPTOR_REALM_NAME:
19704 + case PW_SAML_AAA_ASSERTION:
19705 + bInternalAttribute = true;
19715 + return bInternalAttribute;
19719 +isInternalAttributeP(uint32_t attribute)
19721 + return isInternalAttributeP(ATTRID(attribute), VENDOR(attribute));
19725 +isFragmentedAttributeP(uint16_t attrid, uint16_t vendor)
19727 + /* A bit of a hack for the PAC for now. Should be configurable. */
19728 + return (vendor == VENDORPEC_UKERNA) &&
19729 + !isInternalAttributeP(attrid, vendor);
19733 +isFragmentedAttributeP(uint32_t attribute)
19735 + return isFragmentedAttributeP(ATTRID(attribute), VENDOR(attribute));
19739 + * Copy AVP list, same as paircopy except it filters out attributes
19740 + * containing keys.
19742 +static VALUE_PAIR *
19743 +copyAvps(const VALUE_PAIR *src)
19745 + const VALUE_PAIR *vp;
19746 + VALUE_PAIR *dst = NULL, **pDst = &dst;
19748 + for (vp = src; vp != NULL; vp = vp->next) {
19749 + VALUE_PAIR *vpcopy;
19751 + if (isSecretAttributeP(vp->attribute))
19754 + vpcopy = paircopyvp(vp);
19755 + if (vpcopy == NULL) {
19757 + throw std::bad_alloc();
19760 + pDst = &vpcopy->next;
19767 +gss_eap_radius_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
19768 + void *data) const
19771 + std::vector <std::string> seen;
19773 + for (vp = m_vps; vp != NULL; vp = vp->next) {
19774 + gss_buffer_desc attribute;
19777 + /* Don't advertise attributes that are internal to the GSS-EAP mechanism */
19778 + if (isInternalAttributeP(vp->attribute))
19781 + if (alreadyAddedAttributeP(seen, vp))
19784 + snprintf(attrid, sizeof(attrid), "%s%d",
19785 + (char *)radiusUrnPrefix.value, vp->attribute);
19787 + attribute.value = attrid;
19788 + attribute.length = strlen(attrid);
19790 + if (!addAttribute(m_manager, this, &attribute, data))
19793 + seen.push_back(std::string(vp->name));
19800 +getAttributeId(const gss_buffer_t attr)
19802 + OM_uint32 tmpMinor;
19803 + gss_buffer_desc strAttr = GSS_C_EMPTY_BUFFER;
19806 + uint32_t attrid = 0;
19808 + if (attr->length < radiusUrnPrefix.length ||
19809 + memcmp(attr->value, radiusUrnPrefix.value, radiusUrnPrefix.length) != 0)
19812 + /* need to duplicate because attr may not be NUL terminated */
19813 + duplicateBuffer(*attr, &strAttr);
19814 + s = (char *)strAttr.value + radiusUrnPrefix.length;
19816 + if (isdigit(*s)) {
19817 + attrid = strtoul(s, NULL, 10);
19819 + da = dict_attrbyname(s);
19821 + attrid = da->attr;
19824 + gss_release_buffer(&tmpMinor, &strAttr);
19830 +gss_eap_radius_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
19832 + const gss_buffer_t value)
19834 + OM_uint32 major = GSS_S_UNAVAILABLE, minor;
19836 + if (!isSecretAttributeP(attrid) &&
19837 + !isInternalAttributeP(attrid)) {
19838 + deleteAttribute(attrid);
19840 + major = gssEapRadiusAddAvp(&minor, &m_vps,
19841 + ATTRID(attrid), VENDOR(attrid),
19845 + return !GSS_ERROR(major);
19849 +gss_eap_radius_attr_provider::setAttribute(int complete,
19850 + const gss_buffer_t attr,
19851 + const gss_buffer_t value)
19853 + uint32_t attrid = getAttributeId(attr);
19858 + return setAttribute(complete, attrid, value);
19862 +gss_eap_radius_attr_provider::deleteAttribute(uint32_t attrid)
19864 + if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid) ||
19865 + pairfind(m_vps, attrid) == NULL)
19868 + pairdelete(&m_vps, attrid);
19874 +gss_eap_radius_attr_provider::deleteAttribute(const gss_buffer_t attr)
19876 + uint32_t attrid = getAttributeId(attr);
19881 + return deleteAttribute(attrid);
19885 +gss_eap_radius_attr_provider::getAttribute(const gss_buffer_t attr,
19886 + int *authenticated,
19888 + gss_buffer_t value,
19889 + gss_buffer_t display_value,
19894 + attrid = getAttributeId(attr);
19898 + return getAttribute(attrid, authenticated, complete,
19899 + value, display_value, more);
19903 +gss_eap_radius_attr_provider::getAttribute(uint32_t attrid,
19904 + int *authenticated,
19906 + gss_buffer_t value,
19907 + gss_buffer_t display_value,
19911 + int i = *more, count = 0;
19918 + if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) {
19920 + } else if (isFragmentedAttributeP(attrid)) {
19921 + return getFragmentedAttribute(attrid,
19927 + for (vp = pairfind(m_vps, attrid);
19929 + vp = pairfind(vp->next, attrid)) {
19930 + if (count++ == i) {
19931 + if (pairfind(vp->next, attrid) != NULL)
19937 + if (vp == NULL && *more == 0)
19940 + if (value != GSS_C_NO_BUFFER) {
19941 + gss_buffer_desc valueBuf;
19943 + valueBuf.value = (void *)vp->vp_octets;
19944 + valueBuf.length = vp->length;
19946 + duplicateBuffer(valueBuf, value);
19949 + if (display_value != GSS_C_NO_BUFFER &&
19950 + vp->type != PW_TYPE_OCTETS) {
19951 + char displayString[MAX_STRING_LEN];
19952 + gss_buffer_desc displayBuf;
19954 + displayBuf.length = vp_prints_value(displayString,
19955 + sizeof(displayString), vp, 0);
19956 + displayBuf.value = (void *)displayString;
19958 + duplicateBuffer(displayBuf, display_value);
19961 + if (authenticated != NULL)
19962 + *authenticated = m_authenticated;
19963 + if (complete != NULL)
19964 + *complete = true;
19970 +gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute,
19972 + int *authenticated,
19974 + gss_buffer_t value) const
19976 + OM_uint32 major, minor;
19978 + major = gssEapRadiusGetAvp(&minor, m_vps, attribute, vendor, value, TRUE);
19980 + if (authenticated != NULL)
19981 + *authenticated = m_authenticated;
19982 + if (complete != NULL)
19983 + *complete = true;
19985 + return !GSS_ERROR(major);
19989 +gss_eap_radius_attr_provider::getFragmentedAttribute(uint32_t attrid,
19990 + int *authenticated,
19992 + gss_buffer_t value) const
19994 + return getFragmentedAttribute(ATTRID(attrid), VENDOR(attrid),
19995 + authenticated, complete, value);
19999 +gss_eap_radius_attr_provider::getAttribute(uint16_t attribute,
20001 + int *authenticated,
20003 + gss_buffer_t value,
20004 + gss_buffer_t display_value,
20008 + return getAttribute(VENDORATTR(attribute, vendor),
20009 + authenticated, complete,
20010 + value, display_value, more);
20014 +gss_eap_radius_attr_provider::mapToAny(int authenticated,
20015 + gss_buffer_t type_id GSSEAP_UNUSED) const
20017 + if (authenticated && !m_authenticated)
20018 + return (gss_any_t)NULL;
20020 + return (gss_any_t)copyAvps(m_vps);
20024 +gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
20025 + gss_any_t input) const
20027 + VALUE_PAIR *vp = (VALUE_PAIR *)input;
20032 +gss_eap_radius_attr_provider::init(void)
20034 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_RADIUS, createAttrContext);
20040 +gss_eap_radius_attr_provider::finalize(void)
20042 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_RADIUS);
20045 +gss_eap_attr_provider *
20046 +gss_eap_radius_attr_provider::createAttrContext(void)
20048 + return new gss_eap_radius_attr_provider;
20052 +gssEapRadiusAddAvp(OM_uint32 *minor,
20053 + VALUE_PAIR **vps,
20054 + uint16_t attribute,
20056 + const gss_buffer_t buffer)
20058 + uint32_t attrid = VENDORATTR(vendor, attribute);
20059 + unsigned char *p = (unsigned char *)buffer->value;
20060 + size_t remain = buffer->length;
20064 + size_t n = remain;
20067 + * There's an extra byte of padding; RADIUS AVPs can only
20070 + if (n >= MAX_STRING_LEN)
20071 + n = MAX_STRING_LEN - 1;
20073 + vp = paircreate(attrid, PW_TYPE_OCTETS);
20074 + if (vp == NULL) {
20076 + return GSS_S_FAILURE;
20079 + memcpy(vp->vp_octets, p, n);
20082 + pairadd(vps, vp);
20086 + } while (remain != 0);
20088 + return GSS_S_COMPLETE;
20092 +gssEapRadiusGetRawAvp(OM_uint32 *minor,
20094 + uint16_t attribute,
20098 + uint32_t attr = VENDORATTR(vendor, attribute);
20100 + *vp = pairfind(vps, attr);
20101 + if (*vp == NULL) {
20102 + *minor = GSSEAP_NO_SUCH_ATTR;
20103 + return GSS_S_UNAVAILABLE;
20106 + return GSS_S_COMPLETE;
20110 +gssEapRadiusGetAvp(OM_uint32 *minor,
20112 + uint16_t attribute,
20114 + gss_buffer_t buffer,
20118 + unsigned char *p;
20119 + uint32_t attr = VENDORATTR(vendor, attribute);
20121 + if (buffer != GSS_C_NO_BUFFER) {
20122 + buffer->length = 0;
20123 + buffer->value = NULL;
20126 + vp = pairfind(vps, attr);
20127 + if (vp == NULL) {
20128 + *minor = GSSEAP_NO_SUCH_ATTR;
20129 + return GSS_S_UNAVAILABLE;
20132 + if (buffer != GSS_C_NO_BUFFER) {
20134 + buffer->length += vp->length;
20135 + } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
20137 + buffer->value = GSSEAP_MALLOC(buffer->length);
20138 + if (buffer->value == NULL) {
20140 + return GSS_S_FAILURE;
20143 + p = (unsigned char *)buffer->value;
20145 + for (vp = pairfind(vps, attr);
20146 + concat && vp != NULL;
20147 + vp = pairfind(vp->next, attr)) {
20148 + memcpy(p, vp->vp_octets, vp->length);
20154 + return GSS_S_COMPLETE;
20158 +gssEapRadiusFreeAvps(OM_uint32 *minor,
20159 + VALUE_PAIR **vps)
20163 + return GSS_S_COMPLETE;
20167 +gssEapRadiusAttrProviderInit(OM_uint32 *minor)
20169 + if (!gss_eap_radius_attr_provider::init()) {
20170 + *minor = GSSEAP_RADSEC_INIT_FAILURE;
20171 + return GSS_S_FAILURE;
20174 + return GSS_S_COMPLETE;
20178 +gssEapRadiusAttrProviderFinalize(OM_uint32 *minor)
20180 + gss_eap_radius_attr_provider::finalize();
20183 + return GSS_S_COMPLETE;
20187 +avpToJson(const VALUE_PAIR *vp)
20191 + GSSEAP_ASSERT(vp->length <= MAX_STRING_LEN);
20193 + switch (vp->type) {
20194 + case PW_TYPE_INTEGER:
20195 + case PW_TYPE_IPADDR:
20196 + case PW_TYPE_DATE:
20197 + obj.set("value", vp->lvalue);
20199 + case PW_TYPE_STRING:
20200 + obj.set("value", vp->vp_strvalue);
20205 + if (base64Encode(vp->vp_octets, vp->length, &b64) < 0)
20206 + throw std::bad_alloc();
20208 + obj.set("value", b64);
20209 + GSSEAP_FREE(b64);
20214 + obj.set("type", vp->attribute);
20220 +jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj)
20222 + VALUE_PAIR *vp = NULL;
20226 + JSONObject type = obj["type"];
20227 + JSONObject value = obj["value"];
20229 + if (!type.isInteger())
20232 + attrid = type.integer();
20233 + da = dict_attrbyvalue(attrid);
20234 + if (da != NULL) {
20235 + vp = pairalloc(da);
20237 + int type = base64Valid(value.string()) ?
20238 + PW_TYPE_OCTETS : PW_TYPE_STRING;
20239 + vp = paircreate(attrid, type);
20242 + throw std::bad_alloc();
20244 + switch (vp->type) {
20245 + case PW_TYPE_INTEGER:
20246 + case PW_TYPE_IPADDR:
20247 + case PW_TYPE_DATE:
20248 + if (!value.isInteger())
20252 + vp->lvalue = value.integer();
20254 + case PW_TYPE_STRING: {
20255 + if (!value.isString())
20258 + const char *str = value.string();
20259 + size_t len = strlen(str);
20261 + if (len >= MAX_STRING_LEN)
20264 + vp->length = len;
20265 + memcpy(vp->vp_strvalue, str, len + 1);
20268 + case PW_TYPE_OCTETS:
20270 + if (!value.isString())
20273 + const char *str = value.string();
20274 + ssize_t len = strlen(str);
20276 + /* this optimization requires base64Decode only understand packed encoding */
20277 + if (len >= BASE64_EXPAND(MAX_STRING_LEN))
20280 + len = base64Decode(str, vp->vp_octets);
20284 + vp->length = len;
20295 + pairbasicfree(vp);
20301 +gss_eap_radius_attr_provider::name(void) const
20307 +gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
20310 + VALUE_PAIR **pNext = &m_vps;
20312 + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
20315 + JSONObject attrs = obj["attributes"];
20316 + size_t nelems = attrs.size();
20318 + for (size_t i = 0; i < nelems; i++) {
20319 + JSONObject attr = attrs[i];
20322 + if (!jsonToAvp(&vp, attr))
20326 + pNext = &vp->next;
20329 + m_authenticated = obj["authenticated"].integer() ? true : false;
20335 +gss_eap_radius_attr_provider::prefix(void) const
20337 + return "urn:ietf:params:gss-eap:radius-avp";
20341 +gss_eap_radius_attr_provider::jsonRepresentation(void) const
20343 + JSONObject obj, attrs = JSONObject::array();
20345 + for (VALUE_PAIR *vp = m_vps; vp != NULL; vp = vp->next) {
20346 + JSONObject attr = avpToJson(vp);
20347 + attrs.append(attr);
20350 + obj.set("attributes", attrs);
20352 + obj.set("authenticated", m_authenticated);
20358 +gss_eap_radius_attr_provider::getExpiryTime(void) const
20362 + vp = pairfind(m_vps, PW_SESSION_TIMEOUT);
20363 + if (vp == NULL || vp->lvalue == 0)
20366 + return time(NULL) + vp->lvalue;
20370 +gssEapRadiusMapError(OM_uint32 *minor,
20371 + struct rs_error *err)
20375 + GSSEAP_ASSERT(err != NULL);
20377 + code = rs_err_code(err, 0);
20379 + if (code == RSE_OK) {
20381 + return GSS_S_COMPLETE;
20384 + *minor = ERROR_TABLE_BASE_rse + code;
20386 + gssEapSaveStatusInfo(*minor, "%s", rs_err_msg(err));
20387 + rs_err_free(err);
20389 + return GSS_S_FAILURE;
20393 +gssEapCreateRadiusContext(OM_uint32 *minor,
20394 + gss_cred_id_t cred,
20395 + struct rs_context **pRadContext)
20397 + const char *configFile = RS_CONFIG_FILE;
20398 + struct rs_context *radContext;
20399 + struct rs_alloc_scheme ralloc;
20400 + struct rs_error *err;
20403 + *pRadContext = NULL;
20405 + if (rs_context_create(&radContext) != 0) {
20406 + *minor = GSSEAP_RADSEC_CONTEXT_FAILURE;
20407 + return GSS_S_FAILURE;
20410 + if (cred->radiusConfigFile.value != NULL)
20411 + configFile = (const char *)cred->radiusConfigFile.value;
20413 + ralloc.calloc = GSSEAP_CALLOC;
20414 + ralloc.malloc = GSSEAP_MALLOC;
20415 + ralloc.free = GSSEAP_FREE;
20416 + ralloc.realloc = GSSEAP_REALLOC;
20418 + rs_context_set_alloc_scheme(radContext, &ralloc);
20420 + if (rs_context_read_config(radContext, configFile) != 0) {
20421 + err = rs_err_ctx_pop(radContext);
20425 + if (rs_context_init_freeradius_dict(radContext, NULL) != 0) {
20426 + err = rs_err_ctx_pop(radContext);
20430 + *pRadContext = radContext;
20433 + return GSS_S_COMPLETE;
20436 + major = gssEapRadiusMapError(minor, err);
20437 + rs_context_destroy(radContext);
20441 diff --git a/mech_eap/util_radius.h b/mech_eap/util_radius.h
20442 new file mode 100644
20443 index 0000000..481876a
20445 +++ b/mech_eap/util_radius.h
20448 + * Copyright (c) 2011, JANET(UK)
20449 + * All rights reserved.
20451 + * Redistribution and use in source and binary forms, with or without
20452 + * modification, are permitted provided that the following conditions
20455 + * 1. Redistributions of source code must retain the above copyright
20456 + * notice, this list of conditions and the following disclaimer.
20458 + * 2. Redistributions in binary form must reproduce the above copyright
20459 + * notice, this list of conditions and the following disclaimer in the
20460 + * documentation and/or other materials provided with the distribution.
20462 + * 3. Neither the name of JANET(UK) nor the names of its contributors
20463 + * may be used to endorse or promote products derived from this software
20464 + * without specific prior written permission.
20466 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20467 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20468 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20469 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20470 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20471 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20472 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20473 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20474 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20475 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20480 + * RADIUS attribute provider.
20483 +#ifndef _UTIL_RADIUS_H_
20484 +#define _UTIL_RADIUS_H_ 1
20486 +#ifdef __cplusplus
20488 +struct gss_eap_radius_attr_provider : gss_eap_attr_provider {
20490 + gss_eap_radius_attr_provider(void);
20491 + ~gss_eap_radius_attr_provider(void);
20493 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
20494 + const gss_eap_attr_provider *ctx);
20495 + bool initWithGssContext(const gss_eap_attr_ctx *source,
20496 + const gss_cred_id_t cred,
20497 + const gss_ctx_id_t ctx);
20499 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
20500 + bool setAttribute(int complete,
20501 + const gss_buffer_t attr,
20502 + const gss_buffer_t value);
20503 + bool deleteAttribute(const gss_buffer_t attr);
20504 + bool getAttribute(const gss_buffer_t attr,
20505 + int *authenticated,
20507 + gss_buffer_t value,
20508 + gss_buffer_t display_value,
20509 + int *more) const;
20510 + gss_any_t mapToAny(int authenticated,
20511 + gss_buffer_t type_id) const;
20512 + void releaseAnyNameMapping(gss_buffer_t type_id,
20513 + gss_any_t input) const;
20515 + const char *prefix(void) const;
20516 + const char *name(void) const;
20517 + bool initWithJsonObject(const gss_eap_attr_ctx *manager,
20518 + JSONObject &obj);
20519 + JSONObject jsonRepresentation(void) const;
20521 + bool getAttribute(uint32_t attribute,
20522 + int *authenticated,
20524 + gss_buffer_t value,
20525 + gss_buffer_t display_value,
20526 + int *more) const;
20527 + bool getAttribute(uint16_t attribute,
20529 + int *authenticated,
20531 + gss_buffer_t value,
20532 + gss_buffer_t display_value,
20533 + int *more) const;
20534 + bool setAttribute(int complete,
20535 + uint32_t attribute,
20536 + const gss_buffer_t value);
20537 + bool deleteAttribute(uint32_t attribute);
20539 + bool getFragmentedAttribute(uint16_t attribute,
20541 + int *authenticated,
20543 + gss_buffer_t value) const;
20544 + bool getFragmentedAttribute(uint32_t attrid,
20545 + int *authenticated,
20547 + gss_buffer_t value) const;
20549 + bool authenticated(void) const { return m_authenticated; }
20551 + time_t getExpiryTime(void) const;
20553 + static bool init(void);
20554 + static void finalize(void);
20556 + static gss_eap_attr_provider *createAttrContext(void);
20559 + const VALUE_PAIR *getAvps(void) const {
20563 + VALUE_PAIR *m_vps;
20564 + bool m_authenticated;
20572 +gssEapRadiusAddAvp(OM_uint32 *minor,
20576 + const gss_buffer_t buffer);
20579 +gssEapRadiusGetAvp(OM_uint32 *minor,
20583 + gss_buffer_t buffer,
20587 +gssEapRadiusGetRawAvp(OM_uint32 *minor,
20591 + VALUE_PAIR **vp);
20593 +gssEapRadiusFreeAvps(OM_uint32 *minor,
20594 + VALUE_PAIR **vps);
20596 +OM_uint32 gssEapRadiusAttrProviderInit(OM_uint32 *minor);
20597 +OM_uint32 gssEapRadiusAttrProviderFinalize(OM_uint32 *minor);
20600 +gssEapRadiusMapError(OM_uint32 *minor,
20601 + struct rs_error *err);
20604 +gssEapCreateRadiusContext(OM_uint32 *minor,
20605 + gss_cred_id_t cred,
20606 + struct rs_context **pRadContext);
20608 +/* This really needs to be a function call on Windows */
20609 +#define RS_CONFIG_FILE SYSCONFDIR "/radsec.conf"
20611 +#define VENDORPEC_MS 311 /* RFC 2548 */
20613 +#define PW_MS_MPPE_SEND_KEY 16
20614 +#define PW_MS_MPPE_RECV_KEY 17
20616 +#define VENDORPEC_UKERNA 25622
20618 +#define PW_GSS_ACCEPTOR_SERVICE_NAME 128
20619 +#define PW_GSS_ACCEPTOR_HOST_NAME 129
20620 +#define PW_GSS_ACCEPTOR_SERVICE_SPECIFIC 130
20621 +#define PW_GSS_ACCEPTOR_REALM_NAME 131
20622 +#define PW_SAML_AAA_ASSERTION 132
20623 +#define PW_MS_WINDOWS_AUTH_DATA 133
20625 +#ifdef __cplusplus
20629 +#endif /* _UTIL_RADIUS_H_ */
20630 diff --git a/mech_eap/util_reauth.c b/mech_eap/util_reauth.c
20631 new file mode 100644
20632 index 0000000..50011ca
20634 +++ b/mech_eap/util_reauth.c
20637 + * Copyright (c) 2011, JANET(UK)
20638 + * All rights reserved.
20640 + * Redistribution and use in source and binary forms, with or without
20641 + * modification, are permitted provided that the following conditions
20644 + * 1. Redistributions of source code must retain the above copyright
20645 + * notice, this list of conditions and the following disclaimer.
20647 + * 2. Redistributions in binary form must reproduce the above copyright
20648 + * notice, this list of conditions and the following disclaimer in the
20649 + * documentation and/or other materials provided with the distribution.
20651 + * 3. Neither the name of JANET(UK) nor the names of its contributors
20652 + * may be used to endorse or promote products derived from this software
20653 + * without specific prior written permission.
20655 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20656 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20657 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20658 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20659 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20660 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20661 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20662 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20663 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20664 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20669 + * Fast reauthentication support.
20672 +#include "gssapiP_eap.h"
20674 +#include <dlfcn.h>
20677 + * Fast reauthentication support for EAP GSS.
20681 +krb5_encrypt_tkt_part(krb5_context, const krb5_keyblock *, krb5_ticket *);
20684 +encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code);
20687 +gssDisplayName(OM_uint32 *minor,
20689 + gss_buffer_t buffer,
20690 + gss_OID *name_type);
20693 +gssImportName(OM_uint32 *minor,
20694 + gss_buffer_t buffer,
20695 + gss_OID name_type,
20696 + gss_name_t *name);
20698 +static krb5_error_code
20699 +getAcceptorKey(krb5_context krbContext,
20700 + gss_ctx_id_t ctx,
20701 + gss_cred_id_t cred,
20702 + krb5_principal *princ,
20703 + krb5_keyblock *key)
20705 + krb5_error_code code;
20706 + krb5_keytab keytab = NULL;
20707 + krb5_keytab_entry ktent = { 0 };
20708 + krb5_kt_cursor cursor;
20711 + memset(key, 0, sizeof(*key));
20712 + memset(&cursor, 0, sizeof(cursor));
20714 + code = krb5_kt_default(krbContext, &keytab);
20718 + if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
20719 + code = krb5_kt_get_entry(krbContext, keytab,
20720 + cred->name->krbPrincipal, 0,
20721 + ctx->encryptionType, &ktent);
20726 + * It's not clear that looking encrypting the ticket in the
20727 + * requested EAP enctype provides any value.
20729 + code = krb5_kt_start_seq_get(krbContext, keytab, &cursor);
20733 + while ((code = krb5_kt_next_entry(krbContext, keytab,
20734 + &ktent, &cursor)) == 0) {
20735 + if (KRB_KEY_TYPE(KRB_KT_ENT_KEYBLOCK(&ktent)) == ctx->encryptionType)
20738 + KRB_KT_ENT_FREE(krbContext, &ktent);
20743 + *princ = ktent.principal;
20744 + *key = *KRB_KT_ENT_KEYBLOCK(&ktent);
20748 + if (cred == GSS_C_NO_CREDENTIAL || cred->name == GSS_C_NO_NAME)
20749 + krb5_kt_end_seq_get(krbContext, keytab, &cursor);
20750 + krb5_kt_close(krbContext, keytab);
20752 + KRB_KT_ENT_FREE(krbContext, &ktent);
20758 +freezeAttrContext(OM_uint32 *minor,
20759 + gss_name_t initiatorName,
20760 + krb5_const_principal acceptorPrinc,
20761 + krb5_keyblock *session,
20762 +#ifdef HAVE_HEIMDAL_VERSION
20763 + krb5_authdata *kdcIssuedAuthData
20765 + krb5_authdata ***kdcIssuedAuthData
20769 + OM_uint32 major, tmpMinor;
20770 + krb5_error_code code;
20771 + krb5_context krbContext;
20772 + gss_buffer_desc attrBuf = GSS_C_EMPTY_BUFFER;
20773 +#ifdef HAVE_HEIMDAL_VERSION
20774 + krb5_authdata authDataBuf, *authData = &authDataBuf;
20775 + AuthorizationDataElement authDatum = { 0 };
20777 + krb5_authdata *authData[2], authDatum = { 0 };
20780 + memset(kdcIssuedAuthData, 0, sizeof(*kdcIssuedAuthData));
20782 + GSSEAP_KRB_INIT(&krbContext);
20784 + major = gssEapExportAttrContext(minor, initiatorName, &attrBuf);
20785 + if (GSS_ERROR(major))
20788 + authDatum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
20789 +#ifdef HAVE_HEIMDAL_VERSION
20790 + authDatum.ad_data.length = attrBuf.length;
20791 + authDatum.ad_data.data = attrBuf.value;
20792 + authData->len = 1;
20793 + authData->val = &authDatum;
20795 + authDatum.length = attrBuf.length;
20796 + authDatum.contents = attrBuf.value;
20797 + authData[0] = &authDatum;
20798 + authData[1] = NULL;
20801 + code = krbMakeAuthDataKdcIssued(krbContext, session, acceptorPrinc,
20802 + authData, kdcIssuedAuthData);
20804 + major = GSS_S_FAILURE;
20807 + major = GSS_S_COMPLETE;
20810 + gss_release_buffer(&tmpMinor, &attrBuf);
20816 + * Fabricate a ticket to ourselves given a GSS EAP context.
20819 +gssEapMakeReauthCreds(OM_uint32 *minor,
20820 + gss_ctx_id_t ctx,
20821 + gss_cred_id_t cred,
20822 + gss_buffer_t credBuf)
20824 + OM_uint32 major = GSS_S_COMPLETE;
20825 + krb5_error_code code;
20826 + krb5_context krbContext = NULL;
20827 + krb5_keyblock session = { 0 }, acceptorKey = { 0 };
20828 + krb5_principal server = NULL;
20829 +#ifdef HAVE_HEIMDAL_VERSION
20831 + EncTicketPart enc_part;
20832 + AuthorizationData authData = { 0 };
20833 + krb5_crypto krbCrypto = NULL;
20834 + krb5_data ticketData = { 0 };
20835 + krb5_data encPartData = { 0 };
20838 + krb5_ticket ticket;
20839 + krb5_enc_tkt_part enc_part;
20840 + krb5_data *ticketData = NULL;
20842 + krb5_data credsData = { 0 };
20843 + krb5_creds creds = { 0 };
20844 + krb5_auth_context authContext = NULL;
20846 + memset(&ticket, 0, sizeof(ticket));
20847 + memset(&enc_part, 0, sizeof(enc_part));
20849 + credBuf->length = 0;
20850 + credBuf->value = NULL;
20852 + GSSEAP_KRB_INIT(&krbContext);
20854 + code = getAcceptorKey(krbContext, ctx, cred, &server, &acceptorKey);
20857 + return GSS_S_UNAVAILABLE;
20861 + * Generate a random session key to place in the ticket and
20862 + * sign the "KDC-Issued" authorization data element.
20864 +#ifdef HAVE_HEIMDAL_VERSION
20865 + ticket.realm = server->realm;
20866 + ticket.sname = server->name;
20868 + code = krb5_generate_random_keyblock(krbContext, ctx->encryptionType,
20873 + enc_part.flags.initial = 1;
20874 + enc_part.key = session;
20875 + enc_part.crealm = ctx->initiatorName->krbPrincipal->realm;
20876 + enc_part.cname = ctx->initiatorName->krbPrincipal->name;
20877 + enc_part.authtime = time(NULL);
20878 + enc_part.starttime = &enc_part.authtime;
20879 + enc_part.endtime = (ctx->expiryTime != 0)
20880 + ? ctx->expiryTime : KRB_TIME_FOREVER;
20881 + enc_part.renew_till = NULL;
20882 + enc_part.authorization_data = &authData;
20884 + major = freezeAttrContext(minor, ctx->initiatorName, server,
20885 + &session, &authData);
20886 + if (GSS_ERROR(major))
20889 + ASN1_MALLOC_ENCODE(EncTicketPart, encPartData.data, encPartData.length,
20890 + &enc_part, &len, code);
20894 + code = krb5_crypto_init(krbContext, &acceptorKey, 0, &krbCrypto);
20898 + code = krb5_encrypt_EncryptedData(krbContext,
20901 + encPartData.data,
20902 + encPartData.length,
20904 + &ticket.enc_part);
20908 + ASN1_MALLOC_ENCODE(Ticket, ticketData.data, ticketData.length,
20909 + &ticket, &len, code);
20913 + ticket.server = server;
20915 + code = krb5_c_make_random_key(krbContext, ctx->encryptionType,
20920 + enc_part.flags = TKT_FLG_INITIAL;
20921 + enc_part.session = &session;
20922 + enc_part.client = ctx->initiatorName->krbPrincipal;
20923 + enc_part.times.authtime = time(NULL);
20924 + enc_part.times.starttime = enc_part.times.authtime;
20925 + enc_part.times.endtime = (ctx->expiryTime != 0)
20926 + ? ctx->expiryTime
20927 + : KRB_TIME_FOREVER;
20928 + enc_part.times.renew_till = 0;
20930 + major = freezeAttrContext(minor, ctx->initiatorName, server,
20931 + &session, &enc_part.authorization_data);
20932 + if (GSS_ERROR(major))
20935 + ticket.enc_part2 = &enc_part;
20937 + code = krb5_encrypt_tkt_part(krbContext, &acceptorKey, &ticket);
20941 + code = encode_krb5_ticket(&ticket, &ticketData);
20944 +#endif /* HAVE_HEIMDAL_VERSION */
20946 + creds.client = ctx->initiatorName->krbPrincipal;
20947 + creds.server = server;
20948 +#ifdef HAVE_HEIMDAL_VERSION
20949 + creds.session = session;
20950 + creds.times.authtime = enc_part.authtime;
20951 + creds.times.starttime = *enc_part.starttime;
20952 + creds.times.endtime = enc_part.endtime;
20953 + creds.times.renew_till = 0;
20954 + creds.flags.b = enc_part.flags;
20955 + creds.ticket = ticketData;
20956 + creds.authdata = authData;
20958 + creds.keyblock = session;
20959 + creds.times = enc_part.times;
20960 + creds.ticket_flags = enc_part.flags;
20961 + creds.ticket = *ticketData;
20962 + creds.authdata = enc_part.authorization_data;
20965 + code = krb5_auth_con_init(krbContext, &authContext);
20969 + code = krb5_auth_con_setflags(krbContext, authContext, 0);
20973 +#ifdef HAVE_HEIMDAL_VERSION
20974 + code = krb5_auth_con_setlocalsubkey(krbContext, authContext,
20975 + &ctx->rfc3961Key);
20977 + code = krb5_auth_con_setsendsubkey(krbContext, authContext,
20978 + &ctx->rfc3961Key);
20983 + code = krbMakeCred(krbContext, authContext, &creds, &credsData);
20987 + krbDataToGssBuffer(&credsData, credBuf);
20990 +#ifdef HAVE_HEIMDAL_VERSION
20991 + if (krbCrypto != NULL)
20992 + krb5_crypto_destroy(krbContext, krbCrypto);
20993 + free_AuthorizationData(&authData);
20994 + free_EncryptedData(&ticket.enc_part);
20995 + krb5_data_free(&ticketData);
20996 + krb5_data_free(&encPartData);
20998 + krb5_free_authdata(krbContext, enc_part.authorization_data);
20999 + if (ticket.enc_part.ciphertext.data != NULL)
21000 + GSSEAP_FREE(ticket.enc_part.ciphertext.data);
21001 + krb5_free_data(krbContext, ticketData);
21003 + krb5_free_keyblock_contents(krbContext, &session);
21004 + krb5_free_principal(krbContext, server);
21005 + krb5_free_keyblock_contents(krbContext, &acceptorKey);
21006 + krb5_auth_con_free(krbContext, authContext);
21008 + if (major == GSS_S_COMPLETE) {
21010 + major = (code != 0) ? GSS_S_FAILURE : GSS_S_COMPLETE;
21017 +isTicketGrantingServiceP(krb5_context krbContext GSSEAP_UNUSED,
21018 + krb5_const_principal principal)
21020 + if (KRB_PRINC_LENGTH(principal) == 2 &&
21021 +#ifdef HAVE_HEIMDAL_VERSION
21022 + strcmp(KRB_PRINC_NAME(principal)[0], "krbtgt") == 0
21024 + krb5_princ_component(krbContext, principal, 0)->length == 6 &&
21025 + memcmp(krb5_princ_component(krbContext,
21026 + principal, 0)->data, "krbtgt", 6) == 0
21035 + * Returns TRUE if the configuration variable reauth_use_ccache is
21036 + * set in krb5.conf for the eap_gss application and the client realm.
21039 +reauthUseCredsCache(krb5_context krbContext,
21040 + krb5_principal principal)
21042 + int reauthUseCCache;
21044 + /* if reauth_use_ccache, use default credentials cache if ticket is for us */
21045 + krb5_appdefault_boolean(krbContext, "eap_gss",
21046 + KRB_PRINC_REALM(principal),
21047 + "reauth_use_ccache", 0, &reauthUseCCache);
21049 + return reauthUseCCache;
21053 + * Look in default credentials cache for reauthentication credentials,
21054 + * if policy allows.
21057 +getDefaultReauthCredentials(OM_uint32 *minor,
21058 + gss_cred_id_t cred,
21059 + gss_name_t target,
21061 + OM_uint32 timeReq)
21063 + OM_uint32 major = GSS_S_CRED_UNAVAIL;
21064 + krb5_context krbContext = NULL;
21065 + krb5_error_code code = 0;
21066 + krb5_ccache ccache = NULL;
21067 + krb5_creds match = { 0 };
21068 + krb5_creds creds = { 0 };
21070 + GSSEAP_KRB_INIT(&krbContext);
21072 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
21073 + GSSEAP_ASSERT(target != GSS_C_NO_NAME);
21075 + if (cred->name == GSS_C_NO_NAME ||
21076 + !reauthUseCredsCache(krbContext, cred->name->krbPrincipal))
21079 + match.client = cred->name->krbPrincipal;
21080 + match.server = target->krbPrincipal;
21081 + if (timeReq != 0 && timeReq != GSS_C_INDEFINITE)
21082 + match.times.endtime = now + timeReq;
21084 + code = krb5_cc_default(krbContext, &ccache);
21088 + code = krb5_cc_retrieve_cred(krbContext, ccache, 0, &match, &creds);
21092 + cred->flags |= CRED_FLAG_DEFAULT_CCACHE;
21093 + cred->krbCredCache = ccache;
21096 + major = gss_krb5_import_cred(minor, cred->krbCredCache, NULL, NULL,
21097 + &cred->reauthCred);
21100 + if (major == GSS_S_CRED_UNAVAIL)
21103 + if (ccache != NULL)
21104 + krb5_cc_close(krbContext, ccache);
21105 + krb5_free_cred_contents(krbContext, &creds);
21111 + * Returns TRUE if the credential handle's reauth credentials are
21112 + * valid or if we can use the default credentials cache. Credentials
21113 + * handle must be locked.
21116 +gssEapCanReauthP(gss_cred_id_t cred,
21117 + gss_name_t target,
21118 + OM_uint32 timeReq)
21120 + time_t now, expiryReq;
21123 + if (cred == GSS_C_NO_CREDENTIAL)
21126 + now = time(NULL);
21128 + if (timeReq != GSS_C_INDEFINITE)
21129 + expiryReq += timeReq;
21131 + if (cred->krbCredCache != NULL && cred->expiryTime > expiryReq)
21134 + if (getDefaultReauthCredentials(&minor, cred, target,
21135 + now, timeReq) == GSS_S_COMPLETE)
21142 + * Store re-authentication (Kerberos) credentials in a credential handle.
21143 + * Credentials handle must be locked.
21146 +gssEapStoreReauthCreds(OM_uint32 *minor,
21147 + gss_ctx_id_t ctx,
21148 + gss_cred_id_t cred,
21149 + gss_buffer_t credBuf)
21151 + OM_uint32 major = GSS_S_COMPLETE;
21152 + krb5_error_code code;
21153 + krb5_context krbContext = NULL;
21154 + krb5_auth_context authContext = NULL;
21155 + krb5_data credData = { 0 };
21156 + krb5_creds **creds = NULL;
21157 + krb5_principal canonPrinc;
21158 + krb5_principal ccPrinc = NULL;
21161 + if (credBuf->length == 0 || cred == GSS_C_NO_CREDENTIAL)
21162 + return GSS_S_COMPLETE;
21164 + GSSEAP_KRB_INIT(&krbContext);
21166 + code = krb5_auth_con_init(krbContext, &authContext);
21170 + code = krb5_auth_con_setflags(krbContext, authContext, 0);
21174 + code = krb5_auth_con_setrecvsubkey(krbContext, authContext,
21175 + &ctx->rfc3961Key);
21179 + gssBufferToKrbData(credBuf, &credData);
21181 + code = krb5_rd_cred(krbContext, authContext, &credData, &creds, NULL);
21185 + if (creds == NULL || creds[0] == NULL)
21188 + code = krb5_copy_principal(krbContext, creds[0]->client, &canonPrinc);
21192 + krb5_free_principal(krbContext, cred->name->krbPrincipal);
21193 + cred->name->krbPrincipal = canonPrinc;
21195 + if (creds[0]->times.endtime == KRB_TIME_FOREVER)
21196 + cred->expiryTime = 0;
21198 + cred->expiryTime = creds[0]->times.endtime;
21200 + if (cred->krbCredCache == NULL) {
21201 + if (reauthUseCredsCache(krbContext, creds[0]->client) &&
21202 + krb5_cc_default(krbContext, &cred->krbCredCache) == 0)
21203 + cred->flags |= CRED_FLAG_DEFAULT_CCACHE;
21206 + * If we already have an associated credentials cache, possibly from
21207 + * the last time we stored a reauthentication credential, then we
21208 + * need to clear it out and release the associated GSS credential.
21210 + if (cred->flags & CRED_FLAG_DEFAULT_CCACHE) {
21211 + krb5_cc_remove_cred(krbContext, cred->krbCredCache, 0, creds[0]);
21213 + krb5_cc_destroy(krbContext, cred->krbCredCache);
21214 + cred->krbCredCache = NULL;
21216 + gssReleaseCred(minor, &cred->reauthCred);
21219 + if (cred->krbCredCache == NULL) {
21220 + code = krb5_cc_new_unique(krbContext, "MEMORY", NULL, &cred->krbCredCache);
21225 + if ((cred->flags & CRED_FLAG_DEFAULT_CCACHE) == 0 ||
21226 + krb5_cc_get_principal(krbContext, cred->krbCredCache, &ccPrinc) != 0) {
21227 + code = krb5_cc_initialize(krbContext, cred->krbCredCache,
21228 + creds[0]->client);
21233 + for (i = 0; creds[i] != NULL; i++) {
21234 + krb5_creds kcred = *(creds[i]);
21237 + * Swap in the acceptor name the client asked for so
21238 + * get_credentials() works. We're making the assumption that
21239 + * any service tickets returned are for us. We'll need to
21240 + * reflect some more on whether that is a safe assumption.
21242 + if (!isTicketGrantingServiceP(krbContext, kcred.server))
21243 + kcred.server = ctx->acceptorName->krbPrincipal;
21245 + code = krb5_cc_store_cred(krbContext, cred->krbCredCache, &kcred);
21250 + major = gss_krb5_import_cred(minor, cred->krbCredCache, NULL, NULL,
21251 + &cred->reauthCred);
21252 + if (GSS_ERROR(major))
21258 + krb5_free_principal(krbContext, ccPrinc);
21259 + krb5_auth_con_free(krbContext, authContext);
21260 + if (creds != NULL) {
21261 + for (i = 0; creds[i] != NULL; i++)
21262 + krb5_free_creds(krbContext, creds[i]);
21263 + GSSEAP_FREE(creds);
21265 + if (major == GSS_S_COMPLETE)
21266 + major = *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
21271 +#ifndef HAVE_HEIMDAL_VERSION
21272 +static gss_buffer_desc radiusAvpKrbAttr = {
21273 + sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp"
21278 + * Unfortunately extracting an AD-KDCIssued authorization data element
21279 + * is pretty implementation-dependent. It's not possible to verify the
21280 + * signature ourselves because the ticket session key is not exposed
21281 + * outside GSS. In an ideal world, all AD-KDCIssued elements would be
21282 + * verified by the Kerberos library and authentication would fail if
21283 + * verification failed. We're not quite there yet and as a result have
21284 + * to go through some hoops to get this to work. The alternative would
21285 + * be to sign the authorization data with our long-term key, but it
21286 + * seems a pity to compromise the design because of current implementation
21289 + * (Specifically, the hoops involve a libkrb5 authorisation data plugin
21290 + * that exposes the verified and serialised attribute context through
21291 + * the Kerberos GSS mechanism's naming extensions API.)
21294 +defrostAttrContext(OM_uint32 *minor,
21295 +#ifdef HAVE_HEIMDAL_VERSION
21296 + gss_ctx_id_t glueContext,
21298 + gss_name_t glueName,
21300 + gss_name_t mechName)
21302 + OM_uint32 major, tmpMinor;
21303 +#ifdef HAVE_HEIMDAL_VERSION
21304 + gss_OID_desc oid = { 0 };
21305 + gss_buffer_set_t authData = GSS_C_NO_BUFFER_SET;
21307 + gss_buffer_desc authData = GSS_C_EMPTY_BUFFER;
21308 + gss_buffer_desc authDataDisplay = GSS_C_EMPTY_BUFFER;
21310 + int authenticated, complete;
21313 +#ifdef HAVE_HEIMDAL_VERSION
21314 + major = composeOid(minor,
21315 + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
21316 + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
21317 + KRB5_AUTHDATA_RADIUS_AVP, &oid);
21318 + if (GSS_ERROR(major))
21321 + /* XXX we are assuming that this verifies AD-KDCIssued signature */
21322 + major = gssInquireSecContextByOid(minor, glueContext,
21323 + &oid, &authData);
21324 + if (major == GSS_S_COMPLETE) {
21325 + if (authData == GSS_C_NO_BUFFER_SET || authData->count != 1)
21326 + major = GSS_S_FAILURE;
21328 + major = gssEapImportAttrContext(minor, authData->elements, mechName);
21329 + } else if (major == GSS_S_FAILURE && *minor == ENOENT) {
21330 + /* This is the equivalent of GSS_S_UNAVAILABLE for MIT attr APIs */
21332 + major = GSS_S_COMPLETE;
21335 + gss_release_buffer_set(&tmpMinor, &authData);
21336 + GSSEAP_FREE(oid.elements);
21338 + major = gssGetNameAttribute(minor, glueName, &radiusAvpKrbAttr,
21339 + &authenticated, &complete,
21340 + &authData, &authDataDisplay, &more);
21341 + if (major == GSS_S_COMPLETE) {
21342 + if (authenticated == 0)
21343 + major = GSS_S_BAD_NAME;
21345 + major = gssEapImportAttrContext(minor, &authData, mechName);
21346 + } else if (major == GSS_S_UNAVAILABLE) {
21347 + major = GSS_S_COMPLETE;
21350 + gss_release_buffer(&tmpMinor, &authData);
21351 + gss_release_buffer(&tmpMinor, &authDataDisplay);
21352 +#endif /* HAVE_HEIMDAL_VERSION */
21358 + * Convert a mechanism glue to an EAP mechanism name by displaying and
21359 + * importing it. This also handles the RADIUS attributes.
21362 +gssEapGlueToMechName(OM_uint32 *minor,
21363 + gss_ctx_id_t ctx,
21364 + gss_name_t glueName,
21365 + gss_name_t *pMechName)
21367 + OM_uint32 major, tmpMinor;
21368 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
21370 + *pMechName = GSS_C_NO_NAME;
21372 + major = gssDisplayName(minor, glueName, &nameBuf, NULL);
21373 + if (GSS_ERROR(major))
21376 + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
21377 + ctx->mechanismUsed, pMechName);
21378 + if (GSS_ERROR(major))
21381 + major = defrostAttrContext(minor,
21382 +#ifdef HAVE_HEIMDAL_VERSION
21388 + if (GSS_ERROR(major))
21392 + if (GSS_ERROR(major)) {
21393 + gssReleaseName(&tmpMinor, pMechName);
21394 + *pMechName = GSS_C_NO_NAME;
21397 + gss_release_buffer(&tmpMinor, &nameBuf);
21403 + * Convert an EAP mechanism name to a mechanism glue name by displaying
21404 + * and importing it.
21407 +gssEapMechToGlueName(OM_uint32 *minor,
21408 + gss_name_t mechName,
21409 + gss_name_t *pGlueName)
21411 + OM_uint32 major, tmpMinor;
21412 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
21414 + *pGlueName = GSS_C_NO_NAME;
21416 + major = gssEapDisplayName(minor, mechName, &nameBuf, NULL);
21417 + if (GSS_ERROR(major))
21420 + major = gssImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
21422 + if (GSS_ERROR(major))
21426 + gss_release_buffer(&tmpMinor, &nameBuf);
21432 + * Suck out the analgous elements of a Kerberos GSS context into an EAP
21433 + * one so that the application doesn't know the difference.
21436 +gssEapReauthComplete(OM_uint32 *minor,
21437 + gss_ctx_id_t ctx,
21438 + gss_cred_id_t cred GSSEAP_UNUSED,
21439 + const gss_OID mech,
21440 + OM_uint32 timeRec)
21442 + OM_uint32 major, tmpMinor;
21443 + gss_buffer_set_t keyData = GSS_C_NO_BUFFER_SET;
21444 + krb5_context krbContext = NULL;
21445 +#ifdef HAVE_HEIMDAL_VERSION
21446 + krb5_storage *sp = NULL;
21449 + GSSEAP_KRB_INIT(&krbContext);
21451 + if (!oidEqual(mech, gss_mech_krb5)) {
21452 + major = GSS_S_BAD_MECH;
21456 + /* Get the raw subsession key and encryption type */
21457 +#ifdef HAVE_HEIMDAL_VERSION
21458 +#define KRB_GSS_SUBKEY_COUNT 1 /* encoded session key */
21459 + major = gssInquireSecContextByOid(minor, ctx->reauthCtx,
21460 + GSS_KRB5_GET_SUBKEY_X, &keyData);
21462 +#define KRB_GSS_SUBKEY_COUNT 2 /* raw session key, enctype OID */
21463 + major = gssInquireSecContextByOid(minor, ctx->reauthCtx,
21464 + GSS_C_INQ_SSPI_SESSION_KEY, &keyData);
21466 + if (GSS_ERROR(major))
21469 + if (keyData == GSS_C_NO_BUFFER_SET || keyData->count < KRB_GSS_SUBKEY_COUNT) {
21470 + *minor = GSSEAP_KEY_UNAVAILABLE;
21471 + major = GSS_S_FAILURE;
21475 +#ifdef HAVE_HEIMDAL_VERSION
21476 + sp = krb5_storage_from_mem(keyData->elements[0].value,
21477 + keyData->elements[0].length);
21478 + if (sp == NULL) {
21480 + major = GSS_S_FAILURE;
21484 + *minor = krb5_ret_keyblock(sp, &ctx->rfc3961Key);
21485 + if (*minor != 0) {
21486 + major = GSS_S_FAILURE;
21491 + gss_OID_desc oid;
21494 + oid.length = keyData->elements[1].length;
21495 + oid.elements = keyData->elements[1].value;
21497 + /* GSS_KRB5_SESSION_KEY_ENCTYPE_OID */
21498 + major = decomposeOid(minor,
21499 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04",
21500 + 10, &oid, &suffix);
21501 + if (GSS_ERROR(major))
21504 + ctx->encryptionType = suffix;
21508 + krb5_keyblock key;
21510 + KRB_KEY_LENGTH(&key) = keyData->elements[0].length;
21511 + KRB_KEY_DATA(&key) = keyData->elements[0].value;
21512 + KRB_KEY_TYPE(&key) = ctx->encryptionType;
21514 + *minor = krb5_copy_keyblock_contents(krbContext,
21515 + &key, &ctx->rfc3961Key);
21516 + if (*minor != 0) {
21517 + major = GSS_S_FAILURE;
21521 +#endif /* HAVE_HEIMDAL_VERSION */
21523 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
21524 + &ctx->checksumType);
21525 + if (GSS_ERROR(major))
21528 + if (timeRec != GSS_C_INDEFINITE)
21529 + ctx->expiryTime = time(NULL) + timeRec;
21531 + /* Initialize our sequence state */
21532 + major = sequenceInit(minor,
21533 + &ctx->seqState, ctx->recvSeq,
21534 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
21535 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
21537 + if (GSS_ERROR(major))
21540 + major = GSS_S_COMPLETE;
21543 +#ifdef HAVE_HEIMDAL_VERSION
21545 + krb5_storage_free(sp);
21547 + gss_release_buffer_set(&tmpMinor, &keyData);
21553 + * The remainder of this file consists of wrappers so we can call into the
21554 + * mechanism glue without calling ourselves.
21557 +(*gssInitSecContextNext)(OM_uint32 *,
21564 + gss_channel_bindings_t,
21572 +(*gssAcceptSecContextNext)(OM_uint32 *,
21576 + gss_channel_bindings_t,
21582 + gss_cred_id_t *);
21585 +(*gssReleaseCredNext)(OM_uint32 *, gss_cred_id_t *);
21588 +(*gssReleaseNameNext)(OM_uint32 *, gss_name_t *);
21591 +(*gssInquireSecContextByOidNext)(OM_uint32 *,
21592 + const gss_ctx_id_t,
21594 + gss_buffer_set_t *);
21597 +(*gssDeleteSecContextNext)(OM_uint32 *,
21602 +(*gssDisplayNameNext)(OM_uint32 *,
21608 +(*gssImportNameNext)(OM_uint32 *,
21614 +(*gssStoreCredNext)(OM_uint32 *,
21615 + const gss_cred_id_t,
21616 + gss_cred_usage_t,
21621 + gss_cred_usage_t *);
21624 +(*gssGetNameAttributeNext)(OM_uint32 *,
21633 +#define NEXT_SYMBOL(local, global) do { \
21634 + ((local) = dlsym(RTLD_NEXT, (global))); \
21635 + if ((local) == NULL) { \
21636 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL; \
21637 + major = GSS_S_UNAVAILABLE; \
21638 + /* but continue */ \
21643 +gssEapReauthInitialize(OM_uint32 *minor)
21645 + OM_uint32 major = GSS_S_COMPLETE;
21647 + NEXT_SYMBOL(gssInitSecContextNext, "gss_init_sec_context");
21648 + NEXT_SYMBOL(gssAcceptSecContextNext, "gss_accept_sec_context");
21649 + NEXT_SYMBOL(gssReleaseCredNext, "gss_release_cred");
21650 + NEXT_SYMBOL(gssReleaseNameNext, "gss_release_name");
21651 + NEXT_SYMBOL(gssInquireSecContextByOidNext, "gss_inquire_sec_context_by_oid");
21652 + NEXT_SYMBOL(gssDeleteSecContextNext, "gss_delete_sec_context");
21653 + NEXT_SYMBOL(gssDisplayNameNext, "gss_display_name");
21654 + NEXT_SYMBOL(gssImportNameNext, "gss_import_name");
21655 + NEXT_SYMBOL(gssStoreCredNext, "gss_store_cred");
21656 +#ifndef HAVE_HEIMDAL_VERSION
21657 + NEXT_SYMBOL(gssGetNameAttributeNext, "gss_get_name_attribute");
21664 +gssInitSecContext(OM_uint32 *minor,
21665 + gss_cred_id_t cred,
21666 + gss_ctx_id_t *context_handle,
21667 + gss_name_t target_name,
21668 + gss_OID mech_type,
21669 + OM_uint32 req_flags,
21670 + OM_uint32 time_req,
21671 + gss_channel_bindings_t input_chan_bindings,
21672 + gss_buffer_t input_token,
21673 + gss_OID *actual_mech_type,
21674 + gss_buffer_t output_token,
21675 + OM_uint32 *ret_flags,
21676 + OM_uint32 *time_rec)
21678 + if (gssInitSecContextNext == NULL) {
21679 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21680 + return GSS_S_UNAVAILABLE;
21683 + return gssInitSecContextNext(minor, cred, context_handle,
21684 + target_name, mech_type, req_flags,
21685 + time_req, input_chan_bindings,
21686 + input_token, actual_mech_type,
21687 + output_token, ret_flags, time_rec);
21691 +gssAcceptSecContext(OM_uint32 *minor,
21692 + gss_ctx_id_t *context_handle,
21693 + gss_cred_id_t cred,
21694 + gss_buffer_t input_token,
21695 + gss_channel_bindings_t input_chan_bindings,
21696 + gss_name_t *src_name,
21697 + gss_OID *mech_type,
21698 + gss_buffer_t output_token,
21699 + OM_uint32 *ret_flags,
21700 + OM_uint32 *time_rec,
21701 + gss_cred_id_t *delegated_cred_handle)
21703 + if (gssAcceptSecContextNext == NULL) {
21704 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21705 + return GSS_S_UNAVAILABLE;
21708 + return gssAcceptSecContextNext(minor, context_handle, cred,
21709 + input_token, input_chan_bindings,
21710 + src_name, mech_type, output_token,
21711 + ret_flags, time_rec, delegated_cred_handle);
21715 +gssReleaseCred(OM_uint32 *minor,
21716 + gss_cred_id_t *cred_handle)
21718 + if (gssReleaseCredNext == NULL) {
21719 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21720 + return GSS_S_UNAVAILABLE;
21723 + return gssReleaseCredNext(minor, cred_handle);
21727 +gssReleaseName(OM_uint32 *minor,
21728 + gss_name_t *name)
21730 + if (gssReleaseName == NULL) {
21731 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21732 + return GSS_S_UNAVAILABLE;
21735 + return gssReleaseNameNext(minor, name);
21739 +gssDeleteSecContext(OM_uint32 *minor,
21740 + gss_ctx_id_t *context_handle,
21741 + gss_buffer_t output_token)
21743 + if (gssDeleteSecContextNext == NULL) {
21744 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21745 + return GSS_S_UNAVAILABLE;
21748 + return gssDeleteSecContextNext(minor, context_handle, output_token);
21752 +gssDisplayName(OM_uint32 *minor,
21754 + gss_buffer_t buffer,
21755 + gss_OID *name_type)
21757 + if (gssDisplayNameNext == NULL) {
21758 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21759 + return GSS_S_UNAVAILABLE;
21762 + return gssDisplayNameNext(minor, name, buffer, name_type);
21766 +gssImportName(OM_uint32 *minor,
21767 + gss_buffer_t buffer,
21768 + gss_OID name_type,
21769 + gss_name_t *name)
21771 + if (gssImportNameNext == NULL) {
21772 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21773 + return GSS_S_UNAVAILABLE;
21776 + return gssImportNameNext(minor, buffer, name_type, name);
21780 +gssInquireSecContextByOid(OM_uint32 *minor,
21781 + const gss_ctx_id_t context_handle,
21782 + const gss_OID desired_object,
21783 + gss_buffer_set_t *data_set)
21785 + if (gssInquireSecContextByOidNext == NULL) {
21786 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21787 + return GSS_S_UNAVAILABLE;
21790 + return gssInquireSecContextByOidNext(minor, context_handle,
21791 + desired_object, data_set);
21795 +gssStoreCred(OM_uint32 *minor,
21796 + const gss_cred_id_t input_cred_handle,
21797 + gss_cred_usage_t input_usage,
21798 + const gss_OID desired_mech,
21799 + OM_uint32 overwrite_cred,
21800 + OM_uint32 default_cred,
21801 + gss_OID_set *elements_stored,
21802 + gss_cred_usage_t *cred_usage_stored)
21804 + if (gssStoreCredNext == NULL) {
21805 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21806 + return GSS_S_UNAVAILABLE;
21809 + return gssStoreCredNext(minor, input_cred_handle, input_usage,
21810 + desired_mech, overwrite_cred, default_cred,
21811 + elements_stored, cred_usage_stored);
21815 +gssGetNameAttribute(OM_uint32 *minor,
21817 + gss_buffer_t attr,
21818 + int *authenticated,
21820 + gss_buffer_t value,
21821 + gss_buffer_t display_value,
21824 + if (gssGetNameAttributeNext == NULL) {
21825 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21826 + return GSS_S_UNAVAILABLE;
21829 + return gssGetNameAttributeNext(minor, name, attr, authenticated, complete,
21830 + value, display_value, more);
21832 diff --git a/mech_eap/util_reauth.h b/mech_eap/util_reauth.h
21833 new file mode 100644
21834 index 0000000..9b9f264
21836 +++ b/mech_eap/util_reauth.h
21839 + * Copyright (c) 2011, JANET(UK)
21840 + * All rights reserved.
21842 + * Redistribution and use in source and binary forms, with or without
21843 + * modification, are permitted provided that the following conditions
21846 + * 1. Redistributions of source code must retain the above copyright
21847 + * notice, this list of conditions and the following disclaimer.
21849 + * 2. Redistributions in binary form must reproduce the above copyright
21850 + * notice, this list of conditions and the following disclaimer in the
21851 + * documentation and/or other materials provided with the distribution.
21853 + * 3. Neither the name of JANET(UK) nor the names of its contributors
21854 + * may be used to endorse or promote products derived from this software
21855 + * without specific prior written permission.
21857 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21858 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21859 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21860 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21861 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21862 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21863 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21864 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21865 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21866 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21871 + * Fast reauthentication support.
21874 +#include "gssapiP_eap.h"
21876 +#ifndef _UTIL_REAUTH_H_
21877 +#define _UTIL_REAUTH_H_ 1
21879 +/* AD element containing serialised AVPs. */
21880 +#define KRB5_AUTHDATA_RADIUS_AVP 513
21883 +gssInitSecContext(OM_uint32 *minor,
21884 + gss_cred_id_t cred,
21885 + gss_ctx_id_t *context_handle,
21886 + gss_name_t target_name,
21887 + gss_OID mech_type,
21888 + OM_uint32 req_flags,
21889 + OM_uint32 time_req,
21890 + gss_channel_bindings_t input_chan_bindings,
21891 + gss_buffer_t input_token,
21892 + gss_OID *actual_mech_type,
21893 + gss_buffer_t output_token,
21894 + OM_uint32 *ret_flags,
21895 + OM_uint32 *time_rec);
21898 +gssAcceptSecContext(OM_uint32 *minor,
21899 + gss_ctx_id_t *context_handle,
21900 + gss_cred_id_t cred,
21901 + gss_buffer_t input_token,
21902 + gss_channel_bindings_t input_chan_bindings,
21903 + gss_name_t *src_name,
21904 + gss_OID *mech_type,
21905 + gss_buffer_t output_token,
21906 + OM_uint32 *ret_flags,
21907 + OM_uint32 *time_rec,
21908 + gss_cred_id_t *delegated_cred_handle);
21911 +gssReleaseCred(OM_uint32 *minor,
21912 + gss_cred_id_t *cred_handle);
21915 +gssReleaseName(OM_uint32 *minor,
21916 + gss_name_t *name);
21919 +gssDeleteSecContext(OM_uint32 *minor,
21920 + gss_ctx_id_t *context_handle,
21921 + gss_buffer_t output_token);
21924 +gssInquireSecContextByOid(OM_uint32 *minor,
21925 + const gss_ctx_id_t context_handle,
21926 + const gss_OID desired_object,
21927 + gss_buffer_set_t *data_set);
21930 +gssStoreCred(OM_uint32 *minor,
21931 + const gss_cred_id_t input_cred_handle,
21932 + gss_cred_usage_t input_usage,
21933 + const gss_OID desired_mech,
21934 + OM_uint32 overwrite_cred,
21935 + OM_uint32 default_cred,
21936 + gss_OID_set *elements_stored,
21937 + gss_cred_usage_t *cred_usage_stored);
21940 +gssGetNameAttribute(OM_uint32 *minor,
21942 + gss_buffer_t attr,
21943 + int *authenticated,
21945 + gss_buffer_t value,
21946 + gss_buffer_t display_value,
21950 +gssEapMakeReauthCreds(OM_uint32 *minor,
21951 + gss_ctx_id_t ctx,
21952 + gss_cred_id_t cred,
21953 + gss_buffer_t credBuf);
21956 +gssEapStoreReauthCreds(OM_uint32 *minor,
21957 + gss_ctx_id_t ctx,
21958 + gss_cred_id_t cred,
21959 + gss_buffer_t credBuf);
21963 +gssEapGlueToMechName(OM_uint32 *minor,
21964 + gss_ctx_id_t glueContext,
21965 + gss_name_t glueName,
21966 + gss_name_t *pMechName);
21969 +gssEapMechToGlueName(OM_uint32 *minor,
21970 + gss_name_t mechName,
21971 + gss_name_t *pGlueName);
21974 +gssEapReauthComplete(OM_uint32 *minor,
21975 + gss_ctx_id_t ctx,
21976 + gss_cred_id_t cred,
21977 + const gss_OID mech,
21978 + OM_uint32 timeRec);
21981 +gssEapReauthInitialize(OM_uint32 *minor);
21984 +gssEapCanReauthP(gss_cred_id_t cred,
21985 + gss_name_t target,
21986 + OM_uint32 timeReq);
21988 +#endif /* _UTIL_REAUTH_H_ */
21989 diff --git a/mech_eap/util_saml.cpp b/mech_eap/util_saml.cpp
21990 new file mode 100644
21991 index 0000000..ce7582e
21993 +++ b/mech_eap/util_saml.cpp
21996 + * Copyright (c) 2011, JANET(UK)
21997 + * All rights reserved.
21999 + * Redistribution and use in source and binary forms, with or without
22000 + * modification, are permitted provided that the following conditions
22003 + * 1. Redistributions of source code must retain the above copyright
22004 + * notice, this list of conditions and the following disclaimer.
22006 + * 2. Redistributions in binary form must reproduce the above copyright
22007 + * notice, this list of conditions and the following disclaimer in the
22008 + * documentation and/or other materials provided with the distribution.
22010 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22011 + * may be used to endorse or promote products derived from this software
22012 + * without specific prior written permission.
22014 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22015 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22016 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22017 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22018 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22019 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22020 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22021 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22022 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22023 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22028 + * SAML attribute provider implementation.
22031 +#include "gssapiP_eap.h"
22033 +#include <sstream>
22035 +#include <xercesc/util/XMLUniDefs.hpp>
22036 +#include <xmltooling/unicode.h>
22037 +#include <xmltooling/XMLToolingConfig.h>
22038 +#include <xmltooling/util/XMLHelper.h>
22039 +#include <xmltooling/util/ParserPool.h>
22040 +#include <xmltooling/util/DateTime.h>
22042 +#include <saml/exceptions.h>
22043 +#include <saml/SAMLConfig.h>
22044 +#include <saml/saml1/core/Assertions.h>
22045 +#include <saml/saml2/core/Assertions.h>
22046 +#include <saml/saml2/metadata/Metadata.h>
22047 +#include <saml/saml2/metadata/MetadataProvider.h>
22049 +using namespace xmltooling;
22050 +using namespace opensaml::saml2md;
22051 +using namespace opensaml;
22052 +using namespace xercesc;
22053 +using namespace std;
22055 +static const XMLCh
22056 +base64Binary[] = {'b','a','s','e','6','4','B','i','n','a','r','y',0};
22059 + * gss_eap_saml_assertion_provider is for retrieving the underlying
22062 +gss_eap_saml_assertion_provider::gss_eap_saml_assertion_provider(void)
22064 + m_assertion = NULL;
22065 + m_authenticated = false;
22068 +gss_eap_saml_assertion_provider::~gss_eap_saml_assertion_provider(void)
22070 + delete m_assertion;
22074 +gss_eap_saml_assertion_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
22075 + const gss_eap_attr_provider *ctx)
22077 + /* Then we may be creating from an existing attribute context */
22078 + const gss_eap_saml_assertion_provider *saml;
22080 + GSSEAP_ASSERT(m_assertion == NULL);
22082 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx))
22085 + saml = static_cast<const gss_eap_saml_assertion_provider *>(ctx);
22086 + setAssertion(saml->getAssertion(), saml->authenticated());
22092 +gss_eap_saml_assertion_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
22093 + const gss_cred_id_t gssCred,
22094 + const gss_ctx_id_t gssCtx)
22096 + const gss_eap_radius_attr_provider *radius;
22097 + gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
22098 + int authenticated, complete;
22101 + GSSEAP_ASSERT(m_assertion == NULL);
22103 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
22107 + * XXX TODO we need to support draft-howlett-radius-saml-attr-00
22109 + radius = static_cast<const gss_eap_radius_attr_provider *>
22110 + (m_manager->getProvider(ATTR_TYPE_RADIUS));
22111 + if (radius != NULL &&
22112 + radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION,
22113 + VENDORPEC_UKERNA,
22114 + &authenticated, &complete, &value)) {
22115 + setAssertion(&value, authenticated);
22116 + gss_release_buffer(&minor, &value);
22118 + m_assertion = NULL;
22125 +gss_eap_saml_assertion_provider::setAssertion(const saml2::Assertion *assertion,
22126 + bool authenticated)
22129 + delete m_assertion;
22131 + if (assertion != NULL) {
22133 + m_assertion = (saml2::Assertion *)((void *)assertion->clone());
22135 + m_assertion = dynamic_cast<saml2::Assertion *>(assertion->clone());
22137 + m_authenticated = authenticated;
22139 + m_assertion = NULL;
22140 + m_authenticated = false;
22145 +gss_eap_saml_assertion_provider::setAssertion(const gss_buffer_t buffer,
22146 + bool authenticated)
22148 + delete m_assertion;
22150 + m_assertion = parseAssertion(buffer);
22151 + m_authenticated = (m_assertion != NULL && authenticated);
22154 +saml2::Assertion *
22155 +gss_eap_saml_assertion_provider::parseAssertion(const gss_buffer_t buffer)
22157 + string str((char *)buffer->value, buffer->length);
22158 + istringstream istream(str);
22159 + DOMDocument *doc;
22160 + const XMLObjectBuilder *b;
22163 + doc = XMLToolingConfig::getConfig().getParser().parse(istream);
22167 + b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
22170 + return (saml2::Assertion *)((void *)b->buildFromDocument(doc));
22172 + return dynamic_cast<saml2::Assertion *>(b->buildFromDocument(doc));
22174 + } catch (exception &e) {
22180 +gss_eap_saml_assertion_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
22181 + void *data) const
22185 + /* just add the prefix */
22186 + if (m_assertion != NULL)
22187 + ret = addAttribute(m_manager, this, GSS_C_NO_BUFFER, data);
22195 +gss_eap_saml_assertion_provider::setAttribute(int complete GSSEAP_UNUSED,
22196 + const gss_buffer_t attr,
22197 + const gss_buffer_t value)
22199 + if (attr == GSS_C_NO_BUFFER || attr->length == 0) {
22200 + setAssertion(value);
22208 +gss_eap_saml_assertion_provider::deleteAttribute(const gss_buffer_t value GSSEAP_UNUSED)
22210 + delete m_assertion;
22211 + m_assertion = NULL;
22212 + m_authenticated = false;
22218 +gss_eap_saml_assertion_provider::getExpiryTime(void) const
22220 + saml2::Conditions *conditions;
22221 + time_t expiryTime = 0;
22223 + if (m_assertion == NULL)
22226 + conditions = m_assertion->getConditions();
22228 + if (conditions != NULL && conditions->getNotOnOrAfter() != NULL)
22229 + expiryTime = conditions->getNotOnOrAfter()->getEpoch();
22231 + return expiryTime;
22235 +gss_eap_saml_assertion_provider::mapException(OM_uint32 *minor,
22236 + std::exception &e) const
22238 + if (typeid(e) == typeid(SecurityPolicyException))
22239 + *minor = GSSEAP_SAML_SEC_POLICY_FAILURE;
22240 + else if (typeid(e) == typeid(BindingException))
22241 + *minor = GSSEAP_SAML_BINDING_FAILURE;
22242 + else if (typeid(e) == typeid(ProfileException))
22243 + *minor = GSSEAP_SAML_PROFILE_FAILURE;
22244 + else if (typeid(e) == typeid(FatalProfileException))
22245 + *minor = GSSEAP_SAML_FATAL_PROFILE_FAILURE;
22246 + else if (typeid(e) == typeid(RetryableProfileException))
22247 + *minor = GSSEAP_SAML_RETRY_PROFILE_FAILURE;
22248 + else if (typeid(e) == typeid(MetadataException))
22249 + *minor = GSSEAP_SAML_METADATA_FAILURE;
22251 + return GSS_S_CONTINUE_NEEDED;
22253 + gssEapSaveStatusInfo(*minor, "%s", e.what());
22255 + return GSS_S_FAILURE;
22259 +gss_eap_saml_assertion_provider::getAttribute(const gss_buffer_t attr,
22260 + int *authenticated,
22262 + gss_buffer_t value,
22263 + gss_buffer_t display_value GSSEAP_UNUSED,
22268 + if (attr != GSS_C_NO_BUFFER && attr->length != 0)
22271 + if (m_assertion == NULL)
22277 + if (authenticated != NULL)
22278 + *authenticated = m_authenticated;
22279 + if (complete != NULL)
22280 + *complete = true;
22282 + XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str);
22284 + if (value != NULL)
22285 + duplicateBuffer(str, value);
22286 + if (display_value != NULL)
22287 + duplicateBuffer(str, display_value);
22295 +gss_eap_saml_assertion_provider::mapToAny(int authenticated,
22296 + gss_buffer_t type_id GSSEAP_UNUSED) const
22298 + if (authenticated && !m_authenticated)
22299 + return (gss_any_t)NULL;
22301 + return (gss_any_t)m_assertion;
22305 +gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
22306 + gss_any_t input) const
22308 + delete ((saml2::Assertion *)input);
22312 +gss_eap_saml_assertion_provider::prefix(void) const
22314 + return "urn:ietf:params:gss-eap:saml-aaa-assertion";
22318 +gss_eap_saml_assertion_provider::init(void)
22320 + bool ret = false;
22323 + ret = SAMLConfig::getConfig().init();
22324 + } catch (exception &e) {
22328 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML_ASSERTION, createAttrContext);
22334 +gss_eap_saml_assertion_provider::finalize(void)
22336 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML_ASSERTION);
22339 +gss_eap_attr_provider *
22340 +gss_eap_saml_assertion_provider::createAttrContext(void)
22342 + return new gss_eap_saml_assertion_provider;
22345 +saml2::Assertion *
22346 +gss_eap_saml_assertion_provider::initAssertion(void)
22348 + delete m_assertion;
22349 + m_assertion = saml2::AssertionBuilder::buildAssertion();
22350 + m_authenticated = false;
22352 + return m_assertion;
22356 + * gss_eap_saml_attr_provider is for retrieving the underlying attributes.
22359 +gss_eap_saml_attr_provider::getAssertion(int *authenticated,
22360 + saml2::Assertion **pAssertion,
22361 + bool createIfAbsent) const
22363 + gss_eap_saml_assertion_provider *saml;
22365 + if (authenticated != NULL)
22366 + *authenticated = false;
22367 + if (pAssertion != NULL)
22368 + *pAssertion = NULL;
22370 + saml = static_cast<gss_eap_saml_assertion_provider *>
22371 + (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
22372 + if (saml == NULL)
22375 + if (authenticated != NULL)
22376 + *authenticated = saml->authenticated();
22377 + if (pAssertion != NULL)
22378 + *pAssertion = saml->getAssertion();
22380 + if (saml->getAssertion() == NULL) {
22381 + if (createIfAbsent) {
22382 + if (authenticated != NULL)
22383 + *authenticated = false;
22384 + if (pAssertion != NULL)
22385 + *pAssertion = saml->initAssertion();
22394 +gss_eap_saml_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
22395 + void *data) const
22397 + saml2::Assertion *assertion;
22398 + int authenticated;
22400 + if (!getAssertion(&authenticated, &assertion))
22404 + * Note: the first prefix is added by the attribute provider manager
22406 + * From draft-hartman-gss-eap-naming-00:
22408 + * Each attribute carried in the assertion SHOULD also be a GSS name
22409 + * attribute. The name of this attribute has three parts, all separated
22410 + * by an ASCII space character. The first part is
22411 + * urn:ietf:params:gss-eap:saml-attr. The second part is the URI for
22412 + * the SAML attribute name format. The final part is the name of the
22413 + * SAML attribute. If the mechanism performs an additional attribute
22414 + * query, the retrieved attributes SHOULD be GSS-API name attributes
22415 + * using the same name syntax.
22417 + /* For each attribute statement, look for an attribute match */
22418 + const vector <saml2::AttributeStatement *> &statements =
22419 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22421 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22422 + s != statements.end();
22424 + const vector<saml2::Attribute*> &attrs =
22425 + const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
22427 + for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
22428 + const XMLCh *attributeName, *attributeNameFormat;
22429 + XMLCh space[2] = { ' ', 0 };
22430 + gss_buffer_desc utf8;
22432 + attributeName = (*a)->getName();
22433 + attributeNameFormat = (*a)->getNameFormat();
22434 + if (attributeNameFormat == NULL || attributeNameFormat[0] == '\0')
22435 + attributeNameFormat = saml2::Attribute::UNSPECIFIED;
22437 + XMLCh qualifiedName[XMLString::stringLen(attributeNameFormat) + 1 +
22438 + XMLString::stringLen(attributeName) + 1];
22439 + XMLString::copyString(qualifiedName, attributeNameFormat);
22440 + XMLString::catString(qualifiedName, space);
22441 + XMLString::catString(qualifiedName, attributeName);
22443 + utf8.value = (void *)toUTF8(qualifiedName);
22444 + utf8.length = strlen((char *)utf8.value);
22446 + if (!addAttribute(m_manager, this, &utf8, data))
22454 +static BaseRefVectorOf<XMLCh> *
22455 +decomposeAttributeName(const gss_buffer_t attr)
22457 + BaseRefVectorOf<XMLCh> *components;
22458 + string str((const char *)attr->value, attr->length);
22459 + auto_ptr_XMLCh qualifiedAttr(str.c_str());
22461 + components = XMLString::tokenizeString(qualifiedAttr.get());
22463 + if (components->size() != 2) {
22464 + delete components;
22465 + components = NULL;
22468 + return components;
22472 +gss_eap_saml_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
22473 + const gss_buffer_t attr,
22474 + const gss_buffer_t value)
22476 + saml2::Assertion *assertion;
22477 + saml2::Attribute *attribute;
22478 + saml2::AttributeValue *attributeValue;
22479 + saml2::AttributeStatement *attributeStatement;
22481 + if (!getAssertion(NULL, &assertion, true))
22484 + if (assertion->getAttributeStatements().size() != 0) {
22485 + attributeStatement = assertion->getAttributeStatements().front();
22487 + attributeStatement = saml2::AttributeStatementBuilder::buildAttributeStatement();
22488 + assertion->getAttributeStatements().push_back(attributeStatement);
22491 + /* Check the attribute name consists of name format | whsp | name */
22492 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22493 + if (components == NULL)
22496 + attribute = saml2::AttributeBuilder::buildAttribute();
22497 + attribute->setNameFormat(components->elementAt(0));
22498 + attribute->setName(components->elementAt(1));
22500 + attributeValue = saml2::AttributeValueBuilder::buildAttributeValue();
22501 + auto_ptr_XMLCh unistr((char *)value->value, value->length);
22502 + attributeValue->setTextContent(unistr.get());
22504 + attribute->getAttributeValues().push_back(attributeValue);
22506 + GSSEAP_ASSERT(attributeStatement != NULL);
22507 + attributeStatement->getAttributes().push_back(attribute);
22509 + delete components;
22515 +gss_eap_saml_attr_provider::deleteAttribute(const gss_buffer_t attr)
22517 + saml2::Assertion *assertion;
22518 + bool ret = false;
22520 + if (!getAssertion(NULL, &assertion) ||
22521 + assertion->getAttributeStatements().size() == 0)
22524 + /* Check the attribute name consists of name format | whsp | name */
22525 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22526 + if (components == NULL)
22529 + /* For each attribute statement, look for an attribute match */
22530 + const vector<saml2::AttributeStatement *> &statements =
22531 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22533 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22534 + s != statements.end();
22536 + const vector<saml2::Attribute *> &attrs =
22537 + const_cast<const saml2::AttributeStatement *>(*s)->getAttributes();
22538 + ssize_t index = -1, i = 0;
22540 + /* There's got to be an easier way to do this */
22541 + for (vector<saml2::Attribute *>::const_iterator a = attrs.begin();
22542 + a != attrs.end();
22544 + if (XMLString::equals((*a)->getNameFormat(), components->elementAt(0)) &&
22545 + XMLString::equals((*a)->getName(), components->elementAt(1))) {
22551 + if (index != -1) {
22552 + (*s)->getAttributes().erase((*s)->getAttributes().begin() + index);
22557 + delete components;
22563 +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr,
22564 + int *authenticated,
22566 + const saml2::Attribute **pAttribute) const
22568 + saml2::Assertion *assertion;
22570 + if (authenticated != NULL)
22571 + *authenticated = false;
22572 + if (complete != NULL)
22573 + *complete = true;
22574 + *pAttribute = NULL;
22576 + if (!getAssertion(authenticated, &assertion) ||
22577 + assertion->getAttributeStatements().size() == 0)
22580 + /* Check the attribute name consists of name format | whsp | name */
22581 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22582 + if (components == NULL)
22585 + /* For each attribute statement, look for an attribute match */
22586 + const vector <saml2::AttributeStatement *> &statements =
22587 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22588 + const saml2::Attribute *ret = NULL;
22590 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22591 + s != statements.end();
22593 + const vector<saml2::Attribute *> &attrs =
22594 + const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
22596 + for (vector<saml2::Attribute *>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
22597 + const XMLCh *attributeName, *attributeNameFormat;
22599 + attributeName = (*a)->getName();
22600 + attributeNameFormat = (*a)->getNameFormat();
22601 + if (attributeNameFormat == NULL || attributeNameFormat[0] == '\0')
22602 + attributeNameFormat = saml2::Attribute::UNSPECIFIED;
22604 + if (XMLString::equals(attributeNameFormat, components->elementAt(0)) &&
22605 + XMLString::equals(attributeName, components->elementAt(1))) {
22615 + delete components;
22617 + *pAttribute = ret;
22619 + return (ret != NULL);
22623 +isBase64EncodedAttributeValueP(const saml2::AttributeValue *av)
22625 + const xmltooling::QName *type = av->getSchemaType();
22627 + if (type == NULL)
22630 + if (!type->hasNamespaceURI() ||
22631 + !XMLString::equals(type->getNamespaceURI(), xmlconstants::XSD_NS))
22634 + if (!type->hasLocalPart() ||
22635 + !XMLString::equals(type->getLocalPart(), base64Binary))
22642 +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr,
22643 + int *authenticated,
22645 + gss_buffer_t value,
22646 + gss_buffer_t display_value,
22649 + const saml2::Attribute *a;
22650 + const saml2::AttributeValue *av;
22651 + int nvalues, i = *more;
22655 + if (!getAttribute(attr, authenticated, complete, &a))
22658 + nvalues = a->getAttributeValues().size();
22662 + if (i >= nvalues)
22665 + av = (const saml2::AttributeValue *)((void *)(a->getAttributeValues().at(i)));
22667 + av = dynamic_cast<const saml2::AttributeValue *>(a->getAttributeValues().at(i));
22669 + if (av != NULL) {
22670 + bool base64Encoded = isBase64EncodedAttributeValueP(av);
22672 + if (value != NULL) {
22673 + char *stringValue = toUTF8(av->getTextContent(), true);
22674 + size_t stringValueLen = strlen(stringValue);
22676 + if (base64Encoded) {
22677 + ssize_t octetLen;
22679 + value->value = GSSEAP_MALLOC(stringValueLen);
22680 + if (value->value == NULL) {
22681 + GSSEAP_FREE(stringValue);
22682 + throw new std::bad_alloc;
22685 + octetLen = base64Decode(stringValue, value->value);
22686 + if (octetLen < 0) {
22687 + GSSEAP_FREE(value->value);
22688 + GSSEAP_FREE(stringValue);
22689 + value->value = NULL;
22692 + value->length = octetLen;
22693 + GSSEAP_FREE(stringValue);
22695 + value->value = stringValue;
22696 + value->length = stringValueLen;
22699 + if (display_value != NULL && base64Encoded == false) {
22700 + display_value->value = toUTF8(av->getTextContent(), true);
22701 + display_value->length = strlen((char *)value->value);
22705 + if (nvalues > ++i)
22712 +gss_eap_saml_attr_provider::mapToAny(int authenticated GSSEAP_UNUSED,
22713 + gss_buffer_t type_id GSSEAP_UNUSED) const
22715 + return (gss_any_t)NULL;
22719 +gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
22720 + gss_any_t input GSSEAP_UNUSED) const
22725 +gss_eap_saml_attr_provider::prefix(void) const
22727 + return "urn:ietf:params:gss-eap:saml-attr";
22731 +gss_eap_saml_attr_provider::init(void)
22733 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML, createAttrContext);
22738 +gss_eap_saml_attr_provider::finalize(void)
22740 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML);
22743 +gss_eap_attr_provider *
22744 +gss_eap_saml_attr_provider::createAttrContext(void)
22746 + return new gss_eap_saml_attr_provider;
22750 +gssEapSamlAttrProvidersInit(OM_uint32 *minor)
22752 + if (!gss_eap_saml_assertion_provider::init() ||
22753 + !gss_eap_saml_attr_provider::init()) {
22754 + *minor = GSSEAP_SAML_INIT_FAILURE;
22755 + return GSS_S_FAILURE;
22758 + return GSS_S_COMPLETE;
22762 +gssEapSamlAttrProvidersFinalize(OM_uint32 *minor)
22764 + gss_eap_saml_attr_provider::finalize();
22765 + gss_eap_saml_assertion_provider::finalize();
22768 + return GSS_S_COMPLETE;
22770 diff --git a/mech_eap/util_saml.h b/mech_eap/util_saml.h
22771 new file mode 100644
22772 index 0000000..9110ad4
22774 +++ b/mech_eap/util_saml.h
22777 + * Copyright (c) 2011, JANET(UK)
22778 + * All rights reserved.
22780 + * Redistribution and use in source and binary forms, with or without
22781 + * modification, are permitted provided that the following conditions
22784 + * 1. Redistributions of source code must retain the above copyright
22785 + * notice, this list of conditions and the following disclaimer.
22787 + * 2. Redistributions in binary form must reproduce the above copyright
22788 + * notice, this list of conditions and the following disclaimer in the
22789 + * documentation and/or other materials provided with the distribution.
22791 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22792 + * may be used to endorse or promote products derived from this software
22793 + * without specific prior written permission.
22795 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22796 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22797 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22798 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22799 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22800 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22801 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22802 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22803 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22804 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22809 + * SAML attribute provider.
22812 +#ifndef _UTIL_SAML_H_
22813 +#define _UTIL_SAML_H_ 1
22815 +#ifdef __cplusplus
22817 +namespace opensaml {
22818 + namespace saml2 {
22825 +struct gss_eap_saml_assertion_provider : gss_eap_attr_provider {
22827 + gss_eap_saml_assertion_provider(void);
22828 + ~gss_eap_saml_assertion_provider(void);
22830 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
22831 + const gss_eap_attr_provider *ctx);
22832 + bool initWithGssContext(const gss_eap_attr_ctx *source,
22833 + const gss_cred_id_t cred,
22834 + const gss_ctx_id_t ctx);
22836 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
22837 + bool setAttribute(int complete,
22838 + const gss_buffer_t attr,
22839 + const gss_buffer_t value);
22840 + bool deleteAttribute(const gss_buffer_t value);
22841 + bool getAttribute(const gss_buffer_t attr,
22842 + int *authenticated,
22844 + gss_buffer_t value,
22845 + gss_buffer_t display_value,
22846 + int *more) const;
22847 + gss_any_t mapToAny(int authenticated,
22848 + gss_buffer_t type_id) const;
22849 + void releaseAnyNameMapping(gss_buffer_t type_id,
22850 + gss_any_t input) const;
22852 + const char *prefix(void) const;
22853 + const char *name(void) const { return NULL; }
22854 + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
22855 + JSONObject &object GSSEAP_UNUSED) {
22858 + JSONObject jsonRepresentation(void) const {
22859 + return JSONObject::null();
22862 + opensaml::saml2::Assertion *initAssertion(void);
22864 + opensaml::saml2::Assertion *getAssertion(void) const {
22865 + return m_assertion;
22867 + bool authenticated(void) const {
22868 + return m_authenticated;
22871 + time_t getExpiryTime(void) const;
22872 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
22874 + static bool init(void);
22875 + static void finalize(void);
22877 + static gss_eap_attr_provider *createAttrContext(void);
22880 + static opensaml::saml2::Assertion *
22881 + parseAssertion(const gss_buffer_t buffer);
22883 + void setAssertion(const opensaml::saml2::Assertion *assertion,
22884 + bool authenticated = false);
22885 + void setAssertion(const gss_buffer_t buffer,
22886 + bool authenticated = false);
22888 + opensaml::saml2::Assertion *m_assertion;
22889 + bool m_authenticated;
22892 +struct gss_eap_saml_attr_provider : gss_eap_attr_provider {
22894 + gss_eap_saml_attr_provider(void) {}
22895 + ~gss_eap_saml_attr_provider(void) {}
22897 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
22898 + bool setAttribute(int complete,
22899 + const gss_buffer_t attr,
22900 + const gss_buffer_t value);
22901 + bool deleteAttribute(const gss_buffer_t value);
22902 + bool getAttribute(const gss_buffer_t attr,
22903 + int *authenticated,
22905 + gss_buffer_t value,
22906 + gss_buffer_t display_value,
22907 + int *more) const;
22908 + gss_any_t mapToAny(int authenticated,
22909 + gss_buffer_t type_id) const;
22910 + void releaseAnyNameMapping(gss_buffer_t type_id,
22911 + gss_any_t input) const;
22913 + const char *prefix(void) const;
22914 + const char *name(void) const {
22917 + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
22918 + JSONObject &object GSSEAP_UNUSED) {
22921 + JSONObject jsonRepresentation(void) const {
22922 + return JSONObject::null();
22925 + bool getAttribute(const gss_buffer_t attr,
22926 + int *authenticated,
22928 + const opensaml::saml2::Attribute **pAttribute) const;
22929 + bool getAssertion(int *authenticated,
22930 + opensaml::saml2::Assertion **pAssertion,
22931 + bool createIfAbsent = false) const;
22933 + static bool init(void);
22934 + static void finalize(void);
22936 + static gss_eap_attr_provider *createAttrContext(void);
22944 +OM_uint32 gssEapSamlAttrProvidersInit(OM_uint32 *minor);
22945 +OM_uint32 gssEapSamlAttrProvidersFinalize(OM_uint32 *minor);
22947 +#ifdef __cplusplus
22951 +#endif /* _UTIL_SAML_H_ */
22952 diff --git a/mech_eap/util_shib.cpp b/mech_eap/util_shib.cpp
22953 new file mode 100644
22954 index 0000000..f8c702b
22956 +++ b/mech_eap/util_shib.cpp
22959 + * Copyright (c) 2011, JANET(UK)
22960 + * All rights reserved.
22962 + * Redistribution and use in source and binary forms, with or without
22963 + * modification, are permitted provided that the following conditions
22966 + * 1. Redistributions of source code must retain the above copyright
22967 + * notice, this list of conditions and the following disclaimer.
22969 + * 2. Redistributions in binary form must reproduce the above copyright
22970 + * notice, this list of conditions and the following disclaimer in the
22971 + * documentation and/or other materials provided with the distribution.
22973 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22974 + * may be used to endorse or promote products derived from this software
22975 + * without specific prior written permission.
22977 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22978 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22979 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22980 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22981 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22982 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22983 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22984 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22985 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22986 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22990 + * Copyright 2001-2009 Internet2
22992 + * Licensed under the Apache License, Version 2.0 (the "License");
22993 + * you may not use this file except in compliance with the License.
22994 + * You may obtain a copy of the License at
22996 + * http://www.apache.org/licenses/LICENSE-2.0
22998 + * Unless required by applicable law or agreed to in writing, software
22999 + * distributed under the License is distributed on an "AS IS" BASIS,
23000 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23001 + * See the License for the specific language governing permissions and
23002 + * limitations under the License.
23006 + * Local attribute provider implementation.
23009 +#include "gssapiP_eap.h"
23011 +#include <xmltooling/XMLObject.h>
23012 +#ifndef HAVE_OPENSAML
23013 +#include <xmltooling/XMLToolingConfig.h>
23014 +#include <xmltooling/util/ParserPool.h>
23017 +#include <saml/saml2/core/Assertions.h>
23019 +#include <shibsp/exceptions.h>
23020 +#include <shibsp/attribute/SimpleAttribute.h>
23021 +#include <shibsp/attribute/BinaryAttribute.h>
23022 +#include <shibsp/attribute/ScopedAttribute.h>
23023 +#include <shibresolver/resolver.h>
23025 +#include <sstream>
23027 +using namespace shibsp;
23028 +using namespace shibresolver;
23029 +using namespace xmltooling;
23030 +using namespace std;
23031 +#ifdef HAVE_OPENSAML
23032 +using namespace opensaml::saml2md;
23033 +using namespace opensaml;
23035 +using namespace xercesc;
23038 +gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void)
23040 + m_initialized = false;
23041 + m_authenticated = false;
23044 +gss_eap_shib_attr_provider::~gss_eap_shib_attr_provider(void)
23046 + for_each(m_attributes.begin(),
23047 + m_attributes.end(),
23048 + xmltooling::cleanup<Attribute>())
23053 +gss_eap_shib_attr_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
23054 + const gss_eap_attr_provider *ctx)
23056 + const gss_eap_shib_attr_provider *shib;
23058 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx)) {
23062 + m_authenticated = false;
23064 + shib = static_cast<const gss_eap_shib_attr_provider *>(ctx);
23065 + if (shib != NULL) {
23066 + m_attributes = duplicateAttributes(shib->getAttributes());
23067 + m_authenticated = shib->authenticated();
23070 + m_initialized = true;
23076 +gss_eap_shib_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
23077 + const gss_cred_id_t gssCred,
23078 + const gss_ctx_id_t gssCtx)
23080 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
23083 + auto_ptr<ShibbolethResolver> resolver(ShibbolethResolver::create());
23086 + * For now, leave ApplicationID defaulted.
23087 + * Later on, we could allow this via config option to the mechanism
23088 + * or rely on an SPRequest interface to pass in a URI identifying the
23092 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
23093 + if (gssCred != GSS_C_NO_CREDENTIAL &&
23094 + gssEapDisplayName(&minor, gssCred->name, &nameBuf, NULL) == GSS_S_COMPLETE) {
23095 + resolver->setApplicationID((const char *)nameBuf.value);
23096 + gss_release_buffer(&minor, &nameBuf);
23100 + gss_buffer_desc mechName = GSS_C_EMPTY_BUFFER;
23101 + OM_uint32 major, minor;
23103 + major = gssEapExportNameInternal(&minor, gssCtx->initiatorName, &mechName,
23104 + EXPORT_NAME_FLAG_OID |
23105 + EXPORT_NAME_FLAG_COMPOSITE);
23106 + if (major == GSS_S_COMPLETE) {
23107 + resolver->addToken(&mechName);
23108 + gss_release_buffer(&minor, &mechName);
23111 +#ifdef HAVE_OPENSAML
23112 + const gss_eap_saml_assertion_provider *saml;
23113 + saml = static_cast<const gss_eap_saml_assertion_provider *>
23114 + (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
23115 + if (saml != NULL && saml->getAssertion() != NULL) {
23116 + resolver->addToken(saml->getAssertion());
23119 + /* If no OpenSAML, parse the XML assertion explicitly */
23120 + const gss_eap_radius_attr_provider *radius;
23121 + int authenticated, complete;
23122 + gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
23124 + radius = static_cast<const gss_eap_radius_attr_provider *>
23125 + (m_manager->getProvider(ATTR_TYPE_RADIUS));
23126 + if (radius != NULL &&
23127 + radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION,
23128 + VENDORPEC_UKERNA,
23129 + &authenticated, &complete, &value)) {
23130 + string str((char *)value.value, value.length);
23131 + istringstream istream(str);
23132 + DOMDocument *doc = XMLToolingConfig::getConfig().getParser().parse(istream);
23133 + const XMLObjectBuilder *b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
23134 + resolver->addToken(b->buildFromDocument(doc));
23135 + gss_release_buffer(&minor, &value);
23137 +#endif /* HAVE_OPENSAML */
23140 + resolver->resolve();
23141 + m_attributes = resolver->getResolvedAttributes();
23142 + resolver->getResolvedAttributes().clear();
23143 + } catch (exception &e) {
23147 + m_authenticated = true;
23148 + m_initialized = true;
23154 +gss_eap_shib_attr_provider::getAttributeIndex(const gss_buffer_t attr) const
23158 + GSSEAP_ASSERT(m_initialized);
23160 + for (vector<Attribute *>::const_iterator a = m_attributes.begin();
23161 + a != m_attributes.end();
23164 + for (vector<string>::const_iterator s = (*a)->getAliases().begin();
23165 + s != (*a)->getAliases().end();
23167 + if (attr->length == (*s).length() &&
23168 + memcmp((*s).c_str(), attr->value, attr->length) == 0) {
23178 +gss_eap_shib_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
23179 + const gss_buffer_t attr,
23180 + const gss_buffer_t value)
23182 + string attrStr((char *)attr->value, attr->length);
23183 + vector <string> ids(1, attrStr);
23184 + BinaryAttribute *a = new BinaryAttribute(ids);
23186 + GSSEAP_ASSERT(m_initialized);
23188 + if (value->length != 0) {
23189 + string valueStr((char *)value->value, value->length);
23191 + a->getValues().push_back(valueStr);
23194 + m_attributes.push_back(a);
23195 + m_authenticated = false;
23201 +gss_eap_shib_attr_provider::deleteAttribute(const gss_buffer_t attr)
23205 + GSSEAP_ASSERT(m_initialized);
23207 + i = getAttributeIndex(attr);
23209 + m_attributes.erase(m_attributes.begin() + i);
23211 + m_authenticated = false;
23217 +gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
23218 + void *data) const
23220 + GSSEAP_ASSERT(m_initialized);
23222 + for (vector<Attribute*>::const_iterator a = m_attributes.begin();
23223 + a != m_attributes.end();
23226 + gss_buffer_desc attribute;
23228 + attribute.value = (void *)((*a)->getId());
23229 + attribute.length = strlen((char *)attribute.value);
23231 + if (!addAttribute(m_manager, this, &attribute, data))
23239 +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr) const
23241 + const Attribute *ret = NULL;
23243 + GSSEAP_ASSERT(m_initialized);
23245 + for (vector<Attribute *>::const_iterator a = m_attributes.begin();
23246 + a != m_attributes.end();
23249 + for (vector<string>::const_iterator s = (*a)->getAliases().begin();
23250 + s != (*a)->getAliases().end();
23252 + if (attr->length == (*s).length() &&
23253 + memcmp((*s).c_str(), attr->value, attr->length) == 0) {
23266 +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr,
23267 + int *authenticated,
23269 + gss_buffer_t value,
23270 + gss_buffer_t display_value,
23273 + const Attribute *shibAttr = NULL;
23274 + const BinaryAttribute *binaryAttr;
23275 + gss_buffer_desc valueBuf = GSS_C_EMPTY_BUFFER;
23276 + gss_buffer_desc displayValueBuf = GSS_C_EMPTY_BUFFER;
23277 + int nvalues, i = *more;
23279 + GSSEAP_ASSERT(m_initialized);
23283 + shibAttr = getAttribute(attr);
23284 + if (shibAttr == NULL)
23287 + nvalues = shibAttr->valueCount();
23291 + if (i >= nvalues)
23294 + binaryAttr = dynamic_cast<const BinaryAttribute *>(shibAttr);
23295 + if (binaryAttr != NULL) {
23296 + std::string str = binaryAttr->getValues()[*more];
23298 + valueBuf.value = (void *)str.data();
23299 + valueBuf.length = str.size();
23301 + std::string str = shibAttr->getSerializedValues()[*more];
23303 + valueBuf.value = (void *)str.c_str();
23304 + valueBuf.length = str.length();
23306 + const SimpleAttribute *simpleAttr =
23307 + dynamic_cast<const SimpleAttribute *>(shibAttr);
23308 + const ScopedAttribute *scopedAttr =
23309 + dynamic_cast<const ScopedAttribute *>(shibAttr);
23310 + if (simpleAttr != NULL || scopedAttr != NULL)
23311 + displayValueBuf = valueBuf;
23314 + if (authenticated != NULL)
23315 + *authenticated = m_authenticated;
23316 + if (complete != NULL)
23317 + *complete = true;
23318 + if (value != NULL)
23319 + duplicateBuffer(valueBuf, value);
23320 + if (display_value != NULL)
23321 + duplicateBuffer(displayValueBuf, display_value);
23322 + if (nvalues > ++i)
23329 +gss_eap_shib_attr_provider::mapToAny(int authenticated,
23330 + gss_buffer_t type_id GSSEAP_UNUSED) const
23332 + gss_any_t output;
23334 + GSSEAP_ASSERT(m_initialized);
23336 + if (authenticated && !m_authenticated)
23337 + return (gss_any_t)NULL;
23339 + vector <Attribute *>v = duplicateAttributes(m_attributes);
23341 + output = (gss_any_t)new vector <Attribute *>(v);
23347 +gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
23348 + gss_any_t input) const
23350 + GSSEAP_ASSERT(m_initialized);
23352 + vector <Attribute *> *v = ((vector <Attribute *> *)input);
23357 +gss_eap_shib_attr_provider::prefix(void) const
23363 +gss_eap_shib_attr_provider::name(void) const
23369 +gss_eap_shib_attr_provider::jsonRepresentation(void) const
23373 + if (m_initialized == false)
23374 + return obj; /* don't export incomplete context */
23376 + JSONObject jattrs = JSONObject::array();
23378 + for (vector<Attribute*>::const_iterator a = m_attributes.begin();
23379 + a != m_attributes.end(); ++a) {
23380 + DDF attr = (*a)->marshall();
23381 + JSONObject jattr = JSONObject::ddf(attr);
23382 + jattrs.append(jattr);
23385 + obj.set("attributes", jattrs);
23387 + obj.set("authenticated", m_authenticated);
23393 +gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
23396 + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
23399 + GSSEAP_ASSERT(m_authenticated == false);
23400 + GSSEAP_ASSERT(m_attributes.size() == 0);
23402 + JSONObject jattrs = obj["attributes"];
23403 + size_t nelems = jattrs.size();
23405 + for (size_t i = 0; i < nelems; i++) {
23406 + JSONObject jattr = jattrs.get(i);
23408 + DDF attr = jattr.ddf();
23409 + Attribute *attribute = Attribute::unmarshall(attr);
23410 + m_attributes.push_back(attribute);
23413 + m_authenticated = obj["authenticated"].integer();
23414 + m_initialized = true;
23420 +gss_eap_shib_attr_provider::init(void)
23422 + bool ret = false;
23425 + ret = ShibbolethResolver::init();
23426 + } catch (exception &e) {
23430 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext);
23436 +gss_eap_shib_attr_provider::finalize(void)
23438 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_LOCAL);
23439 + ShibbolethResolver::term();
23443 +gss_eap_shib_attr_provider::mapException(OM_uint32 *minor,
23444 + std::exception &e) const
23446 + if (typeid(e) == typeid(AttributeException))
23447 + *minor = GSSEAP_SHIB_ATTR_FAILURE;
23448 + else if (typeid(e) == typeid(AttributeExtractionException))
23449 + *minor = GSSEAP_SHIB_ATTR_EXTRACT_FAILURE;
23450 + else if (typeid(e) == typeid(AttributeFilteringException))
23451 + *minor = GSSEAP_SHIB_ATTR_FILTER_FAILURE;
23452 + else if (typeid(e) == typeid(AttributeResolutionException))
23453 + *minor = GSSEAP_SHIB_ATTR_RESOLVE_FAILURE;
23454 + else if (typeid(e) == typeid(ConfigurationException))
23455 + *minor = GSSEAP_SHIB_CONFIG_FAILURE;
23456 + else if (typeid(e) == typeid(ListenerException))
23457 + *minor = GSSEAP_SHIB_LISTENER_FAILURE;
23459 + return GSS_S_CONTINUE_NEEDED;
23461 + gssEapSaveStatusInfo(*minor, "%s", e.what());
23463 + return GSS_S_FAILURE;
23466 +gss_eap_attr_provider *
23467 +gss_eap_shib_attr_provider::createAttrContext(void)
23469 + return new gss_eap_shib_attr_provider;
23473 +gss_eap_shib_attr_provider::duplicateAttribute(const Attribute *src)
23475 + DDF obj = src->marshall();
23476 + Attribute *attribute = Attribute::unmarshall(obj);
23479 + return attribute;
23482 +vector <Attribute *>
23483 +gss_eap_shib_attr_provider::duplicateAttributes(const vector <Attribute *>src)
23485 + vector <Attribute *> dst;
23487 + for (vector<Attribute *>::const_iterator a = src.begin();
23490 + dst.push_back(duplicateAttribute(*a));
23496 +gssEapLocalAttrProviderInit(OM_uint32 *minor)
23498 + if (!gss_eap_shib_attr_provider::init()) {
23499 + *minor = GSSEAP_SHIB_INIT_FAILURE;
23500 + return GSS_S_FAILURE;
23502 + return GSS_S_COMPLETE;
23506 +gssEapLocalAttrProviderFinalize(OM_uint32 *minor)
23508 + gss_eap_shib_attr_provider::finalize();
23511 + return GSS_S_COMPLETE;
23513 diff --git a/mech_eap/util_shib.h b/mech_eap/util_shib.h
23514 new file mode 100644
23515 index 0000000..4cf7481
23517 +++ b/mech_eap/util_shib.h
23520 + * Copyright (c) 2011, JANET(UK)
23521 + * All rights reserved.
23523 + * Redistribution and use in source and binary forms, with or without
23524 + * modification, are permitted provided that the following conditions
23527 + * 1. Redistributions of source code must retain the above copyright
23528 + * notice, this list of conditions and the following disclaimer.
23530 + * 2. Redistributions in binary form must reproduce the above copyright
23531 + * notice, this list of conditions and the following disclaimer in the
23532 + * documentation and/or other materials provided with the distribution.
23534 + * 3. Neither the name of JANET(UK) nor the names of its contributors
23535 + * may be used to endorse or promote products derived from this software
23536 + * without specific prior written permission.
23538 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23539 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23540 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23541 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23542 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23543 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23544 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23545 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23546 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23547 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23552 + * Local attribute provider.
23555 +#ifndef _UTIL_SHIB_H_
23556 +#define _UTIL_SHIB_H_ 1
23558 +#ifdef __cplusplus
23562 +namespace shibsp {
23566 +namespace shibresolver {
23567 + class ShibbolethResolver;
23570 +struct gss_eap_shib_attr_provider : gss_eap_attr_provider {
23572 + gss_eap_shib_attr_provider(void);
23573 + ~gss_eap_shib_attr_provider(void);
23575 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
23576 + const gss_eap_attr_provider *ctx);
23577 + bool initWithGssContext(const gss_eap_attr_ctx *source,
23578 + const gss_cred_id_t cred,
23579 + const gss_ctx_id_t ctx);
23581 + bool setAttribute(int complete,
23582 + const gss_buffer_t attr,
23583 + const gss_buffer_t value);
23584 + bool deleteAttribute(const gss_buffer_t value);
23585 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
23586 + bool getAttribute(const gss_buffer_t attr,
23587 + int *authenticated,
23589 + gss_buffer_t value,
23590 + gss_buffer_t display_value,
23591 + int *more) const;
23592 + gss_any_t mapToAny(int authenticated,
23593 + gss_buffer_t type_id) const;
23594 + void releaseAnyNameMapping(gss_buffer_t type_id,
23595 + gss_any_t input) const;
23597 + const char *prefix(void) const;
23598 + const char *name(void) const;
23599 + bool initWithJsonObject(const gss_eap_attr_ctx *manager,
23600 + JSONObject &obj);
23601 + JSONObject jsonRepresentation(void) const;
23603 + static bool init(void);
23604 + static void finalize(void);
23606 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
23608 + static gss_eap_attr_provider *createAttrContext(void);
23610 + std::vector<shibsp::Attribute *> getAttributes(void) const {
23611 + return m_attributes;
23615 + static shibsp::Attribute *
23616 + duplicateAttribute(const shibsp::Attribute *src);
23617 + static std::vector <shibsp::Attribute *>
23618 + duplicateAttributes(const std::vector <shibsp::Attribute *>src);
23620 + ssize_t getAttributeIndex(const gss_buffer_t attr) const;
23621 + const shibsp::Attribute *getAttribute(const gss_buffer_t attr) const;
23623 + bool authenticated(void) const { return m_authenticated; }
23625 + bool m_initialized;
23626 + bool m_authenticated;
23627 + std::vector<shibsp::Attribute *> m_attributes;
23633 +OM_uint32 gssEapLocalAttrProviderInit(OM_uint32 *minor);
23634 +OM_uint32 gssEapLocalAttrProviderFinalize(OM_uint32 *minor);
23636 +#ifdef __cplusplus
23640 +#endif /* _UTIL_SHIB_H_ */
23641 diff --git a/mech_eap/util_sm.c b/mech_eap/util_sm.c
23642 new file mode 100644
23643 index 0000000..56248d8
23645 +++ b/mech_eap/util_sm.c
23648 + * Copyright (c) 2011, JANET(UK)
23649 + * All rights reserved.
23651 + * Redistribution and use in source and binary forms, with or without
23652 + * modification, are permitted provided that the following conditions
23655 + * 1. Redistributions of source code must retain the above copyright
23656 + * notice, this list of conditions and the following disclaimer.
23658 + * 2. Redistributions in binary form must reproduce the above copyright
23659 + * notice, this list of conditions and the following disclaimer in the
23660 + * documentation and/or other materials provided with the distribution.
23662 + * 3. Neither the name of JANET(UK) nor the names of its contributors
23663 + * may be used to endorse or promote products derived from this software
23664 + * without specific prior written permission.
23666 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23667 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23668 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23669 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23670 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23671 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23672 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23673 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23674 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23675 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23680 + * Context establishment state machine.
23683 +#include "gssapiP_eap.h"
23685 +/* private flags */
23686 +#define SM_FLAG_TRANSITED 0x80000000
23688 +#define SM_ASSERT_VALID(ctx, status) do { \
23689 + GSSEAP_ASSERT(GSS_ERROR((status)) || \
23690 + ((status) == GSS_S_CONTINUE_NEEDED && ((ctx)->state > GSSEAP_STATE_INITIAL && (ctx)->state < GSSEAP_STATE_ESTABLISHED)) || \
23691 + ((status) == GSS_S_COMPLETE && (ctx)->state == GSSEAP_STATE_ESTABLISHED)); \
23694 +#ifdef GSSEAP_DEBUG
23695 +static const char *
23696 +gssEapStateToString(enum gss_eap_state state)
23701 + case GSSEAP_STATE_INITIAL:
23704 + case GSSEAP_STATE_AUTHENTICATE:
23705 + s = "AUTHENTICATE";
23707 + case GSSEAP_STATE_INITIATOR_EXTS:
23708 + s = "INITIATOR_EXTS";
23710 + case GSSEAP_STATE_ACCEPTOR_EXTS:
23711 + s = "ACCEPTOR_EXTS";
23713 +#ifdef GSSEAP_ENABLE_REAUTH
23714 + case GSSEAP_STATE_REAUTHENTICATE:
23715 + s = "REAUTHENTICATE";
23718 + case GSSEAP_STATE_ESTABLISHED:
23719 + s = "ESTABLISHED";
23730 +gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state)
23732 + GSSEAP_ASSERT(state >= GSSEAP_STATE_INITIAL);
23733 + GSSEAP_ASSERT(state <= GSSEAP_STATE_ESTABLISHED);
23735 + fprintf(stderr, "GSS-EAP: state transition %s->%s\n",
23736 + gssEapStateToString(GSSEAP_SM_STATE(ctx)),
23737 + gssEapStateToString(state));
23739 + ctx->state = state;
23741 +#endif /* GSSEAP_DEBUG */
23744 +makeErrorToken(OM_uint32 *minor,
23745 + OM_uint32 majorStatus,
23746 + OM_uint32 minorStatus,
23747 + struct gss_eap_token_buffer_set *token)
23749 + OM_uint32 major, tmpMinor;
23750 + unsigned char errorData[8];
23751 + gss_buffer_desc errorBuffer;
23753 + GSSEAP_ASSERT(GSS_ERROR(majorStatus));
23756 + * Only return error codes that the initiator could have caused,
23757 + * to avoid information leakage.
23759 + if (IS_RADIUS_ERROR(minorStatus)) {
23760 + /* Squash RADIUS error codes */
23761 + minorStatus = GSSEAP_RADIUS_PROT_FAILURE;
23762 + } else if (!IS_WIRE_ERROR(minorStatus)) {
23763 + /* Don't return non-wire error codes */
23764 + return GSS_S_COMPLETE;
23767 + minorStatus -= ERROR_TABLE_BASE_eapg;
23769 + store_uint32_be(majorStatus, &errorData[0]);
23770 + store_uint32_be(minorStatus, &errorData[4]);
23772 + major = gssEapAllocInnerTokens(&tmpMinor, 1, token);
23773 + if (GSS_ERROR(major)) {
23774 + *minor = tmpMinor;
23778 + errorBuffer.length = sizeof(errorData);
23779 + errorBuffer.value = errorData;
23781 + major = duplicateBuffer(&tmpMinor, &errorBuffer, &token->buffers.elements[0]);
23782 + if (GSS_ERROR(major)) {
23783 + gssEapReleaseInnerTokens(&tmpMinor, token, 1);
23784 + *minor = tmpMinor;
23788 + token->buffers.count = 1;
23789 + token->types[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
23792 + return GSS_S_COMPLETE;
23796 +gssEapSmStep(OM_uint32 *minor,
23797 + gss_cred_id_t cred,
23798 + gss_ctx_id_t ctx,
23799 + gss_name_t target,
23801 + OM_uint32 reqFlags,
23802 + OM_uint32 timeReq,
23803 + gss_channel_bindings_t chanBindings,
23804 + gss_buffer_t inputToken,
23805 + gss_buffer_t outputToken,
23806 + struct gss_eap_sm *sm, /* ordered by state */
23809 + OM_uint32 major, tmpMajor, tmpMinor;
23810 + struct gss_eap_token_buffer_set inputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
23811 + struct gss_eap_token_buffer_set outputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
23812 + gss_buffer_desc unwrappedInputToken = GSS_C_EMPTY_BUFFER;
23813 + gss_buffer_desc unwrappedOutputToken = GSS_C_EMPTY_BUFFER;
23814 + unsigned int smFlags = 0;
23816 + int initialContextToken = 0;
23817 + enum gss_eap_token_type tokType;
23819 + GSSEAP_ASSERT(smCount > 0);
23823 + outputToken->length = 0;
23824 + outputToken->value = NULL;
23826 + if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
23827 + major = gssEapVerifyToken(minor, ctx, inputToken, &tokType,
23828 + &unwrappedInputToken);
23829 + if (GSS_ERROR(major))
23832 + if (tokType != (CTX_IS_INITIATOR(ctx)
23833 + ? TOK_TYPE_ACCEPTOR_CONTEXT : TOK_TYPE_INITIATOR_CONTEXT)) {
23834 + major = GSS_S_DEFECTIVE_TOKEN;
23835 + *minor = GSSEAP_WRONG_TOK_ID;
23838 + } else if (!CTX_IS_INITIATOR(ctx) || ctx->state != GSSEAP_STATE_INITIAL) {
23839 + major = GSS_S_DEFECTIVE_TOKEN;
23840 + *minor = GSSEAP_WRONG_SIZE;
23843 + initialContextToken = 1;
23846 + if (CTX_IS_ESTABLISHED(ctx)) {
23847 + major = GSS_S_BAD_STATUS;
23848 + *minor = GSSEAP_CONTEXT_ESTABLISHED;
23852 + GSSEAP_ASSERT(ctx->state < GSSEAP_STATE_ESTABLISHED);
23854 + major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken, &inputTokens);
23855 + if (GSS_ERROR(major))
23858 + major = gssEapAllocInnerTokens(minor, smCount, &outputTokens);
23859 + if (GSS_ERROR(major))
23862 + ctx->inputTokens = &inputTokens;
23863 + ctx->outputTokens = &outputTokens;
23865 + /* Process all the tokens that are valid for the current state. */
23866 + for (i = 0; i < smCount; i++) {
23867 + struct gss_eap_sm *smp = &sm[i];
23868 + int processToken = 0;
23869 + gss_buffer_t innerInputToken = GSS_C_NO_BUFFER;
23870 + OM_uint32 *inputTokenType = NULL;
23871 + gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER;
23873 + if ((smp->validStates & ctx->state) == 0)
23877 + * We special case the first call to gss_init_sec_context so that
23878 + * all token providers have the opportunity to generate an initial
23879 + * context token. Providers where inputTokenType is ITOK_TYPE_NONE
23880 + * are always called and generally act on state transition boundaries,
23881 + * for example to advance the state after a series of optional tokens
23882 + * (as is the case with the extension token exchange) or to generate
23883 + * a new token after the state was advanced by a provider which did
23884 + * not emit a token.
23886 + if (smp->inputTokenType == ITOK_TYPE_NONE || initialContextToken) {
23887 + processToken = 1;
23888 + } else if ((smFlags & SM_FLAG_TRANSITED) == 0) {
23889 + /* Don't regurgitate a token which belonds to a previous state. */
23890 + for (j = 0; j < inputTokens.buffers.count; j++) {
23891 + if ((inputTokens.types[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
23892 + if (processToken) {
23893 + /* Check for duplicate inner tokens */
23894 + major = GSS_S_DEFECTIVE_TOKEN;
23895 + *minor = GSSEAP_DUPLICATE_ITOK;
23898 + processToken = 1;
23899 + innerInputToken = &inputTokens.buffers.elements[j];
23900 + inputTokenType = &inputTokens.types[j];
23903 + if (GSS_ERROR(major))
23907 + if (processToken) {
23908 + enum gss_eap_state oldState = ctx->state;
23911 + if (inputTokenType != NULL && (*inputTokenType & ITOK_FLAG_CRITICAL))
23912 + smFlags |= SM_FLAG_INPUT_TOKEN_CRITICAL;
23914 + major = smp->processToken(minor, cred, ctx, target, mech, reqFlags,
23915 + timeReq, chanBindings, innerInputToken,
23916 + &innerOutputToken, &smFlags);
23917 + if (GSS_ERROR(major))
23920 + if (inputTokenType != NULL)
23921 + *inputTokenType |= ITOK_FLAG_VERIFIED;
23922 + if (ctx->state < oldState)
23923 + i = 0; /* restart */
23924 + else if (ctx->state != oldState)
23925 + smFlags |= SM_FLAG_TRANSITED;
23927 + if (innerOutputToken.value != NULL) {
23928 + outputTokens.buffers.elements[outputTokens.buffers.count] = innerOutputToken;
23929 + GSSEAP_ASSERT(smp->outputTokenType != ITOK_TYPE_NONE);
23930 + outputTokens.types[outputTokens.buffers.count] = smp->outputTokenType;
23931 + if (smFlags & SM_FLAG_OUTPUT_TOKEN_CRITICAL)
23932 + outputTokens.types[outputTokens.buffers.count] |= ITOK_FLAG_CRITICAL;
23933 + outputTokens.buffers.count++;
23936 + * Break out if we made a state transition and have some tokens to send.
23938 + if ((smFlags & SM_FLAG_TRANSITED) &&
23939 + ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || outputTokens.buffers.count != 0)) {
23940 + SM_ASSERT_VALID(ctx, major);
23943 + } else if ((smp->itokFlags & SM_ITOK_FLAG_REQUIRED) &&
23944 + smp->inputTokenType != ITOK_TYPE_NONE) {
23945 + /* Check for required inner tokens */
23946 + major = GSS_S_DEFECTIVE_TOKEN;
23947 + *minor = GSSEAP_MISSING_REQUIRED_ITOK;
23952 + GSSEAP_ASSERT(outputTokens.buffers.count <= smCount);
23954 + /* Check we understood all critical tokens sent by peer */
23955 + if (!GSS_ERROR(major)) {
23956 + for (j = 0; j < inputTokens.buffers.count; j++) {
23957 + if ((inputTokens.types[j] & ITOK_FLAG_CRITICAL) &&
23958 + (inputTokens.types[j] & ITOK_FLAG_VERIFIED) == 0) {
23959 + major = GSS_S_UNAVAILABLE;
23960 + *minor = GSSEAP_CRIT_ITOK_UNAVAILABLE;
23966 + /* Optionaly emit an error token if we are the acceptor */
23967 + if (GSS_ERROR(major)) {
23968 + if (CTX_IS_INITIATOR(ctx))
23969 + goto cleanup; /* return error directly to caller */
23971 + /* replace any emitted tokens with error token */
23972 + gssEapReleaseInnerTokens(&tmpMinor, &outputTokens, 1);
23974 + tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &outputTokens);
23975 + if (GSS_ERROR(tmpMajor)) {
23976 + major = tmpMajor;
23977 + *minor = tmpMinor;
23982 + /* Format output token from inner tokens */
23983 + if (outputTokens.buffers.count != 0 || /* inner tokens to send */
23984 + !CTX_IS_INITIATOR(ctx) || /* any leg acceptor */
23985 + !CTX_IS_ESTABLISHED(ctx)) { /* non-last leg initiator */
23986 + tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, &outputTokens, &unwrappedOutputToken);
23987 + if (tmpMajor == GSS_S_COMPLETE) {
23988 + if (CTX_IS_INITIATOR(ctx))
23989 + tokType = TOK_TYPE_INITIATOR_CONTEXT;
23991 + tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
23993 + tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &unwrappedOutputToken,
23994 + tokType, outputToken);
23995 + if (GSS_ERROR(tmpMajor)) {
23996 + major = tmpMajor;
23997 + *minor = tmpMinor;
24003 + /* If the context is established, empty tokens only to be emitted by initiator */
24004 + GSSEAP_ASSERT(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx)));
24006 + SM_ASSERT_VALID(ctx, major);
24009 + gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 0);
24010 + gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 1);
24012 + gss_release_buffer(&tmpMinor, &unwrappedOutputToken);
24014 + ctx->inputTokens = NULL;
24015 + ctx->outputTokens = NULL;
24019 diff --git a/mech_eap/util_tld.c b/mech_eap/util_tld.c
24020 new file mode 100644
24021 index 0000000..05bc3d1
24023 +++ b/mech_eap/util_tld.c
24026 + * Copyright (c) 2011, JANET(UK)
24027 + * All rights reserved.
24029 + * Redistribution and use in source and binary forms, with or without
24030 + * modification, are permitted provided that the following conditions
24033 + * 1. Redistributions of source code must retain the above copyright
24034 + * notice, this list of conditions and the following disclaimer.
24036 + * 2. Redistributions in binary form must reproduce the above copyright
24037 + * notice, this list of conditions and the following disclaimer in the
24038 + * documentation and/or other materials provided with the distribution.
24040 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24041 + * may be used to endorse or promote products derived from this software
24042 + * without specific prior written permission.
24044 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24045 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24046 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24047 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24048 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24049 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24050 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24051 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24052 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24053 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24058 + * Thread local data abstraction, using pthreads on Unix and the TlsXXX
24059 + * APIs on Windows.
24062 +#include "gssapiP_eap.h"
24064 +/* Clean up thread-local data; called on thread detach */
24066 +destroyThreadLocalData(struct gss_eap_thread_local_data *tld)
24068 + if (tld->statusInfo != NULL)
24069 + gssEapDestroyStatusInfo(tld->statusInfo);
24070 + if (tld->krbContext != NULL)
24071 + gssEapDestroyKrbContext(tld->krbContext);
24072 + GSSEAP_FREE(tld);
24078 + * This is the TLS index returned by TlsAlloc() on process init.
24079 + * Each thread, on thread attach in DllMain(), allocates its thread-local
24080 + * data and uses this index with TlsSetValue() to store it.
24081 + * It can then subsequently be retrieved with TlsGetValue().
24083 +static DWORD tlsIndex = TLS_OUT_OF_INDEXES;
24085 +/* Access thread-local data */
24086 +struct gss_eap_thread_local_data *
24087 +gssEapGetThreadLocalData(void)
24089 + struct gss_eap_thread_local_data *tlsData;
24091 + GSSEAP_ASSERT(tlsIndex != TLS_OUT_OF_INDEXES);
24093 + tlsData = TlsGetValue(tlsIndex);
24094 + if (tlsData == NULL) {
24095 + tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
24096 + TlsSetValue(tlsIndex, tlsData);
24103 +DllMain(HINSTANCE hDLL, /* DLL module handle */
24104 + DWORD reason, /* reason called */
24105 + LPVOID reserved) /* reserved */
24107 + struct gss_eap_thread_local_data *tlsData;
24108 + OM_uint32 major, minor;
24110 + switch (reason) {
24111 + case DLL_PROCESS_ATTACH:
24112 + /* Allocate a TLS index. */
24113 + major = gssEapInitiatorInit(&minor);
24114 + if (GSS_ERROR(major))
24117 + tlsIndex = TlsAlloc();
24118 + if (tlsIndex == TLS_OUT_OF_INDEXES)
24120 + /* No break: Initialize the index for first thread.*/
24121 + case DLL_THREAD_ATTACH:
24122 + /* Initialize the TLS index for this thread. */
24123 + tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
24124 + if (tlsData == NULL)
24126 + TlsSetValue(tlsIndex, tlsData);
24128 + case DLL_THREAD_DETACH:
24129 + /* Release the allocated memory for this thread. */
24130 + tlsData = TlsGetValue(tlsIndex);
24131 + if (tlsData != NULL) {
24132 + destroyThreadLocalData(tlsData);
24133 + TlsSetValue(tlsIndex, NULL);
24136 + case DLL_PROCESS_DETACH:
24137 + /* Release the TLS index. */
24138 + TlsFree(tlsIndex);
24139 + gssEapFinalize();
24146 + UNREFERENCED_PARAMETER(hDLL);
24147 + UNREFERENCED_PARAMETER(reserved);
24152 +/* pthreads implementation */
24154 +static GSSEAP_THREAD_ONCE tldKeyOnce = GSSEAP_ONCE_INITIALIZER;
24155 +static GSSEAP_THREAD_KEY tldKey;
24158 +pthreadDestroyThreadLocalData(void *arg)
24160 + struct gss_eap_thread_local_data* tld = arg;
24163 + destroyThreadLocalData(tld);
24167 +createThreadLocalDataKey(void)
24169 + GSSEAP_KEY_CREATE(&tldKey, pthreadDestroyThreadLocalData);
24172 +struct gss_eap_thread_local_data *
24173 +gssEapGetThreadLocalData()
24175 + struct gss_eap_thread_local_data *tld;
24177 + GSSEAP_ONCE(&tldKeyOnce, createThreadLocalDataKey);
24179 + tld = GSSEAP_GETSPECIFIC(tldKey);
24180 + if (tld == NULL) {
24181 + tld = GSSEAP_CALLOC(1, sizeof(*tld));
24185 + GSSEAP_SETSPECIFIC(tldKey, tld);
24191 +#endif /* WIN32 */
24192 diff --git a/mech_eap/util_token.c b/mech_eap/util_token.c
24193 new file mode 100644
24194 index 0000000..a1aea0c
24196 +++ b/mech_eap/util_token.c
24199 + * Copyright (c) 2011, JANET(UK)
24200 + * All rights reserved.
24202 + * Redistribution and use in source and binary forms, with or without
24203 + * modification, are permitted provided that the following conditions
24206 + * 1. Redistributions of source code must retain the above copyright
24207 + * notice, this list of conditions and the following disclaimer.
24209 + * 2. Redistributions in binary form must reproduce the above copyright
24210 + * notice, this list of conditions and the following disclaimer in the
24211 + * documentation and/or other materials provided with the distribution.
24213 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24214 + * may be used to endorse or promote products derived from this software
24215 + * without specific prior written permission.
24217 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24218 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24219 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24220 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24221 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24222 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24223 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24224 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24225 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24226 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24230 + * Portions Copyright 1993 by OpenVision Technologies, Inc.
24232 + * Permission to use, copy, modify, distribute, and sell this software
24233 + * and its documentation for any purpose is hereby granted without fee,
24234 + * provided that the above copyright notice appears in all copies and
24235 + * that both that copyright notice and this permission notice appear in
24236 + * supporting documentation, and that the name of OpenVision not be used
24237 + * in advertising or publicity pertaining to distribution of the software
24238 + * without specific, written prior permission. OpenVision makes no
24239 + * representations about the suitability of this software for any
24240 + * purpose. It is provided "as is" without express or implied warranty.
24242 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24243 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
24244 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24245 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24246 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
24247 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24248 + * PERFORMANCE OF THIS SOFTWARE.
24252 + * Utility routines for GSS tokens.
24255 +#include "gssapiP_eap.h"
24258 +gssEapEncodeInnerTokens(OM_uint32 *minor,
24259 + struct gss_eap_token_buffer_set *tokens,
24260 + gss_buffer_t buffer)
24262 + OM_uint32 major, tmpMinor;
24263 + size_t required = 0, i;
24264 + unsigned char *p;
24266 + buffer->value = NULL;
24267 + buffer->length = 0;
24269 + for (i = 0; i < tokens->buffers.count; i++) {
24270 + required += 8 + tokens->buffers.elements[i].length;
24274 + * We must always return a non-NULL token otherwise the calling state
24275 + * machine assumes we are finished. Hence care in case malloc(0) does
24278 + buffer->value = GSSEAP_MALLOC(required ? required : 1);
24279 + if (buffer->value == NULL) {
24280 + major = GSS_S_FAILURE;
24285 + buffer->length = required;
24286 + p = (unsigned char *)buffer->value;
24288 + for (i = 0; i < tokens->buffers.count; i++) {
24289 + gss_buffer_t tokenBuffer = &tokens->buffers.elements[i];
24291 + GSSEAP_ASSERT((tokens->types[i] & ITOK_FLAG_VERIFIED) == 0); /* private flag */
24294 + * Extensions are encoded as type-length-value, where the upper
24295 + * bit of the type indicates criticality.
24297 + store_uint32_be(tokens->types[i], &p[0]);
24298 + store_uint32_be(tokenBuffer->length, &p[4]);
24299 + memcpy(&p[8], tokenBuffer->value, tokenBuffer->length);
24301 + p += 8 + tokenBuffer->length;
24304 + GSSEAP_ASSERT(p == (unsigned char *)buffer->value + required);
24305 + GSSEAP_ASSERT(buffer->value != NULL);
24307 + major = GSS_S_COMPLETE;
24311 + if (GSS_ERROR(major)) {
24312 + gss_release_buffer(&tmpMinor, buffer);
24319 +gssEapDecodeInnerTokens(OM_uint32 *minor,
24320 + const gss_buffer_t buffer,
24321 + struct gss_eap_token_buffer_set *tokens)
24323 + OM_uint32 major, tmpMinor;
24324 + unsigned char *p;
24325 + size_t count = 0;
24328 + tokens->buffers.count = 0;
24329 + tokens->buffers.elements = NULL;
24330 + tokens->types = NULL;
24332 + if (buffer->length == 0) {
24333 + major = GSS_S_COMPLETE;
24337 + p = (unsigned char *)buffer->value;
24338 + remain = buffer->length;
24341 + OM_uint32 *ntypes;
24342 + gss_buffer_desc tokenBuffer, *newTokenBuffers;
24344 + if (remain < 8) {
24345 + major = GSS_S_DEFECTIVE_TOKEN;
24346 + *minor = GSSEAP_TOK_TRUNC;
24350 + if (tokens->buffers.count <= count) {
24356 + ntypes = GSSEAP_MALLOC(count * sizeof(OM_uint32));
24357 + if (ntypes == NULL) {
24358 + major = GSS_S_FAILURE;
24362 + if (tokens->types != NULL) {
24363 + memcpy(ntypes, tokens->types, tokens->buffers.count * sizeof(OM_uint32));
24364 + GSSEAP_FREE(tokens->types);
24366 + tokens->types = ntypes;
24368 + newTokenBuffers = GSSEAP_MALLOC(count * sizeof(gss_buffer_desc));
24369 + if (newTokenBuffers == NULL) {
24370 + major = GSS_S_FAILURE;
24374 + if (tokens->buffers.elements != NULL) {
24375 + memcpy(newTokenBuffers, tokens->buffers.elements,
24376 + tokens->buffers.count * sizeof(gss_buffer_desc));
24377 + GSSEAP_FREE(tokens->buffers.elements);
24379 + tokens->buffers.elements = newTokenBuffers;
24382 + tokens->types[tokens->buffers.count] = load_uint32_be(&p[0]);
24383 + tokenBuffer.length = load_uint32_be(&p[4]);
24385 + if (remain < 8 + tokenBuffer.length) {
24386 + major = GSS_S_DEFECTIVE_TOKEN;
24387 + *minor = GSSEAP_TOK_TRUNC;
24390 + tokenBuffer.value = &p[8];
24392 + tokens->buffers.elements[tokens->buffers.count] = tokenBuffer;
24393 + tokens->buffers.count++;
24395 + p += 8 + tokenBuffer.length;
24396 + remain -= 8 + tokenBuffer.length;
24397 + } while (remain != 0);
24399 + major = GSS_S_COMPLETE;
24403 + if (GSS_ERROR(major))
24404 + gssEapReleaseInnerTokens(&tmpMinor, tokens, 0);
24410 + * $Id: util_token.c 23457 2009-12-08 00:04:48Z tlyu $
24413 +/* XXXX this code currently makes the assumption that a mech oid will
24414 + never be longer than 127 bytes. This assumption is not inherent in
24415 + the interfaces, so the code can be fixed if the OSI namespace
24416 + balloons unexpectedly. */
24419 + * Each token looks like this:
24420 + * 0x60 tag for APPLICATION 0, SEQUENCE
24421 + * (constructed, definite-length)
24422 + * <length> possible multiple bytes, need to parse/generate
24423 + * 0x06 tag for OBJECT IDENTIFIER
24424 + * <moid_length> compile-time constant string (assume 1 byte)
24425 + * <moid_bytes> compile-time constant string
24426 + * <inner_bytes> the ANY containing the application token
24427 + * bytes 0,1 are the token type
24428 + * bytes 2,n are the token data
24430 + * Note that the token type field is a feature of RFC 1964 mechanisms and
24431 + * is not used by other GSSAPI mechanisms. As such, a token type of -1
24432 + * is interpreted to mean that no token type should be expected or
24435 + * For the purposes of this abstraction, the token "header" consists of
24436 + * the sequence tag and length octets, the mech OID DER encoding, and the
24437 + * first two inner bytes, which indicate the token type. The token
24438 + * "body" consists of everything else.
24442 +der_length_size(size_t length)
24444 + if (length < (1<<7))
24446 + else if (length < (1<<8))
24448 +#if INT_MAX == 0x7fff
24452 + else if (length < (1<<16))
24454 + else if (length < (1<<24))
24462 +der_write_length(unsigned char **buf, size_t length)
24464 + if (length < (1<<7)) {
24465 + *(*buf)++ = (unsigned char)length;
24467 + *(*buf)++ = (unsigned char)(der_length_size(length)+127);
24468 +#if INT_MAX > 0x7fff
24469 + if (length >= (1<<24))
24470 + *(*buf)++ = (unsigned char)(length>>24);
24471 + if (length >= (1<<16))
24472 + *(*buf)++ = (unsigned char)((length>>16)&0xff);
24474 + if (length >= (1<<8))
24475 + *(*buf)++ = (unsigned char)((length>>8)&0xff);
24476 + *(*buf)++ = (unsigned char)(length&0xff);
24480 +/* returns decoded length, or < 0 on failure. Advances buf and
24481 + decrements bufsize */
24484 +der_read_length(unsigned char **buf, ssize_t *bufsize)
24486 + unsigned char sf;
24489 + if (*bufsize < 1)
24495 + if ((sf &= 0x7f) > ((*bufsize)-1))
24497 + if (sf > sizeof(int))
24500 + for (; sf; sf--) {
24501 + ret = (ret<<8) + (*(*buf)++);
24511 +/* returns the length of a token, given the mech oid and the body size */
24514 +tokenSize(const gss_OID_desc *mech, size_t body_size)
24516 + GSSEAP_ASSERT(mech != GSS_C_NO_OID);
24518 + /* set body_size to sequence contents size */
24519 + body_size += 4 + (size_t) mech->length; /* NEED overflow check */
24520 + return 1 + der_length_size(body_size) + body_size;
24523 +/* fills in a buffer with the token header. The buffer is assumed to
24524 + be the right size. buf is advanced past the token header */
24528 + const gss_OID_desc *mech,
24529 + size_t body_size,
24530 + unsigned char **buf,
24531 + enum gss_eap_token_type tok_type)
24533 + *(*buf)++ = 0x60;
24534 + der_write_length(buf, (tok_type == -1) ?2:4 + mech->length + body_size);
24535 + *(*buf)++ = 0x06;
24536 + *(*buf)++ = (unsigned char)mech->length;
24537 + memcpy(*buf, mech->elements, mech->length);
24538 + *buf += mech->length;
24539 + GSSEAP_ASSERT(tok_type != TOK_TYPE_NONE);
24540 + *(*buf)++ = (unsigned char)((tok_type>>8) & 0xff);
24541 + *(*buf)++ = (unsigned char)(tok_type & 0xff);
24545 + * Given a buffer containing a token, reads and verifies the token,
24546 + * leaving buf advanced past the token header, and setting body_size
24547 + * to the number of remaining bytes. Returns 0 on success,
24548 + * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
24549 + * mechanism in the token does not match the mech argument. buf and
24550 + * *body_size are left unmodified on error.
24554 +verifyTokenHeader(OM_uint32 *minor,
24556 + size_t *body_size,
24557 + unsigned char **buf_in,
24558 + size_t toksize_in,
24559 + enum gss_eap_token_type *ret_tok_type)
24561 + unsigned char *buf = *buf_in;
24563 + gss_OID_desc toid;
24564 + ssize_t toksize = (ssize_t)toksize_in;
24566 + *minor = GSSEAP_BAD_TOK_HEADER;
24568 + if (ret_tok_type != NULL)
24569 + *ret_tok_type = TOK_TYPE_NONE;
24571 + if ((toksize -= 1) < 0)
24572 + return GSS_S_DEFECTIVE_TOKEN;
24574 + if (*buf++ != 0x60)
24575 + return GSS_S_DEFECTIVE_TOKEN;
24577 + seqsize = der_read_length(&buf, &toksize);
24579 + return GSS_S_DEFECTIVE_TOKEN;
24581 + if (seqsize != toksize)
24582 + return GSS_S_DEFECTIVE_TOKEN;
24584 + if ((toksize -= 1) < 0)
24585 + return GSS_S_DEFECTIVE_TOKEN;
24587 + if (*buf++ != 0x06)
24588 + return GSS_S_DEFECTIVE_TOKEN;
24590 + if ((toksize -= 1) < 0)
24591 + return GSS_S_DEFECTIVE_TOKEN;
24593 + toid.length = *buf++;
24595 + if ((toksize -= toid.length) < 0)
24596 + return GSS_S_DEFECTIVE_TOKEN;
24598 + toid.elements = buf;
24599 + buf += toid.length;
24601 + if (mech->elements == NULL) {
24603 + if (toid.length == 0)
24604 + return GSS_S_BAD_MECH;
24605 + } else if (!oidEqual(&toid, mech)) {
24606 + *minor = GSSEAP_WRONG_MECH;
24607 + return GSS_S_BAD_MECH;
24610 + if (ret_tok_type != NULL) {
24611 + if ((toksize -= 2) < 0)
24612 + return GSS_S_DEFECTIVE_TOKEN;
24614 + *ret_tok_type = load_uint16_be(buf);
24619 + *body_size = toksize;
24622 + return GSS_S_COMPLETE;
24626 +gssEapAllocInnerTokens(OM_uint32 *minor,
24628 + struct gss_eap_token_buffer_set *tokens)
24632 + tokens->buffers.count = 0;
24633 + tokens->buffers.elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc));
24634 + if (tokens->buffers.elements == NULL) {
24635 + major = GSS_S_FAILURE;
24640 + tokens->types = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32));
24641 + if (tokens->types == NULL) {
24642 + major = GSS_S_FAILURE;
24647 + major = GSS_S_COMPLETE;
24651 + if (GSS_ERROR(major)) {
24652 + if (tokens->buffers.elements != NULL) {
24653 + GSSEAP_FREE(tokens->buffers.elements);
24654 + tokens->buffers.elements = NULL;
24656 + if (tokens->types != NULL) {
24657 + GSSEAP_FREE(tokens->types);
24658 + tokens->types = NULL;
24666 +gssEapReleaseInnerTokens(OM_uint32 *minor,
24667 + struct gss_eap_token_buffer_set *tokens,
24670 + OM_uint32 tmpMinor;
24673 + if (tokens->buffers.elements != NULL) {
24674 + if (freeBuffers) {
24675 + for (i = 0; i < tokens->buffers.count; i++)
24676 + gss_release_buffer(&tmpMinor, &tokens->buffers.elements[i]);
24678 + GSSEAP_FREE(tokens->buffers.elements);
24679 + tokens->buffers.elements = NULL;
24681 + tokens->buffers.count = 0;
24683 + if (tokens->types != NULL) {
24684 + GSSEAP_FREE(tokens->types);
24685 + tokens->types = NULL;
24689 + return GSS_S_COMPLETE;
24691 diff --git a/mech_eap/verify_mic.c b/mech_eap/verify_mic.c
24692 new file mode 100644
24693 index 0000000..c0829f5
24695 +++ b/mech_eap/verify_mic.c
24698 + * Copyright (c) 2011, JANET(UK)
24699 + * All rights reserved.
24701 + * Redistribution and use in source and binary forms, with or without
24702 + * modification, are permitted provided that the following conditions
24705 + * 1. Redistributions of source code must retain the above copyright
24706 + * notice, this list of conditions and the following disclaimer.
24708 + * 2. Redistributions in binary form must reproduce the above copyright
24709 + * notice, this list of conditions and the following disclaimer in the
24710 + * documentation and/or other materials provided with the distribution.
24712 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24713 + * may be used to endorse or promote products derived from this software
24714 + * without specific prior written permission.
24716 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24717 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24718 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24719 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24720 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24721 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24722 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24723 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24724 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24725 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24730 + * Message protection services: verify a message integrity check.
24733 +#include "gssapiP_eap.h"
24735 +OM_uint32 GSSAPI_CALLCONV
24736 +gss_verify_mic(OM_uint32 *minor,
24737 + gss_ctx_id_t ctx,
24738 + gss_buffer_t message_buffer,
24739 + gss_buffer_t message_token,
24740 + gss_qop_t *qop_state)
24743 + gss_iov_buffer_desc iov[3];
24746 + if (message_token->length < 16) {
24747 + *minor = GSSEAP_TOK_TRUNC;
24748 + return GSS_S_BAD_SIG;
24753 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
24754 + iov[0].buffer = *message_buffer;
24756 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
24757 + iov[1].buffer = *message_token;
24759 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
24761 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, &conf_state, qop_state,
24762 + iov, 2, TOK_TYPE_MIC);
24764 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
24768 diff --git a/mech_eap/wrap.c b/mech_eap/wrap.c
24769 new file mode 100644
24770 index 0000000..2e27fb3
24772 +++ b/mech_eap/wrap.c
24775 + * Copyright (c) 2011, JANET(UK)
24776 + * All rights reserved.
24778 + * Redistribution and use in source and binary forms, with or without
24779 + * modification, are permitted provided that the following conditions
24782 + * 1. Redistributions of source code must retain the above copyright
24783 + * notice, this list of conditions and the following disclaimer.
24785 + * 2. Redistributions in binary form must reproduce the above copyright
24786 + * notice, this list of conditions and the following disclaimer in the
24787 + * documentation and/or other materials provided with the distribution.
24789 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24790 + * may be used to endorse or promote products derived from this software
24791 + * without specific prior written permission.
24793 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24794 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24795 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24796 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24797 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24798 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24799 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24800 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24801 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24802 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24807 + * Message protection services: wrap.
24810 +#include "gssapiP_eap.h"
24812 +OM_uint32 GSSAPI_CALLCONV
24813 +gss_wrap(OM_uint32 *minor,
24814 + gss_ctx_id_t ctx,
24815 + int conf_req_flag,
24816 + gss_qop_t qop_req,
24817 + gss_buffer_t input_message_buffer,
24819 + gss_buffer_t output_message_buffer)
24823 + if (ctx == GSS_C_NO_CONTEXT) {
24825 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
24830 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
24832 + if (!CTX_IS_ESTABLISHED(ctx)) {
24833 + major = GSS_S_NO_CONTEXT;
24834 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
24838 + major = gssEapWrap(minor, ctx, conf_req_flag, qop_req,
24839 + input_message_buffer,
24840 + conf_state, output_message_buffer);
24841 + if (GSS_ERROR(major))
24845 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
24851 +gssEapWrap(OM_uint32 *minor,
24852 + gss_ctx_id_t ctx,
24853 + int conf_req_flag,
24854 + gss_qop_t qop_req,
24855 + gss_buffer_t input_message_buffer,
24857 + gss_buffer_t output_message_buffer)
24859 + OM_uint32 major, tmpMinor;
24860 + gss_iov_buffer_desc iov[4];
24861 + unsigned char *p;
24864 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
24865 + iov[0].buffer.value = NULL;
24866 + iov[0].buffer.length = 0;
24868 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
24869 + iov[1].buffer = *input_message_buffer;
24871 + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
24872 + iov[2].buffer.value = NULL;
24873 + iov[2].buffer.length = 0;
24875 + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
24876 + iov[3].buffer.value = NULL;
24877 + iov[3].buffer.length = 0;
24879 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
24881 + if (GSS_ERROR(major)) {
24885 + for (i = 0, output_message_buffer->length = 0; i < 4; i++) {
24886 + output_message_buffer->length += iov[i].buffer.length;
24889 + output_message_buffer->value = GSSEAP_MALLOC(output_message_buffer->length);
24890 + if (output_message_buffer->value == NULL) {
24892 + return GSS_S_FAILURE;
24895 + for (i = 0, p = output_message_buffer->value; i < 4; i++) {
24896 + if (iov[i].type == GSS_IOV_BUFFER_TYPE_DATA) {
24897 + memcpy(p, input_message_buffer->value, input_message_buffer->length);
24899 + iov[i].buffer.value = p;
24900 + p += iov[i].buffer.length;
24903 + major = gssEapWrapOrGetMIC(minor, ctx, conf_req_flag, conf_state,
24904 + iov, 4, TOK_TYPE_WRAP);
24905 + if (GSS_ERROR(major)) {
24906 + gss_release_buffer(&tmpMinor, output_message_buffer);
24911 diff --git a/mech_eap/wrap_iov.c b/mech_eap/wrap_iov.c
24912 new file mode 100644
24913 index 0000000..be890b6
24915 +++ b/mech_eap/wrap_iov.c
24918 + * Copyright (c) 2011, JANET(UK)
24919 + * All rights reserved.
24921 + * Redistribution and use in source and binary forms, with or without
24922 + * modification, are permitted provided that the following conditions
24925 + * 1. Redistributions of source code must retain the above copyright
24926 + * notice, this list of conditions and the following disclaimer.
24928 + * 2. Redistributions in binary form must reproduce the above copyright
24929 + * notice, this list of conditions and the following disclaimer in the
24930 + * documentation and/or other materials provided with the distribution.
24932 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24933 + * may be used to endorse or promote products derived from this software
24934 + * without specific prior written permission.
24936 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24937 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24938 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24939 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24940 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24941 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24942 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24943 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24944 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24945 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24949 + * Copyright 2008 by the Massachusetts Institute of Technology.
24950 + * All Rights Reserved.
24952 + * Export of this software from the United States of America may
24953 + * require a specific license from the United States Government.
24954 + * It is the responsibility of any person or organization contemplating
24955 + * export to obtain such a license before exporting.
24957 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
24958 + * distribute this software and its documentation for any purpose and
24959 + * without fee is hereby granted, provided that the above copyright
24960 + * notice appear in all copies and that both that copyright notice and
24961 + * this permission notice appear in supporting documentation, and that
24962 + * the name of M.I.T. not be used in advertising or publicity pertaining
24963 + * to distribution of the software without specific, written prior
24964 + * permission. Furthermore if you modify this software you must label
24965 + * your software as modified software and not distribute it in such a
24966 + * fashion that it might be confused with the original M.I.T. software.
24967 + * M.I.T. makes no representations about the suitability of
24968 + * this software for any purpose. It is provided "as is" without express
24969 + * or implied warranty.
24973 + * Message protection services: wrap with scatter-gather API.
24976 +#include "gssapiP_eap.h"
24979 +rfc4121Flags(gss_ctx_id_t ctx, int receiving)
24981 + unsigned char flags;
24984 + isAcceptor = !CTX_IS_INITIATOR(ctx);
24986 + isAcceptor = !isAcceptor;
24990 + flags |= TOK_FLAG_SENDER_IS_ACCEPTOR;
24992 + if ((ctx->flags & CTX_FLAG_KRB_REAUTH) &&
24993 + (ctx->gssFlags & GSS_C_MUTUAL_FLAG))
24994 + flags |= TOK_FLAG_ACCEPTOR_SUBKEY;
25000 +gssEapWrapOrGetMIC(OM_uint32 *minor,
25001 + gss_ctx_id_t ctx,
25002 + int conf_req_flag,
25004 + gss_iov_buffer_desc *iov,
25006 + enum gss_eap_token_type toktype)
25008 + krb5_error_code code = 0;
25009 + gss_iov_buffer_t header;
25010 + gss_iov_buffer_t padding;
25011 + gss_iov_buffer_t trailer;
25012 + unsigned char flags;
25013 + unsigned char *outbuf = NULL;
25014 + unsigned char *tbuf = NULL;
25017 + size_t gssHeaderLen, gssTrailerLen;
25018 + size_t dataLen, assocDataLen;
25019 + krb5_context krbContext;
25020 +#ifdef HAVE_HEIMDAL_VERSION
25021 + krb5_crypto krbCrypto = NULL;
25024 + if (ctx->encryptionType == ENCTYPE_NULL) {
25025 + *minor = GSSEAP_KEY_UNAVAILABLE;
25026 + return GSS_S_UNAVAILABLE;
25029 + GSSEAP_KRB_INIT(&krbContext);
25031 + flags = rfc4121Flags(ctx, FALSE);
25033 + if (toktype == TOK_TYPE_WRAP) {
25034 + keyUsage = CTX_IS_INITIATOR(ctx)
25035 + ? KEY_USAGE_INITIATOR_SEAL
25036 + : KEY_USAGE_ACCEPTOR_SEAL;
25038 + keyUsage = CTX_IS_INITIATOR(ctx)
25039 + ? KEY_USAGE_INITIATOR_SIGN
25040 + : KEY_USAGE_ACCEPTOR_SIGN;
25043 + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
25045 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
25046 + if (header == NULL) {
25047 + *minor = GSSEAP_MISSING_IOV;
25048 + return GSS_S_FAILURE;
25051 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
25052 + if (padding != NULL)
25053 + padding->buffer.length = 0;
25055 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
25057 +#ifdef HAVE_HEIMDAL_VERSION
25058 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
25063 + if (toktype == TOK_TYPE_WRAP && conf_req_flag) {
25064 + size_t krbHeaderLen, krbTrailerLen, krbPadLen;
25065 + size_t ec = 0, confDataLen = dataLen - assocDataLen;
25067 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25068 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
25072 + code = krbPaddingLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25073 + confDataLen + 16 /* E(Header) */,
25078 + if (krbPadLen == 0 && (ctx->gssFlags & GSS_C_DCE_STYLE)) {
25079 + /* Windows rejects AEAD tokens with non-zero EC */
25080 + code = krbBlockSize(krbContext, KRB_CRYPTO_CONTEXT(ctx), &ec);
25086 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25087 + KRB5_CRYPTO_TYPE_TRAILER, &krbTrailerLen);
25091 + gssHeaderLen = 16 /* Header */ + krbHeaderLen;
25092 + gssTrailerLen = ec + 16 /* E(Header) */ + krbTrailerLen;
25094 + if (trailer == NULL) {
25095 + rrc = gssTrailerLen;
25096 + /* Workaround for Windows bug where it rotates by EC + RRC */
25097 + if (ctx->gssFlags & GSS_C_DCE_STYLE)
25099 + gssHeaderLen += gssTrailerLen;
25102 + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
25103 + code = gssEapAllocIov(header, (size_t)gssHeaderLen);
25104 + } else if (header->buffer.length < gssHeaderLen)
25105 + code = GSSEAP_WRONG_SIZE;
25108 + outbuf = (unsigned char *)header->buffer.value;
25109 + header->buffer.length = (size_t)gssHeaderLen;
25111 + if (trailer != NULL) {
25112 + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25113 + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen);
25114 + else if (trailer->buffer.length < gssTrailerLen)
25115 + code = GSSEAP_WRONG_SIZE;
25118 + trailer->buffer.length = (size_t)gssTrailerLen;
25122 + store_uint16_be((uint16_t)toktype, outbuf);
25124 + outbuf[2] = flags
25125 + | (conf_req_flag ? TOK_FLAG_WRAP_CONFIDENTIAL : 0);
25127 + outbuf[3] = 0xFF;
25129 + store_uint16_be(ec, outbuf + 4);
25131 + store_uint16_be(0, outbuf + 6);
25132 + store_uint64_be(ctx->sendSeq, outbuf + 8);
25135 + * EC | copy of header to be encrypted, located in
25136 + * (possibly rotated) trailer
25138 + if (trailer == NULL)
25139 + tbuf = (unsigned char *)header->buffer.value + 16; /* Header */
25141 + tbuf = (unsigned char *)trailer->buffer.value;
25143 + memset(tbuf, 0xFF, ec);
25144 + memcpy(tbuf + ec, header->buffer.value, 16);
25146 + code = gssEapEncrypt(krbContext,
25147 + ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0),
25148 + ec, rrc, KRB_CRYPTO_CONTEXT(ctx),
25149 + keyUsage, iov, iov_count);
25154 + store_uint16_be(rrc, outbuf + 6);
25157 + } else if (toktype == TOK_TYPE_WRAP && !conf_req_flag) {
25158 + wrap_with_checksum:
25160 + gssHeaderLen = 16;
25162 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25163 + KRB5_CRYPTO_TYPE_CHECKSUM, &gssTrailerLen);
25167 + GSSEAP_ASSERT(gssTrailerLen <= 0xFFFF);
25169 + if (trailer == NULL) {
25170 + rrc = gssTrailerLen;
25171 + gssHeaderLen += gssTrailerLen;
25174 + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25175 + code = gssEapAllocIov(header, (size_t)gssHeaderLen);
25176 + else if (header->buffer.length < gssHeaderLen)
25177 + code = GSSEAP_WRONG_SIZE;
25180 + outbuf = (unsigned char *)header->buffer.value;
25181 + header->buffer.length = (size_t)gssHeaderLen;
25183 + if (trailer != NULL) {
25184 + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25185 + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen);
25186 + else if (trailer->buffer.length < gssTrailerLen)
25187 + code = GSSEAP_WRONG_SIZE;
25190 + trailer->buffer.length = (size_t)gssTrailerLen;
25194 + store_uint16_be((uint16_t)toktype, outbuf);
25196 + outbuf[2] = flags;
25198 + outbuf[3] = 0xFF;
25199 + if (toktype == TOK_TYPE_WRAP) {
25200 + /* Use 0 for checksum calculation, substitute
25201 + * checksum length later.
25204 + store_uint16_be(0, outbuf + 4);
25206 + store_uint16_be(0, outbuf + 6);
25208 + /* MIC and DEL store 0xFF in EC and RRC */
25209 + store_uint16_be(0xFFFF, outbuf + 4);
25210 + store_uint16_be(0xFFFF, outbuf + 6);
25212 + store_uint64_be(ctx->sendSeq, outbuf + 8);
25214 + code = gssEapSign(krbContext, ctx->checksumType, rrc,
25215 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
25222 + if (toktype == TOK_TYPE_WRAP) {
25223 + /* Fix up EC field */
25224 + store_uint16_be(gssTrailerLen, outbuf + 4);
25225 + /* Fix up RRC field */
25226 + store_uint16_be(rrc, outbuf + 6);
25228 + } else if (toktype == TOK_TYPE_MIC) {
25230 + goto wrap_with_checksum;
25231 + } else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
25233 + goto wrap_with_checksum;
25239 + if (conf_state != NULL)
25240 + *conf_state = conf_req_flag;
25244 + gssEapReleaseIov(iov, iov_count);
25245 +#ifdef HAVE_HEIMDAL_VERSION
25246 + if (krbCrypto != NULL)
25247 + krb5_crypto_destroy(krbContext, krbCrypto);
25252 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
25255 +OM_uint32 GSSAPI_CALLCONV
25256 +gss_wrap_iov(OM_uint32 *minor,
25257 + gss_ctx_id_t ctx,
25258 + int conf_req_flag,
25259 + gss_qop_t qop_req,
25261 + gss_iov_buffer_desc *iov,
25266 + if (ctx == GSS_C_NO_CONTEXT) {
25268 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25271 + if (qop_req != GSS_C_QOP_DEFAULT) {
25272 + *minor = GSSEAP_UNKNOWN_QOP;
25273 + return GSS_S_UNAVAILABLE;
25278 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25280 + if (!CTX_IS_ESTABLISHED(ctx)) {
25281 + major = GSS_S_NO_CONTEXT;
25282 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25286 + major = gssEapWrapOrGetMIC(minor, ctx, conf_req_flag, conf_state,
25287 + iov, iov_count, TOK_TYPE_WRAP);
25288 + if (GSS_ERROR(major))
25292 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
25296 diff --git a/mech_eap/wrap_iov_length.c b/mech_eap/wrap_iov_length.c
25297 new file mode 100644
25298 index 0000000..247b78d
25300 +++ b/mech_eap/wrap_iov_length.c
25303 + * Copyright (c) 2011, JANET(UK)
25304 + * All rights reserved.
25306 + * Redistribution and use in source and binary forms, with or without
25307 + * modification, are permitted provided that the following conditions
25310 + * 1. Redistributions of source code must retain the above copyright
25311 + * notice, this list of conditions and the following disclaimer.
25313 + * 2. Redistributions in binary form must reproduce the above copyright
25314 + * notice, this list of conditions and the following disclaimer in the
25315 + * documentation and/or other materials provided with the distribution.
25317 + * 3. Neither the name of JANET(UK) nor the names of its contributors
25318 + * may be used to endorse or promote products derived from this software
25319 + * without specific prior written permission.
25321 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25322 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25323 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25324 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25325 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25326 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25327 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25328 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25329 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25330 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25334 + * Copyright 2008 by the Massachusetts Institute of Technology.
25335 + * All Rights Reserved.
25337 + * Export of this software from the United States of America may
25338 + * require a specific license from the United States Government.
25339 + * It is the responsibility of any person or organization contemplating
25340 + * export to obtain such a license before exporting.
25342 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
25343 + * distribute this software and its documentation for any purpose and
25344 + * without fee is hereby granted, provided that the above copyright
25345 + * notice appear in all copies and that both that copyright notice and
25346 + * this permission notice appear in supporting documentation, and that
25347 + * the name of M.I.T. not be used in advertising or publicity pertaining
25348 + * to distribution of the software without specific, written prior
25349 + * permission. Furthermore if you modify this software you must label
25350 + * your software as modified software and not distribute it in such a
25351 + * fashion that it might be confused with the original M.I.T. software.
25352 + * M.I.T. makes no representations about the suitability of
25353 + * this software for any purpose. It is provided "as is" without express
25354 + * or implied warranty.
25358 + * Message protection services: determine protected message size.
25361 +#include "gssapiP_eap.h"
25363 +#define INIT_IOV_DATA(_iov) do { (_iov)->buffer.value = NULL; \
25364 + (_iov)->buffer.length = 0; } \
25368 +gssEapWrapIovLength(OM_uint32 *minor,
25369 + gss_ctx_id_t ctx,
25370 + int conf_req_flag,
25371 + gss_qop_t qop_req,
25373 + gss_iov_buffer_desc *iov,
25376 + gss_iov_buffer_t header, trailer, padding;
25377 + size_t dataLength, assocDataLength;
25378 + size_t gssHeaderLen, gssPadLen, gssTrailerLen;
25379 + size_t krbHeaderLen = 0, krbTrailerLen = 0, krbPadLen = 0;
25380 + krb5_error_code code;
25381 + krb5_context krbContext;
25384 +#ifdef HAVE_HEIMDAL_VERSION
25385 + krb5_crypto krbCrypto = NULL;
25388 + if (qop_req != GSS_C_QOP_DEFAULT) {
25389 + *minor = GSSEAP_UNKNOWN_QOP;
25390 + return GSS_S_UNAVAILABLE;
25393 + if (ctx->encryptionType == ENCTYPE_NULL) {
25394 + *minor = GSSEAP_KEY_UNAVAILABLE;
25395 + return GSS_S_UNAVAILABLE;
25398 + GSSEAP_KRB_INIT(&krbContext);
25400 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
25401 + if (header == NULL) {
25402 + *minor = GSSEAP_MISSING_IOV;
25403 + return GSS_S_FAILURE;
25405 + INIT_IOV_DATA(header);
25407 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
25408 + if (trailer != NULL) {
25409 + INIT_IOV_DATA(trailer);
25412 + dce_style = ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0);
25414 + /* For CFX, EC is used instead of padding, and is placed in header or trailer */
25415 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
25416 + if (padding != NULL) {
25417 + INIT_IOV_DATA(padding);
25420 + gssEapIovMessageLength(iov, iov_count, &dataLength, &assocDataLength);
25422 + if (conf_req_flag && gssEapIsIntegrityOnly(iov, iov_count))
25423 + conf_req_flag = FALSE;
25425 + gssHeaderLen = gssPadLen = gssTrailerLen = 0;
25427 +#ifdef HAVE_HEIMDAL_VERSION
25428 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
25433 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25435 + KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM,
25439 + return GSS_S_FAILURE;
25442 + if (conf_req_flag) {
25443 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25444 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
25447 + return GSS_S_FAILURE;
25451 + gssHeaderLen = 16; /* Header */
25452 + if (conf_req_flag) {
25453 + gssHeaderLen += krbHeaderLen; /* Kerb-Header */
25454 + gssTrailerLen = 16 /* E(Header) */ + krbTrailerLen; /* Kerb-Trailer */
25456 + code = krbPaddingLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25457 + dataLength - assocDataLength + 16 /* E(Header) */,
25461 + return GSS_S_FAILURE;
25464 + if (krbPadLen == 0 && dce_style) {
25465 + /* Windows rejects AEAD tokens with non-zero EC */
25466 + code = krbBlockSize(krbContext, KRB_CRYPTO_CONTEXT(ctx), &ec);
25469 + return GSS_S_FAILURE;
25474 + gssTrailerLen += ec;
25476 + gssTrailerLen = krbTrailerLen; /* Kerb-Checksum */
25479 + dataLength += gssPadLen;
25481 + if (trailer == NULL)
25482 + gssHeaderLen += gssTrailerLen;
25484 + trailer->buffer.length = gssTrailerLen;
25486 + GSSEAP_ASSERT(gssPadLen == 0 || padding != NULL);
25488 + if (padding != NULL)
25489 + padding->buffer.length = gssPadLen;
25491 + header->buffer.length = gssHeaderLen;
25493 + if (conf_state != NULL)
25494 + *conf_state = conf_req_flag;
25497 + return GSS_S_COMPLETE;
25500 +OM_uint32 GSSAPI_CALLCONV
25501 +gss_wrap_iov_length(OM_uint32 *minor,
25502 + gss_ctx_id_t ctx,
25503 + int conf_req_flag,
25504 + gss_qop_t qop_req,
25506 + gss_iov_buffer_desc *iov,
25511 + if (ctx == GSS_C_NO_CONTEXT) {
25513 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25518 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25520 + if (!CTX_IS_ESTABLISHED(ctx)) {
25521 + major = GSS_S_NO_CONTEXT;
25522 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25526 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
25527 + conf_state, iov, iov_count);
25528 + if (GSS_ERROR(major))
25532 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
25536 diff --git a/mech_eap/wrap_size_limit.c b/mech_eap/wrap_size_limit.c
25537 new file mode 100644
25538 index 0000000..d11fd63
25540 +++ b/mech_eap/wrap_size_limit.c
25543 + * Copyright (c) 2011, JANET(UK)
25544 + * All rights reserved.
25546 + * Redistribution and use in source and binary forms, with or without
25547 + * modification, are permitted provided that the following conditions
25550 + * 1. Redistributions of source code must retain the above copyright
25551 + * notice, this list of conditions and the following disclaimer.
25553 + * 2. Redistributions in binary form must reproduce the above copyright
25554 + * notice, this list of conditions and the following disclaimer in the
25555 + * documentation and/or other materials provided with the distribution.
25557 + * 3. Neither the name of JANET(UK) nor the names of its contributors
25558 + * may be used to endorse or promote products derived from this software
25559 + * without specific prior written permission.
25561 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25562 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25563 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25564 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25565 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25566 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25567 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25568 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25569 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25570 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25575 + * Message protection services: determine maximum input size.
25578 +#include "gssapiP_eap.h"
25580 +OM_uint32 GSSAPI_CALLCONV
25581 +gss_wrap_size_limit(OM_uint32 *minor,
25582 + gss_ctx_id_t ctx,
25583 + int conf_req_flag,
25584 + gss_qop_t qop_req,
25585 + OM_uint32 req_output_size,
25586 + OM_uint32 *max_input_size)
25588 + gss_iov_buffer_desc iov[4];
25589 + OM_uint32 major, overhead;
25591 + if (ctx == GSS_C_NO_CONTEXT) {
25593 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25598 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25600 + if (!CTX_IS_ESTABLISHED(ctx)) {
25601 + major = GSS_S_NO_CONTEXT;
25602 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25606 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
25607 + iov[0].buffer.value = NULL;
25608 + iov[0].buffer.length = 0;
25610 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
25611 + iov[1].buffer.length = req_output_size;
25612 + iov[1].buffer.value = NULL;
25614 + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
25615 + iov[2].buffer.value = NULL;
25616 + iov[2].buffer.length = 0;
25618 + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
25619 + iov[3].buffer.value = NULL;
25620 + iov[3].buffer.length = 0;
25622 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
25624 + if (GSS_ERROR(major))
25627 + overhead = iov[0].buffer.length + iov[3].buffer.length;
25629 + if (iov[2].buffer.length == 0 && overhead < req_output_size)
25630 + *max_input_size = req_output_size - overhead;
25632 + *max_input_size = 0;
25635 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);