1 From d491bc19b59fd9d6d9a46fffef1ed82ddec2503d Mon Sep 17 00:00:00 2001
2 From: Pete Fotheringham <pete.fotheringham@codethink.co.uk>
3 Date: Thu, 29 Dec 2011 10:05:50 +0000
4 Subject: [PATCH] Move moonshot files up
8 acinclude.m4 | 364 ++++++++++
10 build-aux/compile | 144 ++++
14 mech_eap.spec.in | 62 ++
15 mech_eap/.gitignore | 32 +
16 mech_eap/AUTHORS | 6 +
17 mech_eap/COPYING | 3 +
18 mech_eap/LICENSE | 31 +
19 mech_eap/Makefile.am | 189 ++++++
21 mech_eap/README | 147 ++++
22 mech_eap/README.samba4 | 52 ++
24 mech_eap/accept_sec_context.c | 1072 +++++++++++++++++++++++++++++
25 mech_eap/acquire_cred.c | 52 ++
26 mech_eap/acquire_cred_with_password.c | 67 ++
27 mech_eap/add_cred.c | 87 +++
28 mech_eap/add_cred_with_password.c | 93 +++
29 mech_eap/authdata_plugin.h | 331 +++++++++
30 mech_eap/authorize_localname.c | 54 ++
31 mech_eap/canonicalize_name.c | 64 ++
32 mech_eap/compare_name.c | 46 ++
33 mech_eap/context_time.c | 69 ++
34 mech_eap/delete_name_attribute.c | 60 ++
35 mech_eap/delete_sec_context.c | 81 +++
36 mech_eap/dictionary.ukerna | 20 +
37 mech_eap/display_name.c | 48 ++
38 mech_eap/display_name_ext.c | 51 ++
39 mech_eap/display_status.c | 203 ++++++
40 mech_eap/duplicate_name.c | 60 ++
41 mech_eap/eap_mech.c | 219 ++++++
42 mech_eap/exchange_meta_data.c | 82 +++
43 mech_eap/export_name.c | 60 ++
44 mech_eap/export_name_composite.c | 62 ++
45 mech_eap/export_sec_context.c | 246 +++++++
46 mech_eap/get_mic.c | 89 +++
47 mech_eap/get_name_attribute.c | 67 ++
48 mech_eap/gssapiP_eap.h | 410 +++++++++++
49 mech_eap/gssapi_eap.h | 90 +++
50 mech_eap/gsseap_err.et | 162 +++++
51 mech_eap/import_name.c | 47 ++
52 mech_eap/import_sec_context.c | 374 ++++++++++
53 mech_eap/indicate_mechs.c | 44 ++
54 mech_eap/init_sec_context.c | 1097 ++++++++++++++++++++++++++++++
55 mech_eap/inquire_attrs_for_mech.c | 137 ++++
56 mech_eap/inquire_context.c | 116 ++++
57 mech_eap/inquire_cred.c | 61 ++
58 mech_eap/inquire_cred_by_mech.c | 76 +++
59 mech_eap/inquire_cred_by_oid.c | 83 +++
60 mech_eap/inquire_mech_for_saslname.c | 84 +++
61 mech_eap/inquire_mechs_for_name.c | 69 ++
62 mech_eap/inquire_name.c | 75 ++
63 mech_eap/inquire_names_for_mech.c | 77 +++
64 mech_eap/inquire_saslname_for_mech.c | 51 ++
65 mech_eap/inquire_sec_context_by_oid.c | 248 +++++++
66 mech_eap/install-sh | 520 ++++++++++++++
67 mech_eap/map_name_to_any.c | 58 ++
69 mech_eap/mech_eap-noacceptor.exports | 55 ++
70 mech_eap/mech_eap.exports | 63 ++
71 mech_eap/mech_invoke.c | 44 ++
72 mech_eap/process_context_token.c | 71 ++
73 mech_eap/pseudo_random.c | 195 ++++++
74 mech_eap/query_mechanism_info.c | 67 ++
75 mech_eap/query_meta_data.c | 116 ++++
76 mech_eap/radius_ad.exports | 1 +
77 mech_eap/radsec.conf | 12 +
78 mech_eap/radsec_err.et | 38 +
79 mech_eap/release_any_name_mapping.c | 59 ++
80 mech_eap/release_cred.c | 44 ++
81 mech_eap/release_name.c | 44 ++
82 mech_eap/release_oid.c | 44 ++
83 mech_eap/set_cred_option.c | 208 ++++++
84 mech_eap/set_name_attribute.c | 60 ++
85 mech_eap/set_sec_context_option.c | 87 +++
86 mech_eap/store_cred.c | 83 +++
87 mech_eap/unwrap.c | 85 +++
88 mech_eap/unwrap_iov.c | 572 ++++++++++++++++
89 mech_eap/util.h | 1032 ++++++++++++++++++++++++++++
90 mech_eap/util_adshim.c | 242 +++++++
91 mech_eap/util_attr.cpp | 1191 ++++++++++++++++++++++++++++++++
92 mech_eap/util_attr.h | 389 +++++++++++
93 mech_eap/util_base64.c | 161 +++++
94 mech_eap/util_base64.h | 58 ++
95 mech_eap/util_buffer.c | 103 +++
96 mech_eap/util_cksum.c | 242 +++++++
97 mech_eap/util_context.c | 377 +++++++++++
98 mech_eap/util_cred.c | 756 +++++++++++++++++++++
99 mech_eap/util_crypt.c | 397 +++++++++++
100 mech_eap/util_json.cpp | 513 ++++++++++++++
101 mech_eap/util_json.h | 182 +++++
102 mech_eap/util_krb.c | 632 +++++++++++++++++
103 mech_eap/util_lucid.c | 183 +++++
104 mech_eap/util_mech.c | 380 +++++++++++
105 mech_eap/util_moonshot.c | 238 +++++++
106 mech_eap/util_name.c | 789 ++++++++++++++++++++++
107 mech_eap/util_oid.c | 206 ++++++
108 mech_eap/util_ordering.c | 302 +++++++++
109 mech_eap/util_radius.cpp | 899 +++++++++++++++++++++++++
110 mech_eap/util_radius.h | 183 +++++
111 mech_eap/util_reauth.c | 1196 +++++++++++++++++++++++++++++++++
112 mech_eap/util_reauth.h | 151 +++++
113 mech_eap/util_saml.cpp | 775 +++++++++++++++++++++
114 mech_eap/util_saml.h | 176 +++++
115 mech_eap/util_shib.cpp | 555 +++++++++++++++
116 mech_eap/util_shib.h | 122 ++++
117 mech_eap/util_sm.c | 372 ++++++++++
118 mech_eap/util_tld.c | 167 +++++
119 mech_eap/util_token.c | 493 ++++++++++++++
120 mech_eap/verify_mic.c | 71 ++
121 mech_eap/wrap.c | 137 ++++
122 mech_eap/wrap_iov.c | 379 +++++++++++
123 mech_eap/wrap_iov_length.c | 234 +++++++
124 mech_eap/wrap_size_limit.c | 97 +++
125 118 files changed, 24691 insertions(+), 0 deletions(-)
126 create mode 100644 Makefile.am
127 create mode 100644 acinclude.m4
128 create mode 100755 autogen.sh
129 create mode 100755 build-aux/compile
130 create mode 100644 configure.ac
131 create mode 160000 libeap
132 create mode 100644 m4/minuso.m4
133 create mode 100644 mech_eap.spec.in
134 create mode 100644 mech_eap/.gitignore
135 create mode 100644 mech_eap/AUTHORS
136 create mode 100644 mech_eap/COPYING
137 create mode 100644 mech_eap/LICENSE
138 create mode 100644 mech_eap/Makefile.am
139 create mode 100644 mech_eap/NEWS
140 create mode 100644 mech_eap/NOTES
141 create mode 100644 mech_eap/README
142 create mode 100644 mech_eap/README.samba4
143 create mode 100644 mech_eap/TODO
144 create mode 100644 mech_eap/accept_sec_context.c
145 create mode 100644 mech_eap/acquire_cred.c
146 create mode 100644 mech_eap/acquire_cred_with_password.c
147 create mode 100644 mech_eap/add_cred.c
148 create mode 100644 mech_eap/add_cred_with_password.c
149 create mode 100644 mech_eap/authdata_plugin.h
150 create mode 100644 mech_eap/authorize_localname.c
151 create mode 100644 mech_eap/canonicalize_name.c
152 create mode 100644 mech_eap/compare_name.c
153 create mode 100644 mech_eap/context_time.c
154 create mode 100644 mech_eap/delete_name_attribute.c
155 create mode 100644 mech_eap/delete_sec_context.c
156 create mode 100644 mech_eap/dictionary.ukerna
157 create mode 100644 mech_eap/display_name.c
158 create mode 100644 mech_eap/display_name_ext.c
159 create mode 100644 mech_eap/display_status.c
160 create mode 100644 mech_eap/duplicate_name.c
161 create mode 100644 mech_eap/eap_mech.c
162 create mode 100644 mech_eap/exchange_meta_data.c
163 create mode 100644 mech_eap/export_name.c
164 create mode 100644 mech_eap/export_name_composite.c
165 create mode 100644 mech_eap/export_sec_context.c
166 create mode 100644 mech_eap/get_mic.c
167 create mode 100644 mech_eap/get_name_attribute.c
168 create mode 100644 mech_eap/gssapiP_eap.h
169 create mode 100644 mech_eap/gssapi_eap.h
170 create mode 100644 mech_eap/gsseap_err.et
171 create mode 100644 mech_eap/import_name.c
172 create mode 100644 mech_eap/import_sec_context.c
173 create mode 100644 mech_eap/indicate_mechs.c
174 create mode 100644 mech_eap/init_sec_context.c
175 create mode 100644 mech_eap/inquire_attrs_for_mech.c
176 create mode 100644 mech_eap/inquire_context.c
177 create mode 100644 mech_eap/inquire_cred.c
178 create mode 100644 mech_eap/inquire_cred_by_mech.c
179 create mode 100644 mech_eap/inquire_cred_by_oid.c
180 create mode 100644 mech_eap/inquire_mech_for_saslname.c
181 create mode 100644 mech_eap/inquire_mechs_for_name.c
182 create mode 100644 mech_eap/inquire_name.c
183 create mode 100644 mech_eap/inquire_names_for_mech.c
184 create mode 100644 mech_eap/inquire_saslname_for_mech.c
185 create mode 100644 mech_eap/inquire_sec_context_by_oid.c
186 create mode 100755 mech_eap/install-sh
187 create mode 100644 mech_eap/map_name_to_any.c
188 create mode 100644 mech_eap/mech
189 create mode 100644 mech_eap/mech_eap-noacceptor.exports
190 create mode 100644 mech_eap/mech_eap.exports
191 create mode 100644 mech_eap/mech_invoke.c
192 create mode 100644 mech_eap/process_context_token.c
193 create mode 100644 mech_eap/pseudo_random.c
194 create mode 100644 mech_eap/query_mechanism_info.c
195 create mode 100644 mech_eap/query_meta_data.c
196 create mode 100644 mech_eap/radius_ad.exports
197 create mode 100644 mech_eap/radsec.conf
198 create mode 100644 mech_eap/radsec_err.et
199 create mode 100644 mech_eap/release_any_name_mapping.c
200 create mode 100644 mech_eap/release_cred.c
201 create mode 100644 mech_eap/release_name.c
202 create mode 100644 mech_eap/release_oid.c
203 create mode 100644 mech_eap/set_cred_option.c
204 create mode 100644 mech_eap/set_name_attribute.c
205 create mode 100644 mech_eap/set_sec_context_option.c
206 create mode 100644 mech_eap/store_cred.c
207 create mode 100644 mech_eap/unwrap.c
208 create mode 100644 mech_eap/unwrap_iov.c
209 create mode 100644 mech_eap/util.h
210 create mode 100644 mech_eap/util_adshim.c
211 create mode 100644 mech_eap/util_attr.cpp
212 create mode 100644 mech_eap/util_attr.h
213 create mode 100644 mech_eap/util_base64.c
214 create mode 100644 mech_eap/util_base64.h
215 create mode 100644 mech_eap/util_buffer.c
216 create mode 100644 mech_eap/util_cksum.c
217 create mode 100644 mech_eap/util_context.c
218 create mode 100644 mech_eap/util_cred.c
219 create mode 100644 mech_eap/util_crypt.c
220 create mode 100644 mech_eap/util_json.cpp
221 create mode 100644 mech_eap/util_json.h
222 create mode 100644 mech_eap/util_krb.c
223 create mode 100644 mech_eap/util_lucid.c
224 create mode 100644 mech_eap/util_mech.c
225 create mode 100644 mech_eap/util_moonshot.c
226 create mode 100644 mech_eap/util_name.c
227 create mode 100644 mech_eap/util_oid.c
228 create mode 100644 mech_eap/util_ordering.c
229 create mode 100644 mech_eap/util_radius.cpp
230 create mode 100644 mech_eap/util_radius.h
231 create mode 100644 mech_eap/util_reauth.c
232 create mode 100644 mech_eap/util_reauth.h
233 create mode 100644 mech_eap/util_saml.cpp
234 create mode 100644 mech_eap/util_saml.h
235 create mode 100644 mech_eap/util_shib.cpp
236 create mode 100644 mech_eap/util_shib.h
237 create mode 100644 mech_eap/util_sm.c
238 create mode 100644 mech_eap/util_tld.c
239 create mode 100644 mech_eap/util_token.c
240 create mode 100644 mech_eap/verify_mic.c
241 create mode 100644 mech_eap/wrap.c
242 create mode 100644 mech_eap/wrap_iov.c
243 create mode 100644 mech_eap/wrap_iov_length.c
244 create mode 100644 mech_eap/wrap_size_limit.c
246 diff --git a/Makefile.am b/Makefile.am
248 index 0000000..0165219
252 +AUTOMAKE_OPTIONS = foreign
253 +ACLOCAL_AMFLAGS = -I m4
254 +SUBDIRS = libeap mech_eap
255 +EXTRA_DIST = mech_eap.spec
256 diff --git a/acinclude.m4 b/acinclude.m4
258 index 0000000..6f43261
262 +dnl Based on the one from the Boinc project by Reinhard
264 +AC_DEFUN([AX_CHECK_WINDOWS],
265 +[AC_MSG_CHECKING(for windows)
267 +AC_CHECK_HEADER(windows.h,[target_windows="yes"],[target_windows="no"])
268 +AC_MSG_RESULT($target_windows)
269 +AM_CONDITIONAL(TARGET_WINDOWS,test "x$target_windows" = "xyes")
272 +AC_DEFUN([AX_CHECK_KRB5],
273 +[AC_MSG_CHECKING(for GSS-API and Kerberos implementation)
277 + AC_HELP_STRING([--with-krb5],
278 + [Use krb5 (in specified installation directory)]),
279 + [check_krb5_dir="$withval"],
281 +for dir in $check_krb5_dir $prefix /usr/local /usr ; do
283 + if test -x "$dir/bin/krb5-config"; then
285 + if test "x$target_windows" = "xyes"; then
286 + KRB5_CFLAGS=-I"$check_krb5_dir/include";
287 + KRB5_LDFLAGS="-L$check_krb5_dir/lib/";
288 + KRB5_LIBS="-lkrb5_32 -lgssapi32";
289 + COMPILE_ET="$check_krb5_dir/bin/compile_et";
290 + AC_MSG_RESULT([yes])
292 + KRB5_CFLAGS=`$dir/bin/krb5-config gssapi --cflags`;
293 + KRB5_LDFLAGS="-L$dir/lib";
294 + KRB5_LIBS=`$dir/bin/krb5-config gssapi --libs`
295 +AC_MSG_RESULT([yes])
296 + AC_PATH_PROG(COMPILE_ET, [compile_et], [compile_et], [$dir/bin$PATH_SEPARATOr])
301 +if test x_$found_krb5 != x_yes; then
302 + AC_MSG_RESULT($found_krb5)
304 +----------------------------------------------------------------------
305 + Cannot find GSS-API/Kerberos libraries.
307 + Please install MIT or Heimdal or specify installation directory with
309 +----------------------------------------------------------------------
312 + printf "Kerberos found in $krb5dir\n";
313 + AC_SUBST(KRB5_CFLAGS)
314 + AC_SUBST(KRB5_LDFLAGS)
315 + AC_SUBST(KRB5_LIBS)
316 + AC_SUBST(COMPILE_ET)
317 + 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")
318 + 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")
319 + 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")
320 + 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")
321 + AM_CONDITIONAL(HEIMDAL, test "x$heimdal" != "xno")
325 +AC_DEFUN([AX_CHECK_EAP],
326 +[AC_MSG_CHECKING(for EAP implementation)
330 + AC_HELP_STRING([--with-eap],
331 + [Use eap (in specified installation directory)]),
332 + [check_eap_dir="$withval"],
334 +for dir in $check_eap_dir $prefix /usr /usr/local ../libeap ; do
336 + if test -f "$dir/src/eap_peer/eap.h"; then
338 + EAP_DIR="${eapdir}"
339 + EAP_CFLAGS="-I$eapdir/src/common -I$eapdir/src -I$eapdir/src/utils";
343 +AC_MSG_RESULT($found_eap)
344 +if test x_$found_eap != x_yes; then
346 +----------------------------------------------------------------------
347 + Cannot find EAP libraries.
349 + Please install wpa_supplicant or specify installation directory with
351 +----------------------------------------------------------------------
354 + printf "EAP found in $eapdir\n";
355 + EAP_CFLAGS="$EAP_CFLAGS \
369 +-DEAP_SERVER_IDENTITY \
374 +-DEAP_SERVER_MSCHAPV2 \
380 +-DEAP_SERVER_GPSK_SHA256 \
382 + EAP_LIBS="-leap -lutils -lcrypto -ltls";
383 + EAP_LDFLAGS="-L$eapdir/eap_example -L$eapdir/src/utils -L$eapdir/src/crypto -L$eapdir/src/tls";
384 + AC_SUBST(EAP_CFLAGS)
385 + AC_SUBST(EAP_LDFLAGS)
390 +AC_DEFUN([AX_CHECK_SHIBSP],
391 +[AC_MSG_CHECKING(for Shibboleth implementation)
395 + AC_HELP_STRING([--with-shibsp],
396 + [Use shibspboleth (in specified installation directory)]),
397 + [check_shibsp_dir="$withval"],
398 + [check_shibsp_dir=])
399 +for dir in $check_shibsp_dir $prefix /usr /usr/local ; do
401 + if test -f "$dir/include/shibsp/SPConfig.h"; then
402 + found_shibsp="yes";
403 + SHIBSP_DIR="${shibspdir}"
404 + SHIBSP_CXXFLAGS="-I$shibspdir/include";
408 +AC_MSG_RESULT($found_shibsp)
409 +if test x_$found_shibsp != x_yes; then
411 +----------------------------------------------------------------------
412 + Cannot find Shibboleth libraries.
414 + Please install Shibboleth or specify installation directory with
415 + --with-shibsp=(dir).
416 +----------------------------------------------------------------------
419 + printf "Shibboleth found in $shibspdir\n";
420 + SHIBSP_LIBS="-lshibsp -lsaml -lxml-security-c -lxmltooling -lxerces-c";
421 + SHIBSP_LDFLAGS="-L$shibspdir/lib";
422 + AC_SUBST(SHIBSP_CXXFLAGS)
423 + AC_SUBST(SHIBSP_LDFLAGS)
424 + AC_SUBST(SHIBSP_LIBS)
425 + AC_DEFINE_UNQUOTED([HAVE_SHIBSP], 1, [Define is Shibboleth SP is available])
429 +AC_DEFUN([AX_CHECK_SHIBRESOLVER],
430 +[AC_MSG_CHECKING(for Shibboleth resolver implementation)
432 +found_shibresolver="no"
433 +AC_ARG_WITH(shibresolver,
434 + AC_HELP_STRING([--with-shibresolver],
435 + [Use Shibboleth resolver (in specified installation directory)]),
436 + [check_shibresolver_dir="$withval"],
437 + [check_shibresolver_dir=])
438 +if test x_$check_shibresolver_dir != x_no; then
439 +for dir in $check_shibresolver_dir $prefix /usr /usr/local ; do
440 + shibresolverdir="$dir"
441 + if test -f "$dir/include/shibresolver/resolver.h"; then
442 + found_shibresolver="yes";
443 + SHIBRESOLVER_DIR="${shibresolverdir}"
444 + SHIBRESOLVER_CXXFLAGS="-I$shibresolverdir/include";
449 +AC_MSG_RESULT($found_shibresolver)
450 +if test x_$check_shibresolver_dir != x_no; then
451 +if test x_$found_shibresolver != x_yes; then
453 +----------------------------------------------------------------------
454 + Cannot find Shibboleth resolver libraries, building without
455 + Shibboleth support.
457 + Please install Shibboleth or specify installation directory with
458 + --with-shibresolver=(dir).
459 +----------------------------------------------------------------------
462 + printf "Shibboleth resolver found in $shibresolverdir\n";
463 + SHIBRESOLVER_LIBS="-lshibresolver";
464 + SHIBRESOLVER_LDFLAGS="-L$shibresolverdir/lib";
465 + AC_SUBST(SHIBRESOLVER_CXXFLAGS)
466 + AC_SUBST(SHIBRESOLVER_LDFLAGS)
467 + AC_SUBST(SHIBRESOLVER_LIBS)
468 + AC_DEFINE_UNQUOTED([HAVE_SHIBRESOLVER], 1, [Define is Shibboleth resolver is available])
473 +AC_DEFUN([AX_CHECK_OPENSAML],
474 +[AC_MSG_CHECKING(for OpenSAML implementation)
477 +AC_ARG_WITH(opensaml,
478 + AC_HELP_STRING([--with-opensaml],
479 + [Use OpenSAML (in specified installation directory)]),
480 + [check_opensaml_dir="$withval"],
481 + [check_opensaml_dir=])
482 +if test x_$check_opensaml_dir != x_no; then
483 +for dir in $check_opensaml_dir $prefix /usr /usr/local ; do
485 + if test -f "$dir/include/saml/Assertion.h"; then
486 + found_opensaml="yes";
487 + OPENSAML_DIR="${opensamldir}"
488 + OPENSAML_CXXFLAGS="-I$opensamldir/include";
493 +AC_MSG_RESULT($found_opensaml)
494 +if test x_$check_opensaml_dir != x_no; then
495 +if test x_$found_opensaml != x_yes; then
497 +----------------------------------------------------------------------
498 + Cannot find OpenSAML libraries, building without OpenSAML support.
500 + Please install OpenSAML or specify installation directory with
501 + --with-opensaml=(dir).
502 +----------------------------------------------------------------------
505 + printf "OpenSAML found in $opensamldir\n";
506 + OPENSAML_LIBS="-lsaml -lxml-security-c -lxmltooling -lxerces-c";
507 + OPENSAML_LDFLAGS="-L$opensamldir/lib";
508 + AC_SUBST(OPENSAML_CXXFLAGS)
509 + AC_SUBST(OPENSAML_LDFLAGS)
510 + AC_SUBST(OPENSAML_LIBS)
511 + AC_DEFINE_UNQUOTED([HAVE_OPENSAML], 1, [Define is OpenSAML is available])
516 +AC_DEFUN([AX_CHECK_RADSEC],
517 +[AC_MSG_CHECKING(for radsec)
521 + AC_HELP_STRING([--with-radsec],
522 + [Use radsec (in specified installation directory)]),
523 + [check_radsec_dir="$withval"],
524 + [check_radsec_dir=])
525 +for dir in $check_radsec_dir $prefix /usr /usr/local ; do
527 + if test -f "$dir/include/radsec/radsec.h"; then
528 + found_radsec="yes";
529 + RADSEC_DIR="${radsecdir}"
530 + RADSEC_CFLAGS="-I$radsecdir/include";
534 +AC_MSG_RESULT($found_radsec)
535 +if test x_$found_radsec != x_yes; then
537 +----------------------------------------------------------------------
538 + Cannot find radsec libraries.
540 + Please install libradsec or specify installation directory with
541 + --with-radsec=(dir).
542 +----------------------------------------------------------------------
545 + printf "radsec found in $radsecdir\n";
546 + RADSEC_LIBS="-lradsec";
547 + RADSEC_LDFLAGS="-L$radsecdir/lib";
548 + AC_SUBST(RADSEC_CFLAGS)
549 + AC_SUBST(RADSEC_LDFLAGS)
550 + AC_SUBST(RADSEC_LIBS)
554 +AC_DEFUN([AX_CHECK_JANSSON],
555 +[AC_MSG_CHECKING(for jansson)
558 +AC_ARG_WITH(jansson,
559 + AC_HELP_STRING([--with-jansson],
560 + [Use jansson (in specified installation directory)]),
561 + [check_jansson_dir="$withval"],
562 + [check_jansson_dir=])
563 +for dir in $check_jansson_dir $prefix /usr /usr/local ; do
565 + if test -f "$dir/include/jansson.h"; then
566 + found_jansson="yes";
567 + JANSSON_DIR="${janssondir}"
568 + JANSSON_CFLAGS="-I$janssondir/include";
572 +AC_MSG_RESULT($found_jansson)
573 +if test x_$found_jansson != x_yes; then
575 +----------------------------------------------------------------------
576 + Cannot find jansson libraries.
578 + Please install libjansson or specify installation directory with
579 + --with-jansson=(dir).
580 +----------------------------------------------------------------------
583 + printf "jansson found in $janssondir\n";
584 + JANSSON_LIBS="-ljansson";
585 + JANSSON_LDFLAGS="-L$janssondir/lib";
586 + AC_SUBST(JANSSON_CFLAGS)
587 + AC_SUBST(JANSSON_LDFLAGS)
588 + AC_SUBST(JANSSON_LIBS)
592 +AC_DEFUN([AX_CHECK_LIBMOONSHOT],
593 +[AC_MSG_CHECKING(for Moonshot identity selector implementation)
596 +LIBMOONSHOT_LDFLAGS=
598 +found_libmoonshot="no"
599 +AC_ARG_WITH(libmoonshot,
600 + AC_HELP_STRING([--with-libmoonshot],
601 + [Use libmoonshot (in specified installation directory)]),
602 + [check_libmoonshot_dir="$withval"],
603 + [check_libmoonshot_dir=])
604 +for dir in $check_libmoonshot_dir $prefix /usr /usr/local ; do
605 + libmoonshotdir="$dir"
606 + if test -f "$dir/include/libmoonshot.h"; then
607 + found_libmoonshot="yes";
608 + LIBMOONSHOT_DIR="${libmoonshotdir}"
609 + LIBMOONSHOT_CFLAGS="-I$libmoonshotdir/include";
613 +AC_MSG_RESULT($found_libmoonshot)
614 +if test x_$found_libmoonshot = x_yes; then
615 + printf "libmoonshot found in $libmoonshotdir\n";
616 + LIBMOONSHOT_LIBS="-lmoonshot";
617 + LIBMOONSHOT_LDFLAGS="-L$libmoonshot/lib";
618 + AC_CHECK_LIB(moonshot, moonshot_get_identity, [AC_DEFINE_UNQUOTED([HAVE_MOONSHOT_GET_IDENTITY], 1, [Define if Moonshot identity selector is available])], [], "$LIBMOONSHOT_LIBS")
620 + AC_SUBST(LIBMOONSHOT_CFLAGS)
621 + AC_SUBST(LIBMOONSHOT_LDFLAGS)
622 + AC_SUBST(LIBMOONSHOT_LIBS)
623 + AM_CONDITIONAL(LIBMOONSHOT, test "x$found_libmoonshot" != "xno")
626 diff --git a/autogen.sh b/autogen.sh
628 index 0000000..13432d0
634 +# Regenerate autotools files.
637 +PATH=/usr/local/bin:$PATH
639 +if [ -x "`which autoreconf 2>/dev/null`" ] ; then
640 + exec autoreconf -ivf
643 +aclocal -I . -I m4 && \
645 + libtoolize --automake -c && \
647 + automake --add-missing --copy
648 diff --git a/build-aux/compile b/build-aux/compile
650 index 0000000..5360806
652 +++ b/build-aux/compile
655 +# Wrapper for compilers which do not understand `-c -o'.
657 +scriptversion=2009-10-06.20; # UTC
659 +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software
661 +# Written by Tom Tromey <tromey@cygnus.com>.
663 +# This program is free software; you can redistribute it and/or modify
664 +# it under the terms of the GNU General Public License as published by
665 +# the Free Software Foundation; either version 2, or (at your option)
666 +# any later version.
668 +# This program is distributed in the hope that it will be useful,
669 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
670 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
671 +# GNU General Public License for more details.
673 +# You should have received a copy of the GNU General Public License
674 +# along with this program; if not, write to the Free Software
675 +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
677 +# As a special exception to the GNU General Public License, if you
678 +# distribute this file as part of a program that contains a
679 +# configuration script generated by Autoconf, you may include it under
680 +# the same distribution terms that you use for the rest of that program.
682 +# This file is maintained in Automake, please report
683 +# bugs to <bug-automake@gnu.org> or send patches to
684 +# <automake-patches@gnu.org>.
688 + echo "$0: No command. Try \`$0 --help' for more information." 1>&2
693 +Usage: compile [--help] [--version] PROGRAM [ARGS]
695 +Wrapper for compilers which do not understand `-c -o'.
696 +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
697 +arguments, and rename the output as expected.
699 +If you are trying to build a whole package this is not the
700 +right script to run: please start by reading the file `INSTALL'.
702 +Report bugs to <bug-automake@gnu.org>.
707 + echo "compile $scriptversion"
718 + if test -n "$eat"; then
723 + # configure might choose to run compile as `compile cc -o foo foo.c'.
724 + # So we strip `-o arg' only if arg is an object.
750 +if test -z "$ofile" || test -z "$cfile"; then
751 + # If no `-o' option was seen then we might have been invoked from a
752 + # pattern rule where we don't need one. That is ok -- this is a
753 + # normal compilation that the losing compiler can handle. If no
754 + # `.c' file was seen then we are probably linking. That is also
759 +# Name of file we expect compiler to create.
760 +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
762 +# Create the lock directory.
763 +# Note: use `[/\\:.-]' here to ensure that we don't use the same name
764 +# that we are using for the .o file. Also, base the name on the expected
765 +# object file name, since that is what matters with a parallel build.
766 +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
768 + if mkdir "$lockdir" >/dev/null 2>&1; then
773 +# FIXME: race condition here if user kills between mkdir and trap.
774 +trap "rmdir '$lockdir'; exit 1" 1 2 15
780 +if test -f "$cofile"; then
781 + test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
782 +elif test -f "${cofile}bj"; then
783 + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
790 +# mode: shell-script
792 +# eval: (add-hook 'write-file-hooks 'time-stamp)
793 +# time-stamp-start: "scriptversion="
794 +# time-stamp-format: "%:y-%02m-%02d.%02H"
795 +# time-stamp-time-zone: "UTC"
796 +# time-stamp-end: "; # UTC"
798 diff --git a/configure.ac b/configure.ac
800 index 0000000..4297345
805 +AC_INIT([mech_eap], [0.1], [bugs@project-moonshot.org])
806 +AC_CONFIG_MACRO_DIR([m4])
807 +AC_CONFIG_AUX_DIR([build-aux])
809 +dnl AM_INIT_AUTOMAKE([silent-rules])
810 +AC_USE_SYSTEM_EXTENSIONS
813 +AM_MAINTAINER_MODE()
815 +LT_INIT([dlopen disable-static win32-dll])
819 +AC_CONFIG_HEADERS([config.h])
820 +AC_CHECK_HEADERS(stdarg.h stdio.h stdint.h sys/param.h)
821 +AC_REPLACE_FUNCS(vasprintf)
823 +dnl Check if we're on Solaris and set CFLAGS accordingly
824 +dnl AC_CANONICAL_TARGET
825 +dnl case "${target_os}" in
827 +dnl TARGET_CFLAGS="-DSYS_SOLARIS9 -D_POSIX_PTHREAD_SEMANTICS"
828 +dnl if test "$GCC" != yes ; then
829 +dnl TARGET_CFLAGS="$TARGET_CFLAGS -mt"
831 +dnl TARGET_CFLAGS="$TARGET_CFLAGS -pthreads"
833 +dnl TARGET_LDFLAGS="-lpthread -lsocket -lnsl"
836 +dnl TARGET_CFLAGS="-Wall -pedantic -pthread"
837 +dnl TARGET_LDFLAGS=""
841 +AC_ARG_ENABLE(reauth,
842 + [ --enable-reauth whether to enable fast reauthentication protocol: yes/no; default no ],
843 + [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
846 + echo "--enable-reauth argument must be yes or no"
851 +if test "x$reauth" = "xyes" ; then
852 + echo "Fast reauthentication protocol enabled"
853 + TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_REAUTH"
855 +AM_CONDITIONAL(GSSEAP_ENABLE_REAUTH, test "x$reauth" != "xno")
858 +AC_ARG_ENABLE(acceptor,
859 + [ --enable-acceptor whether to enable acceptor codepaths: yes/no; default yes ],
860 + [ if test "x$enableval" = "xyes" -o "x$enableval" = "xno" ; then
861 + acceptor=$enableval
863 + echo "--enable-acceptor argument must be yes or no"
868 +if test "x$acceptor" = "xyes" ; then
869 + echo "acceptor enabled"
870 + TARGET_CFLAGS="$TARGET_CFLAGS -DGSSEAP_ENABLE_ACCEPTOR"
872 +AM_CONDITIONAL(GSSEAP_ENABLE_ACCEPTOR, test "x$acceptor" != "xno")
874 +AC_SUBST(TARGET_CFLAGS)
875 +AC_SUBST(TARGET_LDFLAGS)
879 +AM_CONDITIONAL(OPENSAML, test "x_$check_opensaml_dir" != "x_no")
881 +AX_CHECK_SHIBRESOLVER
882 +AM_CONDITIONAL(SHIBRESOLVER, test "x_$check_shibresolver_dir" != "x_no")
883 +if test x_$found_shibresolver = x_yes; then
887 +if test "x$acceptor" = "xyes" ; then
892 +AX_CHECK_LIBMOONSHOT
893 +AC_CONFIG_FILES([Makefile libeap/Makefile mech_eap/Makefile
896 diff --git a/libeap b/libeap
898 index 0000000..3c68005
902 +Subproject commit 3c6800594dbfcba5d36cfa5556288eae999f83ba
903 diff --git a/m4/minuso.m4 b/m4/minuso.m4
905 index 0000000..d8b1620
910 +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
911 +# Free Software Foundation, Inc.
913 +# This file is free software; the Free Software Foundation
914 +# gives unlimited permission to copy and/or distribute it,
915 +# with or without modifications, as long as this notice is preserved.
921 +# Like AC_PROG_CC_C_O, but changed for automake.
922 +AC_DEFUN([AM_PROG_CC_C_O],
923 +[AC_REQUIRE([AC_PROG_CC_C_O])dnl
924 +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
925 +AC_REQUIRE_AUX_FILE([compile])dnl
926 +# FIXME: we rely on the cache variable name because
927 +# there is no other way.
929 +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
930 +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
931 +if test "$am_t" != yes; then
932 + # Losing compiler, so override with the script.
933 + # FIXME: It is wrong to rewrite CC.
934 + # But if we don't then we get into trouble of one sort or another.
935 + # A longer-term fix would be to have automake use am__CC in this case,
936 + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
937 + CC="$am_aux_dir/compile $CC"
939 +dnl Make sure AC_PROG_CC is never called again, or it will override our
941 +m4_define([AC_PROG_CC],
942 + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
944 diff --git a/mech_eap.spec.in b/mech_eap.spec.in
946 index 0000000..90ac6cf
948 +++ b/mech_eap.spec.in
950 +%global _moonshot_krb5 %{!?_moonshot_krb5:krb5-devel}%{?_moonshot_krb5}
951 +Name: moonshot-gss-eap
954 +Summary: Moonshot GSS-API Mechanism
956 +Group: Security Tools
958 +URL: http://www.project-moonshot.org/
959 +Source0: mech_eap-%{version}.tar.gz
960 +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
962 +BuildRequires: %{_moonshot_krb5} >= 1.9.1
963 +BuildRequires: moonshot-ui-devel
964 +BuildRequires: jansson-devel
965 +Requires: moonshot-ui
966 +BuildRequires: libradsec-devel
967 +BuildRequires: shibboleth-devel >= 2.5
968 +BuildRequires: libshibresolver-devel
973 +Project Moonshot provides federated access management.
977 +%setup -q -n mech_eap-%{version}
981 + export LDFLAGS='-L/usr/%{_lib}/freeradius -Wl,--rpath=/usr/%{_lib}/freeradius'
982 +%configure --with-libmoonshot=%{_prefix} --with-krb5=%{_prefix} --disable-reauth
983 +make %{?_smp_mflags}
987 +rm -rf $RPM_BUILD_ROOT
988 +make install DESTDIR=$RPM_BUILD_ROOT
992 +rm -rf $RPM_BUILD_ROOT
996 +%defattr(-,root,root,-)
997 +%doc mech_eap/README
998 +%doc mech_eap/LICENSE
999 +%doc mech_eap/AUTHORS
1000 +%{_libdir}/gss/mech_eap.so
1001 +%exclude %{_libdir}/gss/mech_eap.la
1002 +%{_includedir}/gssapi/*.h
1003 +#%exclude %{_libdir}/krb5/plugins/authdata/*la
1004 +#%{_libdir}/krb5/plugins/authdata/*.so
1009 +* Wed Sep 28 2011 <hartmans@moonbuildcentos.dev.ja.net> - @VERSION@-2
1010 +- Add radius_ad plugin
1012 diff --git a/mech_eap/.gitignore b/mech_eap/.gitignore
1013 new file mode 100644
1014 index 0000000..06a3924
1016 +++ b/mech_eap/.gitignore
1050 diff --git a/mech_eap/AUTHORS b/mech_eap/AUTHORS
1051 new file mode 100644
1052 index 0000000..3007a4b
1054 +++ b/mech_eap/AUTHORS
1056 +The initial implementation of mech_eap was written by PADL Software
1057 +under contract to JANET(UK).
1060 +Luke Howard <lukeh@padl.com>
1062 diff --git a/mech_eap/COPYING b/mech_eap/COPYING
1063 new file mode 100644
1064 index 0000000..7554e77
1066 +++ b/mech_eap/COPYING
1068 +Copyright (c) 2011, JANET(UK)
1070 +See the LICENSE file for licensing terms.
1071 diff --git a/mech_eap/LICENSE b/mech_eap/LICENSE
1072 new file mode 100644
1073 index 0000000..1b03a95
1075 +++ b/mech_eap/LICENSE
1078 + * Copyright (c) 2011, JANET(UK)
1079 + * All rights reserved.
1081 + * Redistribution and use in source and binary forms, with or without
1082 + * modification, are permitted provided that the following conditions
1085 + * 1. Redistributions of source code must retain the above copyright
1086 + * notice, this list of conditions and the following disclaimer.
1088 + * 2. Redistributions in binary form must reproduce the above copyright
1089 + * notice, this list of conditions and the following disclaimer in the
1090 + * documentation and/or other materials provided with the distribution.
1092 + * 3. Neither the name of JANET(UK) nor the names of its contributors
1093 + * may be used to endorse or promote products derived from this software
1094 + * without specific prior written permission.
1096 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1097 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1098 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1099 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1100 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1101 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1102 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1103 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1104 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1105 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1108 diff --git a/mech_eap/Makefile.am b/mech_eap/Makefile.am
1109 new file mode 100644
1110 index 0000000..23de6af
1112 +++ b/mech_eap/Makefile.am
1114 +AUTOMAKE_OPTIONS = foreign
1116 +EXTRA_DIST = gsseap_err.et radsec_err.et \
1117 + mech_eap.exports mech_eap-noacceptor.exports radius_ad.exports \
1121 +gssincludedir = $(includedir)/gssapi
1122 +gssinclude_HEADERS = gssapi_eap.h
1124 +EAP_CFLAGS = -I$(srcdir)/../libeap/src -I$(srcdir)/../libeap/src/common -I$(srcdir)/../libeap/src/eap_common \
1125 + -I$(srcdir)/../libeap/src/utils
1127 +if GSSEAP_ENABLE_ACCEPTOR
1128 +GSSEAP_EXPORTS = mech_eap.exports
1130 +GSSEAP_EXPORTS = mech_eap-noacceptor.exports
1133 +gssdir = $(libdir)/gss
1134 +gss_LTLIBRARIES = mech_eap.la
1137 +EAP_CFLAGS += -DCONFIG_WIN32_DEFAULTS -DUSE_INTERNAL_CRYPTO
1138 +OS_LIBS = -lshell32 -ladvapi32 -lws2_32 -lcomerr32
1139 +mech_eap_la_CFLAGS = -Zi
1140 +mech_eap_la_CXXFLAGS = -Zi
1142 +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
1144 +mech_eap_la_CFLAGS = -Werror -Wall -Wunused-parameter
1145 +mech_eap_la_CXXFLAGS = -Werror -Wall -Wunused-parameter
1147 +mech_eap_la_DEPENDENCIES = $(GSSEAP_EXPORTS)
1149 +mech_eap_la_CPPFLAGS = -DBUILD_GSSEAP_LIB -DSYSCONFDIR=\"${sysconfdir}\" -DDATAROOTDIR=\"${datarootdir}\"
1150 +mech_eap_la_CFLAGS += \
1151 + @KRB5_CFLAGS@ @RADSEC_CFLAGS@ @TARGET_CFLAGS@ $(EAP_CFLAGS)
1152 +mech_eap_la_CXXFLAGS += \
1153 + @KRB5_CFLAGS@ @RADSEC_CFLAGS@ \
1154 + @OPENSAML_CXXFLAGS@ @SHIBRESOLVER_CXXFLAGS@ @SHIBSP_CXXFLAGS@ \
1155 + @TARGET_CFLAGS@ $(EAP_CFLAGS)
1156 +mech_eap_la_LDFLAGS = -avoid-version -module \
1157 + -export-symbols $(GSSEAP_EXPORTS) -no-undefined \
1158 + @KRB5_LDFLAGS@ @RADSEC_LDFLAGS@ @TARGET_LDFLAGS@
1160 +mech_eap_la_LDFLAGS += -debug
1163 +mech_eap_la_LIBADD = @KRB5_LIBS@ ../libeap/libeap.la @RADSEC_LIBS@ \
1164 + @OPENSAML_LIBS@ @SHIBRESOLVER_LIBS@ @SHIBSP_LIBS@ @JANSSON_LIBS@
1165 +mech_eap_la_SOURCES = \
1167 + acquire_cred_with_password.c \
1169 + add_cred_with_password.c \
1170 + authorize_localname.c \
1171 + canonicalize_name.c \
1174 + delete_sec_context.c \
1176 + display_name_ext.c \
1177 + display_status.c \
1178 + duplicate_name.c \
1180 + exchange_meta_data.c \
1182 + export_sec_context.c \
1186 + import_sec_context.c \
1187 + indicate_mechs.c \
1188 + init_sec_context.c \
1189 + inquire_attrs_for_mech.c \
1190 + inquire_context.c \
1192 + inquire_cred_by_mech.c \
1193 + inquire_cred_by_oid.c \
1194 + inquire_mech_for_saslname.c \
1195 + inquire_mechs_for_name.c \
1196 + inquire_names_for_mech.c \
1197 + inquire_saslname_for_mech.c \
1198 + inquire_sec_context_by_oid.c \
1199 + process_context_token.c \
1201 + query_mechanism_info.c \
1202 + query_meta_data.c \
1207 + set_cred_option.c \
1208 + set_sec_context_option.c \
1229 + wrap_iov_length.c \
1230 + wrap_size_limit.c \
1242 +mech_eap_la_SOURCES += util_moonshot.c
1243 +mech_eap_la_CFLAGS += @LIBMOONSHOT_CFLAGS@
1244 +mech_eap_la_LDFLAGS += @LIBMOONSHOT_LDFLAGS@
1245 +mech_eap_la_LIBADD += @LIBMOONSHOT_LIBS@
1249 +if GSSEAP_ENABLE_ACCEPTOR
1251 +mech_eap_la_SOURCES += \
1252 + accept_sec_context.c \
1253 + delete_name_attribute.c \
1254 + export_name_composite.c \
1255 + get_name_attribute.c \
1257 + map_name_to_any.c \
1258 + release_any_name_mapping.c \
1259 + set_name_attribute.c \
1266 +mech_eap_la_SOURCES += util_saml.cpp
1270 +mech_eap_la_SOURCES += util_shib.cpp
1275 +BUILT_SOURCES = gsseap_err.c radsec_err.c gsseap_err.h radsec_err.h
1277 +if GSSEAP_ENABLE_REAUTH
1278 +mech_eap_la_SOURCES += util_reauth.c
1281 +krb5pluginsdir = $(libdir)/krb5/plugins/authdata
1282 +krb5plugins_LTLIBRARIES = radius_ad.la
1284 +radius_ad_la_CFLAGS = -Werror -Wall -Wunused-parameter \
1285 + @KRB5_CFLAGS@ $(EAP_CFLAGS) @RADSEC_CFLAGS@ @TARGET_CFLAGS@
1286 +radius_ad_la_LDFLAGS = -avoid-version -module \
1287 + -export-symbols radius_ad.exports -no-undefined
1288 +radius_ad_la_LIBADD = @KRB5_LIBS@
1289 +radius_ad_la_SOURCES = util_adshim.c authdata_plugin.h
1293 +gsseap_err.h gsseap_err.c: gsseap_err.et
1296 +radsec_err.h radsec_err.c: radsec_err.et
1299 +radsec_err.c: radsec_err.h
1302 + rm -f gsseap_err.[ch] radsec_err.[ch]
1303 diff --git a/mech_eap/NEWS b/mech_eap/NEWS
1304 new file mode 100644
1305 index 0000000..e69de29
1306 diff --git a/mech_eap/NOTES b/mech_eap/NOTES
1307 new file mode 100644
1308 index 0000000..849ce4e
1310 +++ b/mech_eap/NOTES
1312 +- gss_xxx routines acquire lock, gssXxx don't
1316 +If you do want to update with a rebase, deletethe branch from the
1317 +server first then push the rebased branch
1319 +to delete a branch from a server git push origin :branch_to_del
1321 diff --git a/mech_eap/README b/mech_eap/README
1322 new file mode 100644
1323 index 0000000..3cb2d50
1325 +++ b/mech_eap/README
1330 +This is an implementation of the GSS EAP mechanism, as described in
1331 +draft-ietf-abfab-gss-eap-01.txt.
1336 +In order to build this, a recent Kerberos implementation (MIT or
1337 +Heimdal), Shibboleth, and EAP libraries are required, along with
1338 +all of their dependencies.
1340 +Note: not all SPIs are supported by the Heimdal mechanism glue,
1341 +so not all features will be available.
1349 +When installing, be sure to edit $prefix/etc/gss/mech to register
1350 +the EAP mechanisms. A sample configuration file is in this directory.
1351 +You may need to specify an absolute path.
1353 +RADIUS client library
1354 +---------------------
1356 +Make sure your RADIUS library is configured to talk to the server of
1357 +your choice: see the example radsec.conf in this directory. If you
1358 +want to use TCP or TLS, you'll need to run radsecproxy in front of
1359 +your RADIUS server.
1364 +These instructions apply to FreeRADIUS only, which is downloadable
1365 +from http://freeradius.org/. After configure, make, install, do the
1368 +On the RADIUS server side, you need to install dictionary.ukerna to
1369 +$prefix/etc/raddb and include it from the main dictionary file, by
1372 + $INCLUDE dictionary.ukerna
1374 +to $prefix/etc/raddb/dictionary. Make sure these files are world-
1375 +readable; they weren't in my installation.
1377 +Edit $prefix/etc/raddb/users to add your test user and password:
1379 + bob@PROJECT-MOONSHOT.ORG Cleartext-Password := secret
1381 +Add an entry for your acceptor to $prefix/etc/raddb/clients.conf:
1384 + ipaddr = 127.0.0.1
1385 + secret = testing123
1386 + require_message_authenticator = yes
1389 +Edit $prefix/etc/raddb/eap.conf and set:
1393 + default_eap_type = ttls
1398 + private_key_file = ...
1399 + certificate_file = ...
1402 + default_eap_type = mschapv2
1403 + copy_request_to_tunnel = no
1404 + use_tunneled_reply = no
1405 + virtual_server = "inner-tunnel"
1410 +to enable EAP-TTLS.
1412 +If you want the acceptor be able to identify the user, the RADIUS
1413 +server needs to echo back the EAP username from the inner tunnel;
1414 +for privacy, mech_eap only sends the realm in the EAP Identity
1415 +response. To configure this with FreeRADIUS, add:
1417 + update outer.reply {
1418 + User-Name = "%{request:User-Name}"
1421 +If you want to add a SAML assertion, do this with "update reply"
1422 +in $prefix/etc/raddb/sites-available/default:
1425 + SAML-AAA-Assertion = '<saml:Assertion ...'
1426 + SAML-AAA-Assertion += '...'
1429 +You'll need to split it into multiple lines because of the RADIUS
1430 +attribute size limit.
1435 +You can then test the MIT or Cyrus GSS and SASL example programs.
1436 +Sample usage is given below. Substitute <user>, <pass> and <host>
1437 +appropriately (<host> is the name of the host running the server,
1438 +not the RADIUS server).
1440 +% gss-client -port 5555 -spnego -mech "{1 3 6 1 4 1 5322 22 1 18}" \
1441 + -user <user>@<realm> -pass <pass> <host> host@<host> \
1443 +% gss-server -port 5555 -export host@<host>
1445 +Note: for SASL you will be prompted for a username and password.
1447 +% client -C -p 5556 -s host -m EAP-AES128 <host>
1448 +% server -c -p 5556 -s host -h <host>
1450 +To test fast reauthentication support, add the following to
1455 + reauth_use_ccache = TRUE
1458 +This will store a Kerberos ticket for a GSS-EAP authenticated user
1459 +in a credentials cache, which can then be used for re-authentication
1460 +to the same acceptor. You must have a valid keytab configured.
1462 +In this testing phase of Moonshot, it's also possible to store a
1463 +default identity and credential in a file. The format consists of
1464 +the string representation of the initiator identity and the password,
1465 +separated by newlines. The default location of this file is
1466 +.gss_eap_id in the user's home directory, however the GSSEAP_IDENTITY
1467 +environment variable can be used to set an alternate location.
1469 +You can also set a default realm in [appdefaults]; the Kerberos
1470 +default realm is never used by mech_eap (or at least, that is the
1471 +intention), so if unspecified you must always qualify names. It should
1472 +generally not be necessary to specify this.
1474 diff --git a/mech_eap/README.samba4 b/mech_eap/README.samba4
1475 new file mode 100644
1476 index 0000000..d0a94d1
1478 +++ b/mech_eap/README.samba4
1480 +Notes on using Moonshot with Samba4. Replace paths as appropriate.
1485 +* Download Samba4 and apply patches for mechanism agnosticism which are
1486 + available at http://www.padl.com/~lukeh/samba/
1487 +* Join Samba as a member server or domain controller (only tested former)
1488 +* Extract local service principal key to keytab (currently there do not
1489 + appear to be tools to do this, but you can get the cleartext password
1490 + from /usr/local/samba/private/secrets.ldb)
1495 +* Add a mapping from the PAC RADIUS attribute to urn:mspac: in the file
1496 + /usr/local/etc/shibboleth/attribute-map.xml:
1498 + <GSSAPIAttribute name="urn:ietf:params:gss-eap:radius-avp urn:x-radius:1679163525"
1499 + id="urn:mspac:" binary="true"/>
1504 +Install the rlm_mspac module and configure per below.
1506 +* Install dictionary.ukerna so MS-Windows-Auth-Data is defined
1507 +* Create /usr/local/etc/raddb/modules/mspac with the following:
1510 + keytab = /etc/krb5.keytab
1511 + spn = host/host.fqdn@KERBEROS.REALM
1514 +* Add mspac to instantiate stanza in radiusd.conf
1515 +* Add mspac to post-auth stanza in sites-enabled/inner-tunnel
1517 +You will need to have a TGT for the host service principal before starting
1518 +radiusd. It's easiest to do this with kinit -k.
1523 +The Samba server doesn't require any specific command line arguments, although
1524 +on OS X it was necessary to start it with -M single to function under gdb.
1526 +For the client, the GSS EAP mechanism can be specified on the command line:
1528 +smbclient --password samba --mechanism 1.3.6.1.4.1.5322.22.1.18 '\\host\share'".
1530 +There is no Moonshot SSPI implementation as yet, so it is not possible to test
1531 +with a Windows client.
1532 diff --git a/mech_eap/TODO b/mech_eap/TODO
1533 new file mode 100644
1534 index 0000000..0111459
1538 +- integration with initiator-side EAP channel bindings
1539 +- investigate initiator-side credential locking
1540 +- always intern OIDs so they never need to be freed
1541 +- handle many-to-many Shibboleth attribute mappings; need to encode both attribute and value index into more
1542 +- add --with-xerces option
1543 +- proper acquire_cred_ext implementation pending specification
1544 diff --git a/mech_eap/accept_sec_context.c b/mech_eap/accept_sec_context.c
1545 new file mode 100644
1546 index 0000000..b089bae
1548 +++ b/mech_eap/accept_sec_context.c
1551 + * Copyright (c) 2011, JANET(UK)
1552 + * All rights reserved.
1554 + * Redistribution and use in source and binary forms, with or without
1555 + * modification, are permitted provided that the following conditions
1558 + * 1. Redistributions of source code must retain the above copyright
1559 + * notice, this list of conditions and the following disclaimer.
1561 + * 2. Redistributions in binary form must reproduce the above copyright
1562 + * notice, this list of conditions and the following disclaimer in the
1563 + * documentation and/or other materials provided with the distribution.
1565 + * 3. Neither the name of JANET(UK) nor the names of its contributors
1566 + * may be used to endorse or promote products derived from this software
1567 + * without specific prior written permission.
1569 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1570 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1571 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1572 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
1573 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1574 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1575 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1576 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1577 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1578 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1583 + * Establish a security context on the acceptor (server). These functions
1584 + * wrap around libradsec and (thus) talk to a RADIUS server or proxy.
1587 +#include "gssapiP_eap.h"
1589 +#ifdef GSSEAP_ENABLE_REAUTH
1591 +eapGssSmAcceptGssReauth(OM_uint32 *minor,
1592 + gss_cred_id_t cred,
1594 + gss_name_t target,
1596 + OM_uint32 reqFlags,
1597 + OM_uint32 timeReq,
1598 + gss_channel_bindings_t chanBindings,
1599 + gss_buffer_t inputToken,
1600 + gss_buffer_t outputToken,
1601 + OM_uint32 *smFlags);
1605 + * Mark an acceptor context as ready for cryptographic operations
1608 +acceptReadyEap(OM_uint32 *minor, gss_ctx_id_t ctx, gss_cred_id_t cred)
1610 + OM_uint32 major, tmpMinor;
1612 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
1614 + /* Cache encryption type derived from selected mechanism OID */
1615 + major = gssEapOidToEnctype(minor, ctx->mechanismUsed,
1616 + &ctx->encryptionType);
1617 + if (GSS_ERROR(major))
1620 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
1622 + major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps,
1623 + PW_USER_NAME, 0, &vp);
1624 + if (major == GSS_S_COMPLETE && vp->length) {
1625 + nameBuf.length = vp->length;
1626 + nameBuf.value = vp->vp_strvalue;
1628 + ctx->gssFlags |= GSS_C_ANON_FLAG;
1631 + major = gssEapImportName(minor, &nameBuf,
1632 + (ctx->gssFlags & GSS_C_ANON_FLAG) ?
1633 + GSS_C_NT_ANONYMOUS : GSS_C_NT_USER_NAME,
1634 + ctx->mechanismUsed,
1635 + &ctx->initiatorName);
1636 + if (GSS_ERROR(major))
1639 + major = gssEapRadiusGetRawAvp(minor, ctx->acceptorCtx.vps,
1640 + PW_MS_MPPE_SEND_KEY, VENDORPEC_MS, &vp);
1641 + if (GSS_ERROR(major)) {
1642 + *minor = GSSEAP_KEY_UNAVAILABLE;
1643 + return GSS_S_UNAVAILABLE;
1646 + major = gssEapDeriveRfc3961Key(minor,
1649 + ctx->encryptionType,
1650 + &ctx->rfc3961Key);
1651 + if (GSS_ERROR(major))
1654 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
1655 + &ctx->checksumType);
1656 + if (GSS_ERROR(major))
1659 + major = sequenceInit(minor,
1660 + &ctx->seqState, ctx->recvSeq,
1661 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
1662 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
1664 + if (GSS_ERROR(major))
1667 + major = gssEapCreateAttrContext(minor, cred, ctx,
1668 + &ctx->initiatorName->attrCtx,
1669 + &ctx->expiryTime);
1670 + if (GSS_ERROR(major))
1673 + if (ctx->expiryTime != 0 && ctx->expiryTime < time(NULL)) {
1674 + *minor = GSSEAP_CRED_EXPIRED;
1675 + return GSS_S_CREDENTIALS_EXPIRED;
1679 + return GSS_S_COMPLETE;
1683 +eapGssSmAcceptAcceptorName(OM_uint32 *minor,
1684 + gss_cred_id_t cred GSSEAP_UNUSED,
1686 + gss_name_t target GSSEAP_UNUSED,
1687 + gss_OID mech GSSEAP_UNUSED,
1688 + OM_uint32 reqFlags GSSEAP_UNUSED,
1689 + OM_uint32 timeReq GSSEAP_UNUSED,
1690 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1691 + gss_buffer_t inputToken GSSEAP_UNUSED,
1692 + gss_buffer_t outputToken,
1693 + OM_uint32 *smFlags GSSEAP_UNUSED)
1697 + /* XXX TODO import and validate name from inputToken */
1699 + if (ctx->acceptorName != GSS_C_NO_NAME) {
1700 + /* Send desired target name to acceptor */
1701 + major = gssEapDisplayName(minor, ctx->acceptorName,
1702 + outputToken, NULL);
1703 + if (GSS_ERROR(major))
1707 + return GSS_S_CONTINUE_NEEDED;
1710 +#ifdef GSSEAP_DEBUG
1712 +eapGssSmAcceptVendorInfo(OM_uint32 *minor,
1713 + gss_cred_id_t cred GSSEAP_UNUSED,
1714 + gss_ctx_id_t ctx GSSEAP_UNUSED,
1715 + gss_name_t target GSSEAP_UNUSED,
1716 + gss_OID mech GSSEAP_UNUSED,
1717 + OM_uint32 reqFlags GSSEAP_UNUSED,
1718 + OM_uint32 timeReq GSSEAP_UNUSED,
1719 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1720 + gss_buffer_t inputToken,
1721 + gss_buffer_t outputToken GSSEAP_UNUSED,
1722 + OM_uint32 *smFlags GSSEAP_UNUSED)
1724 + fprintf(stderr, "GSS-EAP: vendor: %.*s\n",
1725 + (int)inputToken->length, (char *)inputToken->value);
1728 + return GSS_S_CONTINUE_NEEDED;
1734 + * Emit a identity EAP request to force the initiator (peer) to identify
1738 +eapGssSmAcceptIdentity(OM_uint32 *minor,
1739 + gss_cred_id_t cred,
1741 + gss_name_t target GSSEAP_UNUSED,
1742 + gss_OID mech GSSEAP_UNUSED,
1743 + OM_uint32 reqFlags GSSEAP_UNUSED,
1744 + OM_uint32 timeReq GSSEAP_UNUSED,
1745 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
1746 + gss_buffer_t inputToken,
1747 + gss_buffer_t outputToken,
1748 + OM_uint32 *smFlags)
1751 + struct wpabuf *reqData;
1752 + gss_buffer_desc pktBuffer;
1754 + if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
1755 + *minor = GSSEAP_CRED_MECH_MISMATCH;
1756 + return GSS_S_BAD_MECH;
1759 + if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
1760 + *minor = GSSEAP_WRONG_SIZE;
1761 + return GSS_S_DEFECTIVE_TOKEN;
1764 + reqData = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, 0,
1765 + EAP_CODE_REQUEST, 0);
1766 + if (reqData == NULL) {
1768 + return GSS_S_FAILURE;
1771 + pktBuffer.length = wpabuf_len(reqData);
1772 + pktBuffer.value = (void *)wpabuf_head(reqData);
1774 + major = duplicateBuffer(minor, &pktBuffer, outputToken);
1775 + if (GSS_ERROR(major))
1778 + wpabuf_free(reqData);
1780 + GSSEAP_SM_TRANSITION_NEXT(ctx);
1783 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
1785 + return GSS_S_CONTINUE_NEEDED;
1789 + * Returns TRUE if the input token contains an EAP identity response.
1792 +isIdentityResponseP(gss_buffer_t inputToken)
1794 + struct wpabuf respData;
1796 + wpabuf_set(&respData, inputToken->value, inputToken->length);
1798 + return (eap_get_type(&respData) == EAP_TYPE_IDENTITY);
1802 + * Save the asserted initiator identity from the EAP identity response.
1805 +importInitiatorIdentity(OM_uint32 *minor,
1807 + gss_buffer_t inputToken)
1809 + OM_uint32 tmpMinor;
1810 + struct wpabuf respData;
1811 + const unsigned char *pos;
1813 + gss_buffer_desc nameBuf;
1815 + wpabuf_set(&respData, inputToken->value, inputToken->length);
1817 + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
1819 + if (pos == NULL) {
1820 + *minor = GSSEAP_PEER_BAD_MESSAGE;
1821 + return GSS_S_DEFECTIVE_TOKEN;
1824 + nameBuf.value = (void *)pos;
1825 + nameBuf.length = len;
1827 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
1829 + return gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
1830 + ctx->mechanismUsed, &ctx->initiatorName);
1834 + * Pass the asserted initiator identity to the authentication server.
1837 +setInitiatorIdentity(OM_uint32 *minor,
1841 + OM_uint32 major, tmpMinor;
1842 + gss_buffer_desc nameBuf;
1845 + * We should have got an EAP identity response, but if we didn't, then
1846 + * we will just avoid sending User-Name. Note that radsecproxy requires
1847 + * User-Name to be sent on every request (presumably so it can remain
1850 + if (ctx->initiatorName != GSS_C_NO_NAME) {
1851 + major = gssEapDisplayName(minor, ctx->initiatorName, &nameBuf, NULL);
1852 + if (GSS_ERROR(major))
1855 + major = gssEapRadiusAddAvp(minor, vps, PW_USER_NAME, 0, &nameBuf);
1856 + if (GSS_ERROR(major))
1859 + gss_release_buffer(&tmpMinor, &nameBuf);
1863 + return GSS_S_COMPLETE;
1867 + * Pass the asserted acceptor identity to the authentication server.
1870 +setAcceptorIdentity(OM_uint32 *minor,
1875 + gss_buffer_desc nameBuf;
1876 + krb5_context krbContext = NULL;
1877 + krb5_principal krbPrinc;
1878 + struct rs_context *rc = ctx->acceptorCtx.radContext;
1880 + GSSEAP_ASSERT(rc != NULL);
1882 + if (ctx->acceptorName == GSS_C_NO_NAME) {
1884 + return GSS_S_COMPLETE;
1887 + if ((ctx->acceptorName->flags & NAME_FLAG_SERVICE) == 0) {
1888 + *minor = GSSEAP_BAD_SERVICE_NAME;
1889 + return GSS_S_BAD_NAME;
1892 + GSSEAP_KRB_INIT(&krbContext);
1894 + krbPrinc = ctx->acceptorName->krbPrincipal;
1895 + GSSEAP_ASSERT(krbPrinc != NULL);
1896 + GSSEAP_ASSERT(KRB_PRINC_LENGTH(krbPrinc) >= 2);
1898 + /* Acceptor-Service-Name */
1899 + krbPrincComponentToGssBuffer(krbPrinc, 0, &nameBuf);
1901 + major = gssEapRadiusAddAvp(minor, vps,
1902 + PW_GSS_ACCEPTOR_SERVICE_NAME,
1905 + if (GSS_ERROR(major))
1908 + /* Acceptor-Host-Name */
1909 + krbPrincComponentToGssBuffer(krbPrinc, 1, &nameBuf);
1911 + major = gssEapRadiusAddAvp(minor, vps,
1912 + PW_GSS_ACCEPTOR_HOST_NAME,
1915 + if (GSS_ERROR(major))
1918 + if (KRB_PRINC_LENGTH(krbPrinc) > 2) {
1919 + /* Acceptor-Service-Specific */
1920 + krb5_principal_data ssiPrinc = *krbPrinc;
1923 + KRB_PRINC_LENGTH(&ssiPrinc) -= 2;
1924 + KRB_PRINC_NAME(&ssiPrinc) += 2;
1926 + *minor = krb5_unparse_name_flags(krbContext, &ssiPrinc,
1927 + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &ssi);
1929 + return GSS_S_FAILURE;
1931 + nameBuf.value = ssi;
1932 + nameBuf.length = strlen(ssi);
1934 + major = gssEapRadiusAddAvp(minor, vps,
1935 + PW_GSS_ACCEPTOR_SERVICE_SPECIFIC,
1939 + if (GSS_ERROR(major)) {
1940 + krb5_free_unparsed_name(krbContext, ssi);
1943 + krb5_free_unparsed_name(krbContext, ssi);
1946 + krbPrincRealmToGssBuffer(krbPrinc, &nameBuf);
1947 + if (nameBuf.length != 0) {
1948 + /* Acceptor-Realm-Name */
1949 + major = gssEapRadiusAddAvp(minor, vps,
1950 + PW_GSS_ACCEPTOR_REALM_NAME,
1953 + if (GSS_ERROR(major))
1958 + return GSS_S_COMPLETE;
1962 + * Allocate a RadSec handle
1965 +createRadiusHandle(OM_uint32 *minor,
1966 + gss_cred_id_t cred,
1969 + struct gss_eap_acceptor_ctx *actx = &ctx->acceptorCtx;
1970 + struct rs_error *err;
1971 + const char *configStanza = "gss-eap";
1974 + GSSEAP_ASSERT(actx->radContext == NULL);
1975 + GSSEAP_ASSERT(actx->radConn == NULL);
1976 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
1978 + major = gssEapCreateRadiusContext(minor, cred, &actx->radContext);
1979 + if (GSS_ERROR(major))
1982 + if (cred->radiusConfigStanza.value != NULL)
1983 + configStanza = (const char *)cred->radiusConfigStanza.value;
1985 + if (rs_conn_create(actx->radContext, &actx->radConn, configStanza) != 0) {
1986 + err = rs_err_conn_pop(actx->radConn);
1987 + return gssEapRadiusMapError(minor, err);
1990 + if (actx->radServer != NULL) {
1991 + if (rs_conn_select_peer(actx->radConn, actx->radServer) != 0) {
1992 + err = rs_err_conn_pop(actx->radConn);
1993 + return gssEapRadiusMapError(minor, err);
1998 + return GSS_S_COMPLETE;
2002 + * Process a EAP response from the initiator.
2005 +eapGssSmAcceptAuthenticate(OM_uint32 *minor,
2006 + gss_cred_id_t cred,
2008 + gss_name_t target GSSEAP_UNUSED,
2009 + gss_OID mech GSSEAP_UNUSED,
2010 + OM_uint32 reqFlags GSSEAP_UNUSED,
2011 + OM_uint32 timeReq GSSEAP_UNUSED,
2012 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2013 + gss_buffer_t inputToken,
2014 + gss_buffer_t outputToken,
2015 + OM_uint32 *smFlags)
2017 + OM_uint32 major, tmpMinor;
2018 + struct rs_connection *rconn;
2019 + struct rs_request *request = NULL;
2020 + struct rs_packet *req = NULL, *resp = NULL;
2021 + struct radius_packet *frreq, *frresp;
2023 + if (ctx->acceptorCtx.radContext == NULL) {
2024 + /* May be NULL from an imported partial context */
2025 + major = createRadiusHandle(minor, cred, ctx);
2026 + if (GSS_ERROR(major))
2030 + if (isIdentityResponseP(inputToken)) {
2031 + major = importInitiatorIdentity(minor, ctx, inputToken);
2032 + if (GSS_ERROR(major))
2036 + rconn = ctx->acceptorCtx.radConn;
2038 + if (rs_packet_create_authn_request(rconn, &req, NULL, NULL) != 0) {
2039 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2042 + frreq = rs_packet_frpkt(req);
2044 + major = setInitiatorIdentity(minor, ctx, &frreq->vps);
2045 + if (GSS_ERROR(major))
2048 + major = setAcceptorIdentity(minor, ctx, &frreq->vps);
2049 + if (GSS_ERROR(major))
2052 + major = gssEapRadiusAddAvp(minor, &frreq->vps,
2053 + PW_EAP_MESSAGE, 0, inputToken);
2054 + if (GSS_ERROR(major))
2057 + if (ctx->acceptorCtx.state.length != 0) {
2058 + major = gssEapRadiusAddAvp(minor, &frreq->vps, PW_STATE, 0,
2059 + &ctx->acceptorCtx.state);
2060 + if (GSS_ERROR(major))
2063 + gss_release_buffer(&tmpMinor, &ctx->acceptorCtx.state);
2066 + if (rs_request_create(rconn, &request) != 0) {
2067 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2071 + rs_request_add_reqpkt(request, req);
2074 + if (rs_request_send(request, &resp) != 0) {
2075 + major = gssEapRadiusMapError(minor, rs_err_conn_pop(rconn));
2079 + GSSEAP_ASSERT(resp != NULL);
2081 + frresp = rs_packet_frpkt(resp);
2082 + switch (frresp->code) {
2083 + case PW_ACCESS_CHALLENGE:
2084 + case PW_AUTHENTICATION_ACK:
2086 + case PW_AUTHENTICATION_REJECT:
2087 + *minor = GSSEAP_RADIUS_AUTH_FAILURE;
2088 + major = GSS_S_DEFECTIVE_CREDENTIAL;
2092 + *minor = GSSEAP_UNKNOWN_RADIUS_CODE;
2093 + major = GSS_S_FAILURE;
2098 + major = gssEapRadiusGetAvp(minor, frresp->vps, PW_EAP_MESSAGE, 0,
2099 + outputToken, TRUE);
2100 + if (major == GSS_S_UNAVAILABLE && frresp->code == PW_ACCESS_CHALLENGE) {
2101 + *minor = GSSEAP_MISSING_EAP_REQUEST;
2102 + major = GSS_S_DEFECTIVE_TOKEN;
2104 + } else if (GSS_ERROR(major))
2107 + if (frresp->code == PW_ACCESS_CHALLENGE) {
2108 + major = gssEapRadiusGetAvp(minor, frresp->vps, PW_STATE, 0,
2109 + &ctx->acceptorCtx.state, TRUE);
2110 + if (GSS_ERROR(major) && *minor != GSSEAP_NO_SUCH_ATTR)
2113 + ctx->acceptorCtx.vps = frresp->vps;
2114 + frresp->vps = NULL;
2116 + major = acceptReadyEap(minor, ctx, cred);
2117 + if (GSS_ERROR(major))
2120 + GSSEAP_SM_TRANSITION_NEXT(ctx);
2123 + major = GSS_S_CONTINUE_NEEDED;
2125 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
2128 + if (request != NULL)
2129 + rs_request_destroy(request);
2131 + rs_packet_destroy(req);
2133 + rs_packet_destroy(resp);
2134 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIATOR_EXTS) {
2135 + GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
2137 + rs_conn_destroy(ctx->acceptorCtx.radConn);
2138 + ctx->acceptorCtx.radConn = NULL;
2145 +eapGssSmAcceptGssFlags(OM_uint32 *minor,
2146 + gss_cred_id_t cred GSSEAP_UNUSED,
2148 + gss_name_t target GSSEAP_UNUSED,
2149 + gss_OID mech GSSEAP_UNUSED,
2150 + OM_uint32 reqFlags GSSEAP_UNUSED,
2151 + OM_uint32 timeReq GSSEAP_UNUSED,
2152 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2153 + gss_buffer_t inputToken,
2154 + gss_buffer_t outputToken GSSEAP_UNUSED,
2155 + OM_uint32 *smFlags GSSEAP_UNUSED)
2158 + OM_uint32 initiatorGssFlags;
2160 + GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
2162 + if (inputToken->length < 4) {
2163 + *minor = GSSEAP_TOK_TRUNC;
2164 + return GSS_S_DEFECTIVE_TOKEN;
2167 + /* allow flags to grow for future expansion */
2168 + p = (unsigned char *)inputToken->value + inputToken->length - 4;
2170 + initiatorGssFlags = load_uint32_be(p);
2171 + initiatorGssFlags &= GSSEAP_WIRE_FLAGS_MASK;
2173 + ctx->gssFlags |= initiatorGssFlags;
2175 + return GSS_S_CONTINUE_NEEDED;
2179 +eapGssSmAcceptGssChannelBindings(OM_uint32 *minor,
2180 + gss_cred_id_t cred GSSEAP_UNUSED,
2182 + gss_name_t target GSSEAP_UNUSED,
2183 + gss_OID mech GSSEAP_UNUSED,
2184 + OM_uint32 reqFlags GSSEAP_UNUSED,
2185 + OM_uint32 timeReq GSSEAP_UNUSED,
2186 + gss_channel_bindings_t chanBindings,
2187 + gss_buffer_t inputToken,
2188 + gss_buffer_t outputToken GSSEAP_UNUSED,
2189 + OM_uint32 *smFlags GSSEAP_UNUSED)
2192 + gss_iov_buffer_desc iov[2];
2194 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
2195 + iov[0].buffer.length = 0;
2196 + iov[0].buffer.value = NULL;
2198 + iov[1].type = GSS_IOV_BUFFER_TYPE_STREAM | GSS_IOV_BUFFER_FLAG_ALLOCATED;
2200 + /* XXX necessary because decrypted in place and we verify it later */
2201 + major = duplicateBuffer(minor, inputToken, &iov[1].buffer);
2202 + if (GSS_ERROR(major))
2205 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
2206 + iov, 2, TOK_TYPE_WRAP);
2207 + if (GSS_ERROR(major)) {
2208 + gssEapReleaseIov(iov, 2);
2212 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS &&
2213 + !bufferEqual(&iov[0].buffer, &chanBindings->application_data)) {
2214 + major = GSS_S_BAD_BINDINGS;
2215 + *minor = GSSEAP_BINDINGS_MISMATCH;
2217 + major = GSS_S_CONTINUE_NEEDED;
2221 + gssEapReleaseIov(iov, 2);
2227 +eapGssSmAcceptInitiatorMIC(OM_uint32 *minor,
2228 + gss_cred_id_t cred GSSEAP_UNUSED,
2230 + gss_name_t target GSSEAP_UNUSED,
2231 + gss_OID mech GSSEAP_UNUSED,
2232 + OM_uint32 reqFlags GSSEAP_UNUSED,
2233 + OM_uint32 timeReq GSSEAP_UNUSED,
2234 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2235 + gss_buffer_t inputToken,
2236 + gss_buffer_t outputToken GSSEAP_UNUSED,
2237 + OM_uint32 *smFlags GSSEAP_UNUSED)
2241 + major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
2242 + if (GSS_ERROR(major))
2245 + GSSEAP_SM_TRANSITION_NEXT(ctx);
2248 + return GSS_S_CONTINUE_NEEDED;
2251 +#ifdef GSSEAP_ENABLE_REAUTH
2253 +eapGssSmAcceptReauthCreds(OM_uint32 *minor,
2254 + gss_cred_id_t cred,
2256 + gss_name_t target GSSEAP_UNUSED,
2257 + gss_OID mech GSSEAP_UNUSED,
2258 + OM_uint32 reqFlags GSSEAP_UNUSED,
2259 + OM_uint32 timeReq GSSEAP_UNUSED,
2260 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2261 + gss_buffer_t inputToken GSSEAP_UNUSED,
2262 + gss_buffer_t outputToken,
2263 + OM_uint32 *smFlags GSSEAP_UNUSED)
2268 + * If we're built with fast reauthentication enabled, then
2269 + * fabricate a ticket from the initiator to ourselves.
2271 + major = gssEapMakeReauthCreds(minor, ctx, cred, outputToken);
2272 + if (major == GSS_S_UNAVAILABLE)
2273 + major = GSS_S_COMPLETE;
2274 + if (major == GSS_S_COMPLETE)
2275 + major = GSS_S_CONTINUE_NEEDED;
2282 +eapGssSmAcceptAcceptorMIC(OM_uint32 *minor,
2283 + gss_cred_id_t cred GSSEAP_UNUSED,
2285 + gss_name_t target GSSEAP_UNUSED,
2286 + gss_OID mech GSSEAP_UNUSED,
2287 + OM_uint32 reqFlags GSSEAP_UNUSED,
2288 + OM_uint32 timeReq GSSEAP_UNUSED,
2289 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
2290 + gss_buffer_t inputToken GSSEAP_UNUSED,
2291 + gss_buffer_t outputToken,
2292 + OM_uint32 *smFlags)
2296 + major = gssEapMakeTokenMIC(minor, ctx, outputToken);
2297 + if (GSS_ERROR(major))
2300 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
2303 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
2305 + return GSS_S_COMPLETE;
2308 +static struct gss_eap_sm eapGssAcceptorSm[] = {
2310 + ITOK_TYPE_ACCEPTOR_NAME_REQ,
2311 + ITOK_TYPE_ACCEPTOR_NAME_RESP,
2312 + GSSEAP_STATE_INITIAL,
2314 + eapGssSmAcceptAcceptorName
2316 +#ifdef GSSEAP_DEBUG
2318 + ITOK_TYPE_VENDOR_INFO,
2320 + GSSEAP_STATE_INITIAL,
2322 + eapGssSmAcceptVendorInfo,
2325 +#ifdef GSSEAP_ENABLE_REAUTH
2327 + ITOK_TYPE_REAUTH_REQ,
2328 + ITOK_TYPE_REAUTH_RESP,
2329 + GSSEAP_STATE_INITIAL,
2331 + eapGssSmAcceptGssReauth,
2336 + ITOK_TYPE_EAP_REQ,
2337 + GSSEAP_STATE_INITIAL,
2338 + SM_ITOK_FLAG_REQUIRED,
2339 + eapGssSmAcceptIdentity,
2342 + ITOK_TYPE_EAP_RESP,
2343 + ITOK_TYPE_EAP_REQ,
2344 + GSSEAP_STATE_AUTHENTICATE,
2345 + SM_ITOK_FLAG_REQUIRED,
2346 + eapGssSmAcceptAuthenticate
2349 + ITOK_TYPE_GSS_FLAGS,
2351 + GSSEAP_STATE_INITIATOR_EXTS,
2353 + eapGssSmAcceptGssFlags
2356 + ITOK_TYPE_GSS_CHANNEL_BINDINGS,
2358 + GSSEAP_STATE_INITIATOR_EXTS,
2359 + SM_ITOK_FLAG_REQUIRED,
2360 + eapGssSmAcceptGssChannelBindings,
2363 + ITOK_TYPE_INITIATOR_MIC,
2365 + GSSEAP_STATE_INITIATOR_EXTS,
2366 + SM_ITOK_FLAG_REQUIRED,
2367 + eapGssSmAcceptInitiatorMIC,
2369 +#ifdef GSSEAP_ENABLE_REAUTH
2372 + ITOK_TYPE_REAUTH_CREDS,
2373 + GSSEAP_STATE_ACCEPTOR_EXTS,
2375 + eapGssSmAcceptReauthCreds,
2380 + ITOK_TYPE_ACCEPTOR_MIC,
2381 + GSSEAP_STATE_ACCEPTOR_EXTS,
2383 + eapGssSmAcceptAcceptorMIC
2388 +gssEapAcceptSecContext(OM_uint32 *minor,
2390 + gss_cred_id_t cred,
2391 + gss_buffer_t input_token,
2392 + gss_channel_bindings_t input_chan_bindings,
2393 + gss_name_t *src_name,
2394 + gss_OID *mech_type,
2395 + gss_buffer_t output_token,
2396 + OM_uint32 *ret_flags,
2397 + OM_uint32 *time_rec,
2398 + gss_cred_id_t *delegated_cred_handle)
2400 + OM_uint32 major, tmpMinor;
2402 + if (cred == GSS_C_NO_CREDENTIAL) {
2403 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
2404 + major = gssEapAcquireCred(minor,
2412 + if (GSS_ERROR(major))
2420 + * Previously we acquired the credential mutex here, but it should not be
2421 + * necessary as the acceptor does not access any mutable elements of the
2422 + * credential handle.
2426 + * Calling gssEapInquireCred() forces the default acceptor credential name
2429 + major = gssEapInquireCred(minor, cred, &ctx->acceptorName, NULL, NULL, NULL);
2430 + if (GSS_ERROR(major))
2433 + major = gssEapSmStep(minor,
2440 + input_chan_bindings,
2444 + sizeof(eapGssAcceptorSm) / sizeof(eapGssAcceptorSm[0]));
2445 + if (GSS_ERROR(major))
2448 + if (mech_type != NULL) {
2449 + OM_uint32 tmpMajor;
2451 + tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, mech_type);
2452 + if (GSS_ERROR(tmpMajor)) {
2454 + *minor = tmpMinor;
2458 + if (ret_flags != NULL)
2459 + *ret_flags = ctx->gssFlags;
2460 + if (delegated_cred_handle != NULL)
2461 + *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
2463 + if (major == GSS_S_COMPLETE) {
2464 + if (src_name != NULL && ctx->initiatorName != GSS_C_NO_NAME) {
2465 + major = gssEapDuplicateName(&tmpMinor, ctx->initiatorName, src_name);
2466 + if (GSS_ERROR(major))
2469 + if (time_rec != NULL) {
2470 + major = gssEapContextTime(&tmpMinor, ctx, time_rec);
2471 + if (GSS_ERROR(major))
2476 + GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
2482 +#ifdef GSSEAP_ENABLE_REAUTH
2484 +acceptReadyKrb(OM_uint32 *minor,
2486 + gss_cred_id_t cred,
2487 + const gss_name_t initiator,
2488 + const gss_OID mech,
2489 + OM_uint32 timeRec)
2493 + major = gssEapGlueToMechName(minor, ctx, initiator, &ctx->initiatorName);
2494 + if (GSS_ERROR(major))
2497 + major = gssEapReauthComplete(minor, ctx, cred, mech, timeRec);
2498 + if (GSS_ERROR(major))
2502 + return GSS_S_COMPLETE;
2506 +eapGssSmAcceptGssReauth(OM_uint32 *minor,
2507 + gss_cred_id_t cred,
2509 + gss_name_t target GSSEAP_UNUSED,
2511 + OM_uint32 reqFlags GSSEAP_UNUSED,
2512 + OM_uint32 timeReq GSSEAP_UNUSED,
2513 + gss_channel_bindings_t chanBindings,
2514 + gss_buffer_t inputToken,
2515 + gss_buffer_t outputToken,
2516 + OM_uint32 *smFlags)
2518 + OM_uint32 major, tmpMinor;
2519 + gss_name_t krbInitiator = GSS_C_NO_NAME;
2520 + OM_uint32 gssFlags, timeRec = GSS_C_INDEFINITE;
2523 + * If we're built with fast reauthentication support, it's valid
2524 + * for an initiator to send a GSS reauthentication token as its
2525 + * initial context token, causing us to short-circuit the state
2526 + * machine and process Kerberos GSS messages instead.
2529 + ctx->flags |= CTX_FLAG_KRB_REAUTH;
2531 + major = gssAcceptSecContext(minor,
2542 + if (major == GSS_S_COMPLETE) {
2543 + major = acceptReadyKrb(minor, ctx, cred,
2544 + krbInitiator, mech, timeRec);
2545 + if (major == GSS_S_COMPLETE) {
2546 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
2548 + ctx->gssFlags = gssFlags;
2549 + } else if (GSS_ERROR(major) &&
2550 + (*smFlags & SM_FLAG_INPUT_TOKEN_CRITICAL) == 0) {
2551 + /* pretend reauthentication attempt never happened */
2552 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
2553 + ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
2554 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
2555 + major = GSS_S_CONTINUE_NEEDED;
2558 + gssReleaseName(&tmpMinor, &krbInitiator);
2562 +#endif /* GSSEAP_ENABLE_REAUTH */
2564 +OM_uint32 GSSAPI_CALLCONV
2565 +gss_accept_sec_context(OM_uint32 *minor,
2566 + gss_ctx_id_t *context_handle,
2567 + gss_cred_id_t cred,
2568 + gss_buffer_t input_token,
2569 + gss_channel_bindings_t input_chan_bindings,
2570 + gss_name_t *src_name,
2571 + gss_OID *mech_type,
2572 + gss_buffer_t output_token,
2573 + OM_uint32 *ret_flags,
2574 + OM_uint32 *time_rec,
2575 + gss_cred_id_t *delegated_cred_handle)
2577 + OM_uint32 major, tmpMinor;
2578 + gss_ctx_id_t ctx = *context_handle;
2582 + output_token->length = 0;
2583 + output_token->value = NULL;
2585 + if (src_name != NULL)
2586 + *src_name = GSS_C_NO_NAME;
2588 + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
2589 + *minor = GSSEAP_TOK_TRUNC;
2590 + return GSS_S_DEFECTIVE_TOKEN;
2593 + if (ctx == GSS_C_NO_CONTEXT) {
2594 + major = gssEapAllocContext(minor, &ctx);
2595 + if (GSS_ERROR(major))
2598 + *context_handle = ctx;
2601 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
2603 + major = gssEapAcceptSecContext(minor,
2607 + input_chan_bindings,
2613 + delegated_cred_handle);
2615 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
2617 + if (GSS_ERROR(major))
2618 + gssEapReleaseContext(&tmpMinor, context_handle);
2622 diff --git a/mech_eap/acquire_cred.c b/mech_eap/acquire_cred.c
2623 new file mode 100644
2624 index 0000000..ae2648e
2626 +++ b/mech_eap/acquire_cred.c
2629 + * Copyright (c) 2011, JANET(UK)
2630 + * All rights reserved.
2632 + * Redistribution and use in source and binary forms, with or without
2633 + * modification, are permitted provided that the following conditions
2636 + * 1. Redistributions of source code must retain the above copyright
2637 + * notice, this list of conditions and the following disclaimer.
2639 + * 2. Redistributions in binary form must reproduce the above copyright
2640 + * notice, this list of conditions and the following disclaimer in the
2641 + * documentation and/or other materials provided with the distribution.
2643 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2644 + * may be used to endorse or promote products derived from this software
2645 + * without specific prior written permission.
2647 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2648 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2649 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2650 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2651 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2652 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2653 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2654 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2655 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2656 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2661 + * Wrapper for acquiring a credential handle.
2664 +#include "gssapiP_eap.h"
2666 +OM_uint32 GSSAPI_CALLCONV
2667 +gss_acquire_cred(OM_uint32 *minor,
2668 + gss_name_t desired_name,
2669 + OM_uint32 time_req,
2670 + gss_OID_set desired_mechs,
2671 + gss_cred_usage_t cred_usage,
2672 + gss_cred_id_t *output_cred_handle,
2673 + gss_OID_set *actual_mechs,
2674 + OM_uint32 *time_rec)
2676 + return gssEapAcquireCred(minor, desired_name,
2677 + time_req, desired_mechs, cred_usage,
2678 + output_cred_handle, actual_mechs, time_rec);
2680 diff --git a/mech_eap/acquire_cred_with_password.c b/mech_eap/acquire_cred_with_password.c
2681 new file mode 100644
2682 index 0000000..8e08358
2684 +++ b/mech_eap/acquire_cred_with_password.c
2687 + * Copyright (c) 2011, JANET(UK)
2688 + * All rights reserved.
2690 + * Redistribution and use in source and binary forms, with or without
2691 + * modification, are permitted provided that the following conditions
2694 + * 1. Redistributions of source code must retain the above copyright
2695 + * notice, this list of conditions and the following disclaimer.
2697 + * 2. Redistributions in binary form must reproduce the above copyright
2698 + * notice, this list of conditions and the following disclaimer in the
2699 + * documentation and/or other materials provided with the distribution.
2701 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2702 + * may be used to endorse or promote products derived from this software
2703 + * without specific prior written permission.
2705 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2706 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2707 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2708 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2709 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2710 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2711 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2712 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2713 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2714 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2719 + * Wrapper for acquiring a credential handle using a password.
2722 +#include "gssapiP_eap.h"
2724 +OM_uint32 GSSAPI_CALLCONV
2725 +gssspi_acquire_cred_with_password(OM_uint32 *minor,
2726 + const gss_name_t desired_name,
2727 + const gss_buffer_t password,
2728 + OM_uint32 time_req,
2729 + const gss_OID_set desired_mechs,
2730 + gss_cred_usage_t cred_usage,
2731 + gss_cred_id_t *output_cred_handle,
2732 + gss_OID_set *actual_mechs,
2733 + OM_uint32 *time_rec)
2735 + OM_uint32 major, tmpMinor;
2737 + major = gssEapAcquireCred(minor, desired_name,
2738 + time_req, desired_mechs, cred_usage,
2739 + output_cred_handle, actual_mechs, time_rec);
2740 + if (GSS_ERROR(major))
2743 + major = gssEapSetCredPassword(minor, *output_cred_handle, password);
2744 + if (GSS_ERROR(major))
2748 + if (GSS_ERROR(major))
2749 + gssEapReleaseCred(&tmpMinor, output_cred_handle);
2753 diff --git a/mech_eap/add_cred.c b/mech_eap/add_cred.c
2754 new file mode 100644
2755 index 0000000..64d97c0
2757 +++ b/mech_eap/add_cred.c
2760 + * Copyright (c) 2011, JANET(UK)
2761 + * All rights reserved.
2763 + * Redistribution and use in source and binary forms, with or without
2764 + * modification, are permitted provided that the following conditions
2767 + * 1. Redistributions of source code must retain the above copyright
2768 + * notice, this list of conditions and the following disclaimer.
2770 + * 2. Redistributions in binary form must reproduce the above copyright
2771 + * notice, this list of conditions and the following disclaimer in the
2772 + * documentation and/or other materials provided with the distribution.
2774 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2775 + * may be used to endorse or promote products derived from this software
2776 + * without specific prior written permission.
2778 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2779 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2780 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2781 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2782 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2783 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2784 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2785 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2786 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2787 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2792 + * Wrapper for acquiring a credential handle.
2795 +#include "gssapiP_eap.h"
2798 + * Note that this shouldn't really be required to be implemented by anything
2799 + * apart from the mechanism glue layer. However, Heimdal does call into the
2802 +OM_uint32 GSSAPI_CALLCONV
2803 +gss_add_cred(OM_uint32 *minor,
2804 + gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
2805 + gss_name_t desired_name,
2806 + gss_OID desired_mech,
2807 + gss_cred_usage_t cred_usage,
2808 + OM_uint32 initiator_time_req,
2809 + OM_uint32 acceptor_time_req,
2810 + gss_cred_id_t *output_cred_handle,
2811 + gss_OID_set *actual_mechs,
2812 + OM_uint32 *initiator_time_rec,
2813 + OM_uint32 *acceptor_time_rec)
2816 + OM_uint32 time_req, time_rec = 0;
2817 + gss_OID_set_desc mechs;
2820 + *output_cred_handle = GSS_C_NO_CREDENTIAL;
2822 + if (cred_usage == GSS_C_ACCEPT)
2823 + time_req = acceptor_time_req;
2825 + time_req = initiator_time_req;
2828 + mechs.elements = desired_mech;
2830 + major = gssEapAcquireCred(minor,
2835 + output_cred_handle,
2839 + if (initiator_time_rec != NULL)
2840 + *initiator_time_rec = time_rec;
2841 + if (acceptor_time_rec != NULL)
2842 + *acceptor_time_rec = time_rec;
2846 diff --git a/mech_eap/add_cred_with_password.c b/mech_eap/add_cred_with_password.c
2847 new file mode 100644
2848 index 0000000..b982f0d
2850 +++ b/mech_eap/add_cred_with_password.c
2853 + * Copyright (c) 2011, JANET(UK)
2854 + * All rights reserved.
2856 + * Redistribution and use in source and binary forms, with or without
2857 + * modification, are permitted provided that the following conditions
2860 + * 1. Redistributions of source code must retain the above copyright
2861 + * notice, this list of conditions and the following disclaimer.
2863 + * 2. Redistributions in binary form must reproduce the above copyright
2864 + * notice, this list of conditions and the following disclaimer in the
2865 + * documentation and/or other materials provided with the distribution.
2867 + * 3. Neither the name of JANET(UK) nor the names of its contributors
2868 + * may be used to endorse or promote products derived from this software
2869 + * without specific prior written permission.
2871 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2872 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2873 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2874 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2875 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2876 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2877 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2878 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2879 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2880 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2885 + * Wrapper for acquiring a credential handle using a password.
2888 +#include "gssapiP_eap.h"
2890 +OM_uint32 GSSAPI_CALLCONV
2891 +gss_add_cred_with_password(OM_uint32 *minor,
2892 + const gss_cred_id_t input_cred_handle GSSEAP_UNUSED,
2893 + const gss_name_t desired_name,
2894 + const gss_OID desired_mech,
2895 + const gss_buffer_t password,
2896 + gss_cred_usage_t cred_usage,
2897 + OM_uint32 initiator_time_req,
2898 + OM_uint32 acceptor_time_req,
2899 + gss_cred_id_t *output_cred_handle,
2900 + gss_OID_set *actual_mechs,
2901 + OM_uint32 *initiator_time_rec,
2902 + OM_uint32 *acceptor_time_rec)
2904 + OM_uint32 major, tmpMinor;
2905 + OM_uint32 time_req, time_rec = 0;
2906 + gss_OID_set_desc mechs;
2909 + *output_cred_handle = GSS_C_NO_CREDENTIAL;
2911 + if (cred_usage == GSS_C_ACCEPT)
2912 + time_req = acceptor_time_req;
2914 + time_req = initiator_time_req;
2917 + mechs.elements = desired_mech;
2919 + major = gssEapAcquireCred(minor,
2924 + output_cred_handle,
2927 + if (GSS_ERROR(major))
2930 + major = gssEapSetCredPassword(minor, *output_cred_handle, password);
2931 + if (GSS_ERROR(major))
2934 + if (initiator_time_rec != NULL)
2935 + *initiator_time_rec = time_rec;
2936 + if (acceptor_time_rec != NULL)
2937 + *acceptor_time_rec = time_rec;
2940 + if (GSS_ERROR(major))
2941 + gssEapReleaseCred(&tmpMinor, output_cred_handle);
2945 diff --git a/mech_eap/authdata_plugin.h b/mech_eap/authdata_plugin.h
2946 new file mode 100644
2947 index 0000000..32bff2f
2949 +++ b/mech_eap/authdata_plugin.h
2951 +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2953 + * krb5/authdata_plugin.h
2955 + * Copyright (C) 2007 Apple Inc. All Rights Reserved.
2957 + * Export of this software from the United States of America may
2958 + * require a specific license from the United States Government.
2959 + * It is the responsibility of any person or organization contemplating
2960 + * export to obtain such a license before exporting.
2962 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
2963 + * distribute this software and its documentation for any purpose and
2964 + * without fee is hereby granted, provided that the above copyright
2965 + * notice appear in all copies and that both that copyright notice and
2966 + * this permission notice appear in supporting documentation, and that
2967 + * the name of M.I.T. not be used in advertising or publicity pertaining
2968 + * to distribution of the software without specific, written prior
2969 + * permission. Furthermore if you modify this software you must label
2970 + * your software as modified software and not distribute it in such a
2971 + * fashion that it might be confused with the original M.I.T. software.
2972 + * M.I.T. makes no representations about the suitability of
2973 + * this software for any purpose. It is provided "as is" without express
2974 + * or implied warranty.
2976 + * AuthorizationData plugin definitions for Kerberos 5.
2980 + * This is considered an INTERNAL interface at this time.
2982 + * Some work is needed before exporting it:
2984 + * + Documentation.
2986 + * + Test cases (preferably automated testing under "make check").
2987 + * + Hook into TGS exchange too; will change API.
2988 + * + Examine memory management issues, especially for Windows; may
2991 + * Other changes that would be nice to have, but not necessarily
2992 + * before making this interface public:
2994 + * + Library support for AD-IF-RELEVANT and similar wrappers. (We can
2995 + * make the plugin construct them if it wants them.)
2996 + * + KDC could combine/optimize wrapped AD elements provided by
2997 + * multiple plugins, e.g., two IF-RELEVANT sequences could be
2998 + * merged. (The preauth plugin API also has this bug, we're going
2999 + * to need a general fix.)
3002 +#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED
3003 +#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED
3004 +#include <krb5/krb5.h>
3007 + * While arguments of these types are passed-in, for the most part a
3008 + * authorization data module can treat them as opaque. If we need
3009 + * keying data, we can ask for it directly.
3011 +struct _krb5_db_entry_new;
3014 + * The function table / structure which an authdata server module must export as
3015 + * "authdata_server_0". NOTE: replace "0" with "1" for the type and
3016 + * variable names if this gets picked up by upstream. If the interfaces work
3017 + * correctly, future versions of the table will add either more callbacks or
3018 + * more arguments to callbacks, and in both cases we'll be able to wrap the v0
3021 +/* extern krb5plugin_authdata_ftable_v0 authdata_server_0; */
3022 +typedef struct krb5plugin_authdata_server_ftable_v0 {
3023 + /* Not-usually-visible name. */
3027 + * Per-plugin initialization/cleanup. The init function is called
3028 + * by the KDC when the plugin is loaded, and the fini function is
3029 + * called before the plugin is unloaded. Both are optional.
3031 + krb5_error_code (*init_proc)(krb5_context, void **);
3032 + void (*fini_proc)(krb5_context, void *);
3034 + * Actual authorization data handling function. If this field
3035 + * holds a null pointer, this mechanism will be skipped, and the
3036 + * init/fini functions will not be run.
3038 + * This function should only modify the field
3039 + * enc_tkt_reply->authorization_data. All other values should be
3040 + * considered inputs only. And, it should *modify* the field, not
3041 + * overwrite it and assume that there are no other authdata
3044 + * Memory management: authorization_data is a malloc-allocated,
3045 + * null-terminated sequence of malloc-allocated pointers to
3046 + * authorization data structures. This plugin code currently
3047 + * assumes the libraries, KDC, and plugin all use the same malloc
3048 + * pool, which may be a problem if/when we get the KDC code
3049 + * running on Windows.
3051 + * If this function returns a non-zero error code, a message
3052 + * is logged, but no other action is taken. Other authdata
3053 + * plugins will be called, and a response will be sent to the
3054 + * client (barring other problems).
3056 + krb5_error_code (*authdata_proc)(krb5_context,
3057 + struct _krb5_db_entry_new *client,
3058 + krb5_data *req_pkt,
3059 + krb5_kdc_req *request,
3060 + krb5_enc_tkt_part *enc_tkt_reply);
3061 +} krb5plugin_server_authdata_ftable_v0;
3063 +typedef krb5plugin_server_authdata_ftable_v0 krb5plugin_authdata_ftable_v0;
3065 +typedef struct krb5plugin_authdata_server_ftable_v2 {
3066 + /* Not-usually-visible name. */
3070 + * Per-plugin initialization/cleanup. The init function is called
3071 + * by the KDC when the plugin is loaded, and the fini function is
3072 + * called before the plugin is unloaded. Both are optional.
3074 + krb5_error_code (*init_proc)(krb5_context, void **);
3075 + void (*fini_proc)(krb5_context, void *);
3077 + * Actual authorization data handling function. If this field
3078 + * holds a null pointer, this mechanism will be skipped, and the
3079 + * init/fini functions will not be run.
3081 + * This function should only modify the field
3082 + * enc_tkt_reply->authorization_data. All other values should be
3083 + * considered inputs only. And, it should *modify* the field, not
3084 + * overwrite it and assume that there are no other authdata
3087 + * Memory management: authorization_data is a malloc-allocated,
3088 + * null-terminated sequence of malloc-allocated pointers to
3089 + * authorization data structures. This plugin code currently
3090 + * assumes the libraries, KDC, and plugin all use the same malloc
3091 + * pool, which may be a problem if/when we get the KDC code
3092 + * running on Windows.
3094 + * If this function returns a non-zero error code, a message
3095 + * is logged, but no other action is taken. Other authdata
3096 + * plugins will be called, and a response will be sent to the
3097 + * client (barring other problems).
3099 + krb5_error_code (*authdata_proc)(krb5_context,
3100 + unsigned int flags,
3101 + struct _krb5_db_entry_new *client,
3102 + struct _krb5_db_entry_new *server,
3103 + struct _krb5_db_entry_new *tgs,
3104 + krb5_keyblock *client_key,
3105 + krb5_keyblock *server_key,
3106 + krb5_keyblock *tgs_key,
3107 + krb5_data *req_pkt,
3108 + krb5_kdc_req *request,
3109 + krb5_const_principal for_user_princ,
3110 + krb5_enc_tkt_part *enc_tkt_request,
3111 + krb5_enc_tkt_part *enc_tkt_reply);
3112 +} krb5plugin_authdata_server_ftable_v2;
3114 +typedef krb5plugin_authdata_server_ftable_v2 krb5plugin_authdata_ftable_v2;
3116 +typedef krb5_error_code
3117 +(*authdata_client_plugin_init_proc)(krb5_context context,
3118 + void **plugin_context);
3120 +#define AD_USAGE_AS_REQ 0x01
3121 +#define AD_USAGE_TGS_REQ 0x02
3122 +#define AD_USAGE_AP_REQ 0x04
3123 +#define AD_USAGE_KDC_ISSUED 0x08
3124 +#define AD_USAGE_MASK 0x0F
3125 +#define AD_INFORMATIONAL 0x10
3127 +struct _krb5_authdata_context;
3130 +(*authdata_client_plugin_flags_proc)(krb5_context kcontext,
3131 + void *plugin_context,
3132 + krb5_authdatatype ad_type,
3133 + krb5_flags *flags);
3136 +(*authdata_client_plugin_fini_proc)(krb5_context kcontext,
3137 + void *plugin_context);
3139 +typedef krb5_error_code
3140 +(*authdata_client_request_init_proc)(krb5_context kcontext,
3141 + struct _krb5_authdata_context *context,
3142 + void *plugin_context,
3143 + void **request_context);
3146 +(*authdata_client_request_fini_proc)(krb5_context kcontext,
3147 + struct _krb5_authdata_context *context,
3148 + void *plugin_context,
3149 + void *request_context);
3151 +typedef krb5_error_code
3152 +(*authdata_client_import_authdata_proc)(krb5_context kcontext,
3153 + struct _krb5_authdata_context *context,
3154 + void *plugin_context,
3155 + void *request_context,
3156 + krb5_authdata **authdata,
3157 + krb5_boolean kdc_issued_flag,
3158 + krb5_const_principal issuer);
3160 +typedef krb5_error_code
3161 +(*authdata_client_export_authdata_proc)(krb5_context kcontext,
3162 + struct _krb5_authdata_context *context,
3163 + void *plugin_context,
3164 + void *request_context,
3166 + krb5_authdata ***authdata);
3168 +typedef krb5_error_code
3169 +(*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
3170 + struct _krb5_authdata_context *context,
3171 + void *plugin_context,
3172 + void *request_context,
3173 + krb5_data **attrs);
3175 +typedef krb5_error_code
3176 +(*authdata_client_get_attribute_proc)(krb5_context kcontext,
3177 + struct _krb5_authdata_context *context,
3178 + void *plugin_context,
3179 + void *request_context,
3180 + const krb5_data *attribute,
3181 + krb5_boolean *authenticated,
3182 + krb5_boolean *complete,
3184 + krb5_data *display_value,
3187 +typedef krb5_error_code
3188 +(*authdata_client_set_attribute_proc)(krb5_context kcontext,
3189 + struct _krb5_authdata_context *context,
3190 + void *plugin_context,
3191 + void *request_context,
3192 + krb5_boolean complete,
3193 + const krb5_data *attribute,
3194 + const krb5_data *value);
3196 +typedef krb5_error_code
3197 +(*authdata_client_delete_attribute_proc)(krb5_context kcontext,
3198 + struct _krb5_authdata_context *context,
3199 + void *plugin_context,
3200 + void *request_context,
3201 + const krb5_data *attribute);
3203 +typedef krb5_error_code
3204 +(*authdata_client_export_internal_proc)(krb5_context kcontext,
3205 + struct _krb5_authdata_context *context,
3206 + void *plugin_context,
3207 + void *request_context,
3208 + krb5_boolean restrict_authenticated,
3212 +(*authdata_client_free_internal_proc)(krb5_context kcontext,
3213 + struct _krb5_authdata_context *context,
3214 + void *plugin_context,
3215 + void *request_context,
3218 +typedef krb5_error_code
3219 +(*authdata_client_verify_proc)(krb5_context kcontext,
3220 + struct _krb5_authdata_context *context,
3221 + void *plugin_context,
3222 + void *request_context,
3223 + const krb5_auth_context *auth_context,
3224 + const krb5_keyblock *key,
3225 + const krb5_ap_req *req);
3227 +typedef krb5_error_code
3228 +(*authdata_client_size_proc)(krb5_context kcontext,
3229 + struct _krb5_authdata_context *context,
3230 + void *plugin_context,
3231 + void *request_context,
3234 +typedef krb5_error_code
3235 +(*authdata_client_externalize_proc)(krb5_context kcontext,
3236 + struct _krb5_authdata_context *context,
3237 + void *plugin_context,
3238 + void *request_context,
3239 + krb5_octet **buffer,
3240 + size_t *lenremain);
3242 +typedef krb5_error_code
3243 +(*authdata_client_internalize_proc)(krb5_context kcontext,
3244 + struct _krb5_authdata_context *context,
3245 + void *plugin_context,
3246 + void *request_context,
3247 + krb5_octet **buffer,
3248 + size_t *lenremain);
3250 +typedef krb5_error_code
3251 +(*authdata_client_copy_proc)(krb5_context kcontext,
3252 + struct _krb5_authdata_context *context,
3253 + void *plugin_context,
3254 + void *request_context,
3255 + void *dst_plugin_context,
3256 + void *dst_request_context);
3258 +typedef struct krb5plugin_authdata_client_ftable_v0 {
3260 + krb5_authdatatype *ad_type_list;
3261 + authdata_client_plugin_init_proc init;
3262 + authdata_client_plugin_fini_proc fini;
3263 + authdata_client_plugin_flags_proc flags;
3264 + authdata_client_request_init_proc request_init;
3265 + authdata_client_request_fini_proc request_fini;
3266 + authdata_client_get_attribute_types_proc get_attribute_types;
3267 + authdata_client_get_attribute_proc get_attribute;
3268 + authdata_client_set_attribute_proc set_attribute;
3269 + authdata_client_delete_attribute_proc delete_attribute;
3270 + authdata_client_export_authdata_proc export_authdata;
3271 + authdata_client_import_authdata_proc import_authdata;
3272 + authdata_client_export_internal_proc export_internal;
3273 + authdata_client_free_internal_proc free_internal;
3274 + authdata_client_verify_proc verify;
3275 + authdata_client_size_proc size;
3276 + authdata_client_externalize_proc externalize;
3277 + authdata_client_internalize_proc internalize;
3278 + authdata_client_copy_proc copy; /* optional */
3279 +} krb5plugin_authdata_client_ftable_v0;
3281 +#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
3282 diff --git a/mech_eap/authorize_localname.c b/mech_eap/authorize_localname.c
3283 new file mode 100644
3284 index 0000000..0037e2b
3286 +++ b/mech_eap/authorize_localname.c
3289 + * Copyright (c) 2011, JANET(UK)
3290 + * All rights reserved.
3292 + * Redistribution and use in source and binary forms, with or without
3293 + * modification, are permitted provided that the following conditions
3296 + * 1. Redistributions of source code must retain the above copyright
3297 + * notice, this list of conditions and the following disclaimer.
3299 + * 2. Redistributions in binary form must reproduce the above copyright
3300 + * notice, this list of conditions and the following disclaimer in the
3301 + * documentation and/or other materials provided with the distribution.
3303 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3304 + * may be used to endorse or promote products derived from this software
3305 + * without specific prior written permission.
3307 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3308 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3309 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3310 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3311 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3312 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3313 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3314 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3315 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3316 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3321 + * Local authorization services.
3324 +#include "gssapiP_eap.h"
3326 +OM_uint32 GSSAPI_CALLCONV
3327 +gssspi_authorize_localname(OM_uint32 *minor,
3328 + const gss_name_t name GSSEAP_UNUSED,
3329 + gss_const_buffer_t local_user GSSEAP_UNUSED,
3330 + gss_const_OID local_nametype GSSEAP_UNUSED)
3333 + * The MIT mechglue will fallback to comparing names in the absence
3334 + * of a mechanism implementation of gss_userok. To avoid this and
3335 + * force the mechglue to use attribute-based authorization, always
3336 + * return access denied here.
3340 + return GSS_S_UNAUTHORIZED;
3342 diff --git a/mech_eap/canonicalize_name.c b/mech_eap/canonicalize_name.c
3343 new file mode 100644
3344 index 0000000..5e66798
3346 +++ b/mech_eap/canonicalize_name.c
3349 + * Copyright (c) 2011, JANET(UK)
3350 + * All rights reserved.
3352 + * Redistribution and use in source and binary forms, with or without
3353 + * modification, are permitted provided that the following conditions
3356 + * 1. Redistributions of source code must retain the above copyright
3357 + * notice, this list of conditions and the following disclaimer.
3359 + * 2. Redistributions in binary form must reproduce the above copyright
3360 + * notice, this list of conditions and the following disclaimer in the
3361 + * documentation and/or other materials provided with the distribution.
3363 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3364 + * may be used to endorse or promote products derived from this software
3365 + * without specific prior written permission.
3367 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3368 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3369 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3370 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3371 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3372 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3373 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3374 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3375 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3376 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3381 + * Function for canonicalizing a name; presently just duplicates it.
3384 +#include "gssapiP_eap.h"
3386 +OM_uint32 GSSAPI_CALLCONV
3387 +gss_canonicalize_name(OM_uint32 *minor,
3388 + const gss_name_t input_name,
3389 + const gss_OID mech_type,
3390 + gss_name_t *output_name)
3396 + if (!gssEapIsMechanismOid(mech_type))
3397 + return GSS_S_BAD_MECH;
3399 + if (input_name == GSS_C_NO_NAME) {
3401 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
3404 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
3406 + major = gssEapCanonicalizeName(minor, input_name, mech_type, output_name);
3408 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
3412 diff --git a/mech_eap/compare_name.c b/mech_eap/compare_name.c
3413 new file mode 100644
3414 index 0000000..edadf3e
3416 +++ b/mech_eap/compare_name.c
3419 + * Copyright (c) 2011, JANET(UK)
3420 + * All rights reserved.
3422 + * Redistribution and use in source and binary forms, with or without
3423 + * modification, are permitted provided that the following conditions
3426 + * 1. Redistributions of source code must retain the above copyright
3427 + * notice, this list of conditions and the following disclaimer.
3429 + * 2. Redistributions in binary form must reproduce the above copyright
3430 + * notice, this list of conditions and the following disclaimer in the
3431 + * documentation and/or other materials provided with the distribution.
3433 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3434 + * may be used to endorse or promote products derived from this software
3435 + * without specific prior written permission.
3437 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3438 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3439 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3440 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3441 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3442 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3443 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3444 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3445 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3446 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3451 + * Compare two names.
3454 +#include "gssapiP_eap.h"
3456 +OM_uint32 GSSAPI_CALLCONV
3457 +gss_compare_name(OM_uint32 *minor,
3462 + return gssEapCompareName(minor, name1, name2, name_equal);
3464 diff --git a/mech_eap/context_time.c b/mech_eap/context_time.c
3465 new file mode 100644
3466 index 0000000..ae47d6c
3468 +++ b/mech_eap/context_time.c
3471 + * Copyright (c) 2011, JANET(UK)
3472 + * All rights reserved.
3474 + * Redistribution and use in source and binary forms, with or without
3475 + * modification, are permitted provided that the following conditions
3478 + * 1. Redistributions of source code must retain the above copyright
3479 + * notice, this list of conditions and the following disclaimer.
3481 + * 2. Redistributions in binary form must reproduce the above copyright
3482 + * notice, this list of conditions and the following disclaimer in the
3483 + * documentation and/or other materials provided with the distribution.
3485 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3486 + * may be used to endorse or promote products derived from this software
3487 + * without specific prior written permission.
3489 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3490 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3491 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3492 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3493 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3494 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3495 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3496 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3497 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3498 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3503 + * Determine remaining lifetime of a context handle.
3506 +#include "gssapiP_eap.h"
3508 +OM_uint32 GSSAPI_CALLCONV
3509 +gss_context_time(OM_uint32 *minor,
3511 + OM_uint32 *time_rec)
3515 + if (ctx == GSS_C_NO_CONTEXT) {
3517 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
3522 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
3524 + if (!CTX_IS_ESTABLISHED(ctx)) {
3525 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
3526 + major = GSS_S_NO_CONTEXT;
3530 + major = gssEapContextTime(minor, ctx, time_rec);
3531 + if (GSS_ERROR(major))
3535 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3539 diff --git a/mech_eap/delete_name_attribute.c b/mech_eap/delete_name_attribute.c
3540 new file mode 100644
3541 index 0000000..fe0ff8f
3543 +++ b/mech_eap/delete_name_attribute.c
3546 + * Copyright (c) 2011, JANET(UK)
3547 + * All rights reserved.
3549 + * Redistribution and use in source and binary forms, with or without
3550 + * modification, are permitted provided that the following conditions
3553 + * 1. Redistributions of source code must retain the above copyright
3554 + * notice, this list of conditions and the following disclaimer.
3556 + * 2. Redistributions in binary form must reproduce the above copyright
3557 + * notice, this list of conditions and the following disclaimer in the
3558 + * documentation and/or other materials provided with the distribution.
3560 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3561 + * may be used to endorse or promote products derived from this software
3562 + * without specific prior written permission.
3564 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3565 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3566 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3567 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3568 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3569 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3570 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3571 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3572 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3573 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3578 + * Wrapper for removing a name attribute.
3581 +#include "gssapiP_eap.h"
3583 +OM_uint32 GSSAPI_CALLCONV
3584 +gss_delete_name_attribute(OM_uint32 *minor,
3586 + gss_buffer_t attr)
3592 + if (name == GSS_C_NO_NAME) {
3594 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
3597 + GSSEAP_MUTEX_LOCK(&name->mutex);
3599 + major = gssEapDeleteNameAttribute(minor, name, attr);
3601 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
3605 diff --git a/mech_eap/delete_sec_context.c b/mech_eap/delete_sec_context.c
3606 new file mode 100644
3607 index 0000000..7913e45
3609 +++ b/mech_eap/delete_sec_context.c
3612 + * Copyright (c) 2011, JANET(UK)
3613 + * All rights reserved.
3615 + * Redistribution and use in source and binary forms, with or without
3616 + * modification, are permitted provided that the following conditions
3619 + * 1. Redistributions of source code must retain the above copyright
3620 + * notice, this list of conditions and the following disclaimer.
3622 + * 2. Redistributions in binary form must reproduce the above copyright
3623 + * notice, this list of conditions and the following disclaimer in the
3624 + * documentation and/or other materials provided with the distribution.
3626 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3627 + * may be used to endorse or promote products derived from this software
3628 + * without specific prior written permission.
3630 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3631 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3632 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3633 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3634 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3635 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3636 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3637 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3638 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3639 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3644 + * Release a context handle.
3647 +#include "gssapiP_eap.h"
3649 +OM_uint32 GSSAPI_CALLCONV
3650 +gss_delete_sec_context(OM_uint32 *minor,
3651 + gss_ctx_id_t *context_handle,
3652 + gss_buffer_t output_token)
3655 + gss_ctx_id_t ctx = *context_handle;
3659 + if (output_token != GSS_C_NO_BUFFER) {
3660 + output_token->length = 0;
3661 + output_token->value = NULL;
3664 + if (ctx == GSS_C_NO_CONTEXT)
3665 + return GSS_S_COMPLETE;
3667 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
3669 + if (output_token != GSS_C_NO_BUFFER) {
3670 + gss_iov_buffer_desc iov[2];
3672 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
3673 + iov[0].buffer.value = NULL;
3674 + iov[0].buffer.length = 0;
3676 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
3677 + iov[1].buffer.value = NULL;
3678 + iov[1].buffer.length = 0;
3680 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
3681 + iov, 2, TOK_TYPE_DELETE_CONTEXT);
3682 + if (GSS_ERROR(major)) {
3683 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3688 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
3690 + return gssEapReleaseContext(minor, context_handle);
3692 diff --git a/mech_eap/dictionary.ukerna b/mech_eap/dictionary.ukerna
3693 new file mode 100644
3694 index 0000000..0e35d43
3696 +++ b/mech_eap/dictionary.ukerna
3705 +VENDOR UKERNA 25622
3707 +BEGIN-VENDOR UKERNA
3709 +ATTRIBUTE GSS-Acceptor-Service-Name 128 string
3710 +ATTRIBUTE GSS-Acceptor-Host-Name 129 string
3711 +ATTRIBUTE GSS-Acceptor-Service-Specific 130 string
3712 +ATTRIBUTE GSS-Acceptor-Realm-Name 131 string
3713 +ATTRIBUTE SAML-AAA-Assertion 132 string
3714 +ATTRIBUTE MS-Windows-Auth-Data 133 octets
3715 +ATTRIBUTE MS-Windows-Group-Sid 134 string
3718 diff --git a/mech_eap/display_name.c b/mech_eap/display_name.c
3719 new file mode 100644
3720 index 0000000..2d87e66
3722 +++ b/mech_eap/display_name.c
3725 + * Copyright (c) 2011, JANET(UK)
3726 + * All rights reserved.
3728 + * Redistribution and use in source and binary forms, with or without
3729 + * modification, are permitted provided that the following conditions
3732 + * 1. Redistributions of source code must retain the above copyright
3733 + * notice, this list of conditions and the following disclaimer.
3735 + * 2. Redistributions in binary form must reproduce the above copyright
3736 + * notice, this list of conditions and the following disclaimer in the
3737 + * documentation and/or other materials provided with the distribution.
3739 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3740 + * may be used to endorse or promote products derived from this software
3741 + * without specific prior written permission.
3743 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3744 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3745 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3746 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3747 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3748 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3749 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3750 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3751 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3752 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3757 + * Wrapper for "displaying" (returning string representation of) a name.
3760 +#include "gssapiP_eap.h"
3762 +OM_uint32 GSSAPI_CALLCONV
3763 +gss_display_name(OM_uint32 *minor,
3765 + gss_buffer_t output_name_buffer,
3766 + gss_OID *output_name_type)
3768 + /* Lock not required as long as attributes are not used */
3769 + return gssEapDisplayName(minor, name, output_name_buffer,
3770 + output_name_type);
3772 diff --git a/mech_eap/display_name_ext.c b/mech_eap/display_name_ext.c
3773 new file mode 100644
3774 index 0000000..d6791d4
3776 +++ b/mech_eap/display_name_ext.c
3779 + * Copyright (c) 2011, JANET(UK)
3780 + * All rights reserved.
3782 + * Redistribution and use in source and binary forms, with or without
3783 + * modification, are permitted provided that the following conditions
3786 + * 1. Redistributions of source code must retain the above copyright
3787 + * notice, this list of conditions and the following disclaimer.
3789 + * 2. Redistributions in binary form must reproduce the above copyright
3790 + * notice, this list of conditions and the following disclaimer in the
3791 + * documentation and/or other materials provided with the distribution.
3793 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3794 + * may be used to endorse or promote products derived from this software
3795 + * without specific prior written permission.
3797 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3798 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3799 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3800 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3801 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3802 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3803 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3804 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3805 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3806 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3811 + * Parameterized version of gss_display_name(), currently unimplemented.
3814 +#include "gssapiP_eap.h"
3816 +OM_uint32 GSSAPI_CALLCONV
3817 +gss_display_name_ext(OM_uint32 *minor,
3818 + gss_name_t name GSSEAP_UNUSED,
3819 + gss_OID display_as_name_type GSSEAP_UNUSED,
3820 + gss_buffer_t display_name)
3824 + display_name->length = 0;
3825 + display_name->value = NULL;
3827 + return GSS_S_UNAVAILABLE;
3829 diff --git a/mech_eap/display_status.c b/mech_eap/display_status.c
3830 new file mode 100644
3831 index 0000000..fc0d1ab
3833 +++ b/mech_eap/display_status.c
3836 + * Copyright (c) 2011, JANET(UK)
3837 + * All rights reserved.
3839 + * Redistribution and use in source and binary forms, with or without
3840 + * modification, are permitted provided that the following conditions
3843 + * 1. Redistributions of source code must retain the above copyright
3844 + * notice, this list of conditions and the following disclaimer.
3846 + * 2. Redistributions in binary form must reproduce the above copyright
3847 + * notice, this list of conditions and the following disclaimer in the
3848 + * documentation and/or other materials provided with the distribution.
3850 + * 3. Neither the name of JANET(UK) nor the names of its contributors
3851 + * may be used to endorse or promote products derived from this software
3852 + * without specific prior written permission.
3854 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3855 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3856 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3857 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3858 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3859 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3860 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3861 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3862 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3863 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3868 + * Function for converting mechanism error codes to strings.
3871 +#include "gssapiP_eap.h"
3873 +struct gss_eap_status_info {
3876 + struct gss_eap_status_info *next;
3880 +gssEapDestroyStatusInfo(struct gss_eap_status_info *p)
3882 + struct gss_eap_status_info *next;
3884 + for (; p != NULL; p = next) {
3886 + GSSEAP_FREE(p->message);
3892 + * Associate a message with a mechanism (minor) status code. This function
3893 + * takes ownership of the message regardless of success. The message must
3894 + * be explicitly cleared, if required, so it is suggested that a specific
3895 + * minor code is either always or never associated with a message, to avoid
3896 + * dangling (and potentially confusing) error messages.
3899 +saveStatusInfoNoCopy(OM_uint32 minor, char *message)
3901 + struct gss_eap_status_info **next = NULL, *p = NULL;
3902 + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
3904 + if (tld != NULL) {
3905 + for (p = tld->statusInfo; p != NULL; p = p->next) {
3906 + if (p->code == minor) {
3907 + /* Set message in-place */
3908 + if (p->message != NULL)
3909 + GSSEAP_FREE(p->message);
3910 + p->message = message;
3915 + p = GSSEAP_CALLOC(1, sizeof(*p));
3919 + if (message != NULL)
3920 + GSSEAP_FREE(message);
3925 + p->message = message;
3930 + tld->statusInfo = p;
3933 +static const char *
3934 +getStatusInfo(OM_uint32 minor)
3936 + struct gss_eap_status_info *p;
3937 + struct gss_eap_thread_local_data *tld = gssEapGetThreadLocalData();
3939 + if (tld != NULL) {
3940 + for (p = tld->statusInfo; p != NULL; p = p->next) {
3941 + if (p->code == minor)
3942 + return p->message;
3949 +gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...)
3952 + OM_uint32 tmpMajor, tmpMinor;
3954 + gss_buffer_desc s = GSS_C_EMPTY_BUFFER;
3957 + if (format != NULL) {
3958 + va_start(ap, format);
3959 + snprintf(buf, sizeof(buf), format, ap);
3963 + tmpMajor = makeStringBuffer(&tmpMinor, buf, &s);
3964 + if (!GSS_ERROR(tmpMajor))
3965 + saveStatusInfoNoCopy(minor, (char *)s.value);
3971 + if (format != NULL) {
3972 + va_start(ap, format);
3973 + n = vasprintf(&s, format, ap);
3979 + saveStatusInfoNoCopy(minor, s);
3984 +gssEapDisplayStatus(OM_uint32 *minor,
3985 + OM_uint32 status_value,
3986 + gss_buffer_t status_string)
3989 + krb5_context krbContext = NULL;
3990 + const char *errMsg;
3992 + status_string->length = 0;
3993 + status_string->value = NULL;
3995 + errMsg = getStatusInfo(status_value);
3996 + if (errMsg == NULL) {
3997 + GSSEAP_KRB_INIT(&krbContext);
3999 + /* Try the com_err message */
4000 + errMsg = krb5_get_error_message(krbContext, status_value);
4003 + if (errMsg != NULL) {
4004 + major = makeStringBuffer(minor, errMsg, status_string);
4006 + major = GSS_S_COMPLETE;
4010 + if (krbContext != NULL)
4011 + krb5_free_error_message(krbContext, errMsg);
4016 +OM_uint32 GSSAPI_CALLCONV
4017 +gss_display_status(OM_uint32 *minor,
4018 + OM_uint32 status_value,
4020 + gss_OID mech_type,
4021 + OM_uint32 *message_context,
4022 + gss_buffer_t status_string)
4024 + if (!gssEapIsMechanismOid(mech_type)) {
4025 + *minor = GSSEAP_WRONG_MECH;
4026 + return GSS_S_BAD_MECH;
4029 + if (status_type != GSS_C_MECH_CODE ||
4030 + *message_context != 0) {
4031 + /* we rely on the mechglue for GSS_C_GSS_CODE */
4033 + return GSS_S_BAD_STATUS;
4036 + return gssEapDisplayStatus(minor, status_value, status_string);
4038 diff --git a/mech_eap/duplicate_name.c b/mech_eap/duplicate_name.c
4039 new file mode 100644
4040 index 0000000..303619e
4042 +++ b/mech_eap/duplicate_name.c
4045 + * Copyright (c) 2011, JANET(UK)
4046 + * All rights reserved.
4048 + * Redistribution and use in source and binary forms, with or without
4049 + * modification, are permitted provided that the following conditions
4052 + * 1. Redistributions of source code must retain the above copyright
4053 + * notice, this list of conditions and the following disclaimer.
4055 + * 2. Redistributions in binary form must reproduce the above copyright
4056 + * notice, this list of conditions and the following disclaimer in the
4057 + * documentation and/or other materials provided with the distribution.
4059 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4060 + * may be used to endorse or promote products derived from this software
4061 + * without specific prior written permission.
4063 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4064 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4065 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4066 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4067 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4068 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4069 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4070 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4071 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4072 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4077 + * Duplicate a name.
4080 +#include "gssapiP_eap.h"
4082 +OM_uint32 GSSAPI_CALLCONV
4083 +gss_duplicate_name(OM_uint32 *minor,
4084 + const gss_name_t input_name,
4085 + gss_name_t *dest_name)
4091 + if (input_name == GSS_C_NO_NAME) {
4093 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4096 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4098 + major = gssEapDuplicateName(minor, input_name, dest_name);
4100 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4104 diff --git a/mech_eap/eap_mech.c b/mech_eap/eap_mech.c
4105 new file mode 100644
4106 index 0000000..96e00c2
4108 +++ b/mech_eap/eap_mech.c
4111 + * Copyright (c) 2011, JANET(UK)
4112 + * All rights reserved.
4114 + * Redistribution and use in source and binary forms, with or without
4115 + * modification, are permitted provided that the following conditions
4118 + * 1. Redistributions of source code must retain the above copyright
4119 + * notice, this list of conditions and the following disclaimer.
4121 + * 2. Redistributions in binary form must reproduce the above copyright
4122 + * notice, this list of conditions and the following disclaimer in the
4123 + * documentation and/or other materials provided with the distribution.
4125 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4126 + * may be used to endorse or promote products derived from this software
4127 + * without specific prior written permission.
4129 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4130 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4131 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4132 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4133 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4134 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4135 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4136 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4137 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4138 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4143 + * Initialisation and finalise functions.
4146 +#include "gssapiP_eap.h"
4149 +eapPeerRegisterMethods(OM_uint32 *minor)
4151 + OM_uint32 ret = 0;
4155 + ret = eap_peer_md5_register();
4156 +#endif /* EAP_MD5 */
4160 + ret = eap_peer_tls_register();
4161 +#endif /* EAP_TLS */
4163 +#ifdef EAP_MSCHAPv2
4165 + ret = eap_peer_mschapv2_register();
4166 +#endif /* EAP_MSCHAPv2 */
4170 + ret = eap_peer_peap_register();
4171 +#endif /* EAP_PEAP */
4175 + ret = eap_peer_ttls_register();
4176 +#endif /* EAP_TTLS */
4180 + ret = eap_peer_gtc_register();
4181 +#endif /* EAP_GTC */
4185 + ret = eap_peer_otp_register();
4186 +#endif /* EAP_OTP */
4190 + ret = eap_peer_sim_register();
4191 +#endif /* EAP_SIM */
4195 + ret = eap_peer_leap_register();
4196 +#endif /* EAP_LEAP */
4200 + ret = eap_peer_psk_register();
4201 +#endif /* EAP_PSK */
4205 + ret = eap_peer_aka_register();
4206 +#endif /* EAP_AKA */
4208 +#ifdef EAP_AKA_PRIME
4210 + ret = eap_peer_aka_prime_register();
4211 +#endif /* EAP_AKA_PRIME */
4215 + ret = eap_peer_fast_register();
4216 +#endif /* EAP_FAST */
4220 + ret = eap_peer_pax_register();
4221 +#endif /* EAP_PAX */
4225 + ret = eap_peer_sake_register();
4226 +#endif /* EAP_SAKE */
4230 + ret = eap_peer_gpsk_register();
4231 +#endif /* EAP_GPSK */
4235 + ret = eap_peer_wsc_register();
4236 +#endif /* EAP_WSC */
4240 + ret = eap_peer_ikev2_register();
4241 +#endif /* EAP_IKEV2 */
4243 +#ifdef EAP_VENDOR_TEST
4245 + ret = eap_peer_vendor_test_register();
4246 +#endif /* EAP_VENDOR_TEST */
4250 + ret = eap_peer_tnc_register();
4251 +#endif /* EAP_TNC */
4254 + return GSS_S_COMPLETE;
4256 + *minor = GSSEAP_LIBEAP_INIT_FAILURE;
4257 + return GSS_S_FAILURE;
4261 +gssEapInitLibEap(OM_uint32 *minor)
4263 + return eapPeerRegisterMethods(minor);
4267 +gssEapInitLibRadsec(OM_uint32 *minor)
4270 + *minor = GSSEAP_RADSEC_INIT_FAILURE;
4271 + return GSS_S_FAILURE;
4274 + return GSS_S_COMPLETE;
4277 +void gssEapFinalize(void) GSSEAP_DESTRUCTOR;
4280 +gssEapInitiatorInit(OM_uint32 *minor)
4284 + initialize_eapg_error_table();
4285 + initialize_rse_error_table();
4287 + major = gssEapInitLibEap(minor);
4288 + if (GSS_ERROR(major))
4291 + major = gssEapInitLibRadsec(minor);
4292 + if (GSS_ERROR(major))
4295 +#ifdef GSSEAP_ENABLE_REAUTH
4296 + major = gssEapReauthInitialize(minor);
4297 + if (GSS_ERROR(major))
4302 + return GSS_S_COMPLETE;
4306 +gssEapFinalize(void)
4308 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4311 + gssEapAttrProvidersFinalize(&minor);
4313 + eap_peer_unregister_methods();
4316 +#ifdef GSSEAP_CONSTRUCTOR
4317 +static void gssEapInitiatorInitAssert(void) GSSEAP_CONSTRUCTOR;
4320 +gssEapInitiatorInitAssert(void)
4322 + OM_uint32 major, minor;
4324 + major = gssEapInitiatorInit(&minor);
4326 + GSSEAP_ASSERT(!GSS_ERROR(major));
4329 diff --git a/mech_eap/exchange_meta_data.c b/mech_eap/exchange_meta_data.c
4330 new file mode 100644
4331 index 0000000..5d56795
4333 +++ b/mech_eap/exchange_meta_data.c
4336 + * Copyright (c) 2011, JANET(UK)
4337 + * All rights reserved.
4339 + * Redistribution and use in source and binary forms, with or without
4340 + * modification, are permitted provided that the following conditions
4343 + * 1. Redistributions of source code must retain the above copyright
4344 + * notice, this list of conditions and the following disclaimer.
4346 + * 2. Redistributions in binary form must reproduce the above copyright
4347 + * notice, this list of conditions and the following disclaimer in the
4348 + * documentation and/or other materials provided with the distribution.
4350 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4351 + * may be used to endorse or promote products derived from this software
4352 + * without specific prior written permission.
4354 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4355 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4356 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4357 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4358 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4359 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4360 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4361 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4362 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4363 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4371 +#include "gssapiP_eap.h"
4373 +OM_uint32 GSSAPI_CALLCONV
4374 +gssEapExchangeMetaData(OM_uint32 *minor,
4375 + gss_const_OID mech GSSEAP_UNUSED,
4376 + gss_cred_id_t cred GSSEAP_UNUSED,
4377 + gss_ctx_id_t *ctx GSSEAP_UNUSED,
4378 + const gss_name_t name GSSEAP_UNUSED,
4379 + OM_uint32 req_flags GSSEAP_UNUSED,
4380 + gss_const_buffer_t meta_data GSSEAP_UNUSED)
4383 + return GSS_S_COMPLETE;
4386 +OM_uint32 GSSAPI_CALLCONV
4387 +gss_exchange_meta_data(OM_uint32 *minor,
4388 + gss_const_OID mech,
4389 + gss_cred_id_t cred,
4390 + gss_ctx_id_t *context_handle,
4391 + const gss_name_t name,
4392 + OM_uint32 req_flags,
4393 + gss_const_buffer_t meta_data)
4395 + gss_ctx_id_t ctx = *context_handle;
4398 + if (cred != GSS_C_NO_CREDENTIAL)
4399 + GSSEAP_MUTEX_LOCK(&cred->mutex);
4401 + if (*context_handle != GSS_C_NO_CONTEXT)
4402 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4404 + major = gssEapExchangeMetaData(minor, mech, cred, &ctx,
4405 + name, req_flags, meta_data);
4407 + if (*context_handle != GSS_C_NO_CONTEXT)
4408 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4410 + *context_handle = ctx;
4412 + if (cred != GSS_C_NO_CREDENTIAL)
4413 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
4417 diff --git a/mech_eap/export_name.c b/mech_eap/export_name.c
4418 new file mode 100644
4419 index 0000000..d91033f
4421 +++ b/mech_eap/export_name.c
4424 + * Copyright (c) 2011, JANET(UK)
4425 + * All rights reserved.
4427 + * Redistribution and use in source and binary forms, with or without
4428 + * modification, are permitted provided that the following conditions
4431 + * 1. Redistributions of source code must retain the above copyright
4432 + * notice, this list of conditions and the following disclaimer.
4434 + * 2. Redistributions in binary form must reproduce the above copyright
4435 + * notice, this list of conditions and the following disclaimer in the
4436 + * documentation and/or other materials provided with the distribution.
4438 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4439 + * may be used to endorse or promote products derived from this software
4440 + * without specific prior written permission.
4442 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4443 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4444 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4445 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4446 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4447 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4448 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4449 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4450 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4451 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4456 + * Serialise a name.
4459 +#include "gssapiP_eap.h"
4461 +OM_uint32 GSSAPI_CALLCONV
4462 +gss_export_name(OM_uint32 *minor,
4463 + const gss_name_t input_name,
4464 + gss_buffer_t exported_name)
4470 + if (input_name == GSS_C_NO_NAME) {
4472 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4475 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4477 + major = gssEapExportName(minor, input_name, exported_name);
4479 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4483 diff --git a/mech_eap/export_name_composite.c b/mech_eap/export_name_composite.c
4484 new file mode 100644
4485 index 0000000..b2a90ae
4487 +++ b/mech_eap/export_name_composite.c
4490 + * Copyright (c) 2011, JANET(UK)
4491 + * All rights reserved.
4493 + * Redistribution and use in source and binary forms, with or without
4494 + * modification, are permitted provided that the following conditions
4497 + * 1. Redistributions of source code must retain the above copyright
4498 + * notice, this list of conditions and the following disclaimer.
4500 + * 2. Redistributions in binary form must reproduce the above copyright
4501 + * notice, this list of conditions and the following disclaimer in the
4502 + * documentation and/or other materials provided with the distribution.
4504 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4505 + * may be used to endorse or promote products derived from this software
4506 + * without specific prior written permission.
4508 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4509 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4510 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4511 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4512 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4513 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4514 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4515 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4516 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4517 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4522 + * Serialise a name and its attributes.
4525 +#include "gssapiP_eap.h"
4527 +OM_uint32 GSSAPI_CALLCONV
4528 +gss_export_name_composite(OM_uint32 *minor,
4529 + gss_name_t input_name,
4530 + gss_buffer_t exported_name)
4536 + if (input_name == GSS_C_NO_NAME) {
4538 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4541 + GSSEAP_MUTEX_LOCK(&input_name->mutex);
4543 + major = gssEapExportNameInternal(minor, input_name, exported_name,
4544 + EXPORT_NAME_FLAG_OID |
4545 + EXPORT_NAME_FLAG_COMPOSITE);
4547 + GSSEAP_MUTEX_UNLOCK(&input_name->mutex);
4551 diff --git a/mech_eap/export_sec_context.c b/mech_eap/export_sec_context.c
4552 new file mode 100644
4553 index 0000000..e5be6d8
4555 +++ b/mech_eap/export_sec_context.c
4558 + * Copyright (c) 2011, JANET(UK)
4559 + * All rights reserved.
4561 + * Redistribution and use in source and binary forms, with or without
4562 + * modification, are permitted provided that the following conditions
4565 + * 1. Redistributions of source code must retain the above copyright
4566 + * notice, this list of conditions and the following disclaimer.
4568 + * 2. Redistributions in binary form must reproduce the above copyright
4569 + * notice, this list of conditions and the following disclaimer in the
4570 + * documentation and/or other materials provided with the distribution.
4572 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4573 + * may be used to endorse or promote products derived from this software
4574 + * without specific prior written permission.
4576 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4577 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4578 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4579 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4580 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4581 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4582 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4583 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4584 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4585 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4590 + * Serialise a security context. On the acceptor, this may be partially
4594 +#include "gssapiP_eap.h"
4596 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4598 +gssEapExportPartialContext(OM_uint32 *minor,
4600 + gss_buffer_t token)
4602 + OM_uint32 major, tmpMinor;
4603 + size_t length, serverLen = 0;
4605 + char serverBuf[MAXHOSTNAMELEN];
4606 + if (ctx->acceptorCtx.radConn != NULL) {
4607 + if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
4608 + serverBuf, sizeof(serverBuf)) != 0) {
4610 + return gssEapRadiusMapError(minor,
4611 + rs_err_conn_pop(ctx->acceptorCtx.radConn));
4613 + serverBuf[0] = '\0'; /* not implemented yet */
4616 + serverLen = strlen(serverBuf);
4618 + length = 4 + serverLen + 4 + ctx->acceptorCtx.state.length;
4620 + token->value = GSSEAP_MALLOC(length);
4621 + if (token->value == NULL) {
4622 + major = GSS_S_FAILURE;
4626 + token->length = length;
4628 + p = (unsigned char *)token->value;
4630 + store_uint32_be(serverLen, p);
4632 + if (serverLen != 0) {
4633 + memcpy(p, serverBuf, serverLen);
4637 + store_uint32_be(ctx->acceptorCtx.state.length, p);
4639 + if (ctx->acceptorCtx.state.length != 0) {
4640 + memcpy(p, ctx->acceptorCtx.state.value,
4641 + ctx->acceptorCtx.state.length);
4642 + p += ctx->acceptorCtx.state.length;
4645 + GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
4647 + major = GSS_S_COMPLETE;
4651 + if (GSS_ERROR(major))
4652 + gss_release_buffer(&tmpMinor, token);
4656 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
4659 +gssEapExportSecContext(OM_uint32 *minor,
4661 + gss_buffer_t token)
4663 + OM_uint32 major, tmpMinor;
4665 + gss_buffer_desc initiatorName = GSS_C_EMPTY_BUFFER;
4666 + gss_buffer_desc acceptorName = GSS_C_EMPTY_BUFFER;
4667 + gss_buffer_desc partialCtx = GSS_C_EMPTY_BUFFER;
4668 + gss_buffer_desc key;
4671 + if ((CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx)) ||
4672 + ctx->mechanismUsed == GSS_C_NO_OID) {
4673 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
4674 + return GSS_S_NO_CONTEXT;
4677 + key.length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
4678 + key.value = KRB_KEY_DATA(&ctx->rfc3961Key);
4680 + if (ctx->initiatorName != GSS_C_NO_NAME) {
4681 + major = gssEapExportNameInternal(minor, ctx->initiatorName,
4683 + EXPORT_NAME_FLAG_COMPOSITE);
4684 + if (GSS_ERROR(major))
4688 + if (ctx->acceptorName != GSS_C_NO_NAME) {
4689 + major = gssEapExportNameInternal(minor, ctx->acceptorName,
4691 + EXPORT_NAME_FLAG_COMPOSITE);
4692 + if (GSS_ERROR(major))
4696 +#ifdef GSSEAP_ENABLE_ACCEPTOR
4698 + * The partial context is only transmitted for unestablished acceptor
4701 + if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
4702 + (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
4703 + major = gssEapExportPartialContext(minor, ctx, &partialCtx);
4704 + if (GSS_ERROR(major))
4709 + length = 16; /* version, state, flags, */
4710 + length += 4 + ctx->mechanismUsed->length; /* mechanismUsed */
4711 + length += 12 + key.length; /* rfc3961Key.value */
4712 + length += 4 + initiatorName.length; /* initiatorName.value */
4713 + length += 4 + acceptorName.length; /* acceptorName.value */
4714 + length += 24 + sequenceSize(ctx->seqState); /* seqState */
4716 + if (partialCtx.value != NULL)
4717 + length += 4 + partialCtx.length; /* partialCtx.value */
4719 + token->value = GSSEAP_MALLOC(length);
4720 + if (token->value == NULL) {
4721 + major = GSS_S_FAILURE;
4725 + token->length = length;
4727 + p = (unsigned char *)token->value;
4729 + store_uint32_be(EAP_EXPORT_CONTEXT_V1, &p[0]); /* version */
4730 + store_uint32_be(GSSEAP_SM_STATE(ctx), &p[4]);
4731 + store_uint32_be(ctx->flags, &p[8]);
4732 + store_uint32_be(ctx->gssFlags, &p[12]);
4733 + p = store_oid(ctx->mechanismUsed, &p[16]);
4735 + store_uint32_be(ctx->checksumType, &p[0]);
4736 + store_uint32_be(ctx->encryptionType, &p[4]);
4737 + p = store_buffer(&key, &p[8], FALSE);
4739 + p = store_buffer(&initiatorName, p, FALSE);
4740 + p = store_buffer(&acceptorName, p, FALSE);
4742 + store_uint64_be(ctx->expiryTime, &p[0]);
4743 + store_uint64_be(ctx->sendSeq, &p[8]);
4744 + store_uint64_be(ctx->recvSeq, &p[16]);
4747 + major = sequenceExternalize(minor, ctx->seqState, &p, &length);
4748 + if (GSS_ERROR(major))
4751 + if (partialCtx.value != NULL)
4752 + p = store_buffer(&partialCtx, p, FALSE);
4754 + GSSEAP_ASSERT(p == (unsigned char *)token->value + token->length);
4756 + major = GSS_S_COMPLETE;
4760 + if (GSS_ERROR(major))
4761 + gss_release_buffer(&tmpMinor, token);
4762 + gss_release_buffer(&tmpMinor, &initiatorName);
4763 + gss_release_buffer(&tmpMinor, &acceptorName);
4764 + gss_release_buffer(&tmpMinor, &partialCtx);
4769 +OM_uint32 GSSAPI_CALLCONV
4770 +gss_export_sec_context(OM_uint32 *minor,
4771 + gss_ctx_id_t *context_handle,
4772 + gss_buffer_t interprocess_token)
4774 + OM_uint32 major, tmpMinor;
4775 + gss_ctx_id_t ctx = *context_handle;
4777 + interprocess_token->length = 0;
4778 + interprocess_token->value = NULL;
4780 + if (ctx == GSS_C_NO_CONTEXT) {
4782 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
4787 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4789 + major = gssEapExportSecContext(minor, ctx, interprocess_token);
4790 + if (GSS_ERROR(major)) {
4791 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4795 + *context_handle = GSS_C_NO_CONTEXT;
4797 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4799 + gssEapReleaseContext(&tmpMinor, &ctx);
4801 + return GSS_S_COMPLETE;
4803 diff --git a/mech_eap/get_mic.c b/mech_eap/get_mic.c
4804 new file mode 100644
4805 index 0000000..7161e9c
4807 +++ b/mech_eap/get_mic.c
4810 + * Copyright (c) 2011, JANET(UK)
4811 + * All rights reserved.
4813 + * Redistribution and use in source and binary forms, with or without
4814 + * modification, are permitted provided that the following conditions
4817 + * 1. Redistributions of source code must retain the above copyright
4818 + * notice, this list of conditions and the following disclaimer.
4820 + * 2. Redistributions in binary form must reproduce the above copyright
4821 + * notice, this list of conditions and the following disclaimer in the
4822 + * documentation and/or other materials provided with the distribution.
4824 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4825 + * may be used to endorse or promote products derived from this software
4826 + * without specific prior written permission.
4828 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4829 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4830 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4831 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4832 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4833 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4834 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4835 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4836 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4837 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4842 + * Message protection services: make a message integerity check.
4845 +#include "gssapiP_eap.h"
4847 +OM_uint32 GSSAPI_CALLCONV
4848 +gss_get_mic(OM_uint32 *minor,
4850 + gss_qop_t qop_req,
4851 + gss_buffer_t message_buffer,
4852 + gss_buffer_t message_token)
4855 + gss_iov_buffer_desc iov[2];
4857 + if (ctx == GSS_C_NO_CONTEXT) {
4859 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
4862 + if (qop_req != GSS_C_QOP_DEFAULT) {
4863 + *minor = GSSEAP_UNKNOWN_QOP;
4864 + return GSS_S_UNAVAILABLE;
4869 + message_token->value = NULL;
4870 + message_token->length = 0;
4872 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
4874 + if (!CTX_IS_ESTABLISHED(ctx)) {
4875 + major = GSS_S_NO_CONTEXT;
4876 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
4880 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
4881 + iov[0].buffer = *message_buffer;
4883 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
4884 + iov[1].buffer.value = NULL;
4885 + iov[1].buffer.length = 0;
4887 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL, iov, 2, TOK_TYPE_MIC);
4888 + if (GSS_ERROR(major))
4891 + *message_token = iov[1].buffer;
4894 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
4898 diff --git a/mech_eap/get_name_attribute.c b/mech_eap/get_name_attribute.c
4899 new file mode 100644
4900 index 0000000..a885823
4902 +++ b/mech_eap/get_name_attribute.c
4905 + * Copyright (c) 2011, JANET(UK)
4906 + * All rights reserved.
4908 + * Redistribution and use in source and binary forms, with or without
4909 + * modification, are permitted provided that the following conditions
4912 + * 1. Redistributions of source code must retain the above copyright
4913 + * notice, this list of conditions and the following disclaimer.
4915 + * 2. Redistributions in binary form must reproduce the above copyright
4916 + * notice, this list of conditions and the following disclaimer in the
4917 + * documentation and/or other materials provided with the distribution.
4919 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4920 + * may be used to endorse or promote products derived from this software
4921 + * without specific prior written permission.
4923 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4924 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4925 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4926 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
4927 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4928 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4929 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4930 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4931 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4932 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4936 +#include "gssapiP_eap.h"
4939 + * Wrapper for retrieving a naming attribute.
4942 +OM_uint32 GSSAPI_CALLCONV
4943 +gss_get_name_attribute(OM_uint32 *minor,
4945 + gss_buffer_t attr,
4946 + int *authenticated,
4948 + gss_buffer_t value,
4949 + gss_buffer_t display_value,
4956 + if (name == GSS_C_NO_NAME) {
4958 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
4961 + GSSEAP_MUTEX_LOCK(&name->mutex);
4963 + major = gssEapGetNameAttribute(minor, name, attr,
4964 + authenticated, complete,
4965 + value, display_value, more);
4967 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
4971 diff --git a/mech_eap/gssapiP_eap.h b/mech_eap/gssapiP_eap.h
4972 new file mode 100644
4973 index 0000000..d1790a0
4975 +++ b/mech_eap/gssapiP_eap.h
4978 + * Copyright (c) 2011, JANET(UK)
4979 + * All rights reserved.
4981 + * Redistribution and use in source and binary forms, with or without
4982 + * modification, are permitted provided that the following conditions
4985 + * 1. Redistributions of source code must retain the above copyright
4986 + * notice, this list of conditions and the following disclaimer.
4988 + * 2. Redistributions in binary form must reproduce the above copyright
4989 + * notice, this list of conditions and the following disclaimer in the
4990 + * documentation and/or other materials provided with the distribution.
4992 + * 3. Neither the name of JANET(UK) nor the names of its contributors
4993 + * may be used to endorse or promote products derived from this software
4994 + * without specific prior written permission.
4996 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4997 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4998 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4999 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5000 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5001 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5002 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5003 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5004 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5005 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5009 +#ifndef _GSSAPIP_EAP_H_
5010 +#define _GSSAPIP_EAP_H_ 1
5012 +#include "config.h"
5014 +#ifdef HAVE_HEIMDAL_VERSION
5015 +#define KRB5_DEPRECATED /* so we can use krb5_free_unparsed_name() */
5018 +#include <assert.h>
5019 +#include <string.h>
5021 +#ifdef HAVE_UNISTD_H
5022 +#include <unistd.h>
5024 +#ifdef HAVE_STDLIB_H
5025 +#include <stdlib.h>
5027 +#ifdef HAVE_STDARG_H
5028 +#include <stdarg.h>
5031 +#ifdef HAVE_SYS_PARAM_H
5032 +#include <sys/param.h>
5036 +#ifndef MAXHOSTNAMELEN
5037 +# include <WinSock2.h>
5038 +# define MAXHOSTNAMELEN NI_MAXHOST
5043 +#include <gssapi/gssapi.h>
5044 +#include <gssapi/gssapi_krb5.h>
5045 +#ifdef HAVE_HEIMDAL_VERSION
5046 +typedef struct gss_any *gss_any_t;
5048 +#include <gssapi/gssapi_ext.h>
5050 +#include "gssapi_eap.h"
5052 +#ifndef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
5053 +typedef const gss_OID_desc *gss_const_OID;
5056 +/* Kerberos headers */
5060 +#include <includes.h>
5061 +#include <common.h>
5062 +#include <eap_peer/eap.h>
5063 +#include <eap_peer/eap_config.h>
5064 +#include <eap_peer/eap_methods.h>
5065 +#include <eap_common/eap_common.h>
5066 +#include <wpabuf.h>
5068 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5069 +/* FreeRADIUS headers */
5073 +#define operator fr_operator
5076 +#include <freeradius/libradius.h>
5077 +#include <freeradius/radius.h>
5081 +/* libradsec headers */
5082 +#include <radsec/radsec.h>
5083 +#include <radsec/request.h>
5090 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
5092 +#include "gsseap_err.h"
5093 +#include "radsec_err.h"
5100 +/* These name flags are informative and not actually used by anything yet */
5101 +#define NAME_FLAG_NAI 0x00000001
5102 +#define NAME_FLAG_SERVICE 0x00000002
5103 +#define NAME_FLAG_COMPOSITE 0x00000004
5105 +struct gss_eap_saml_attr_ctx;
5106 +struct gss_eap_attr_ctx;
5108 +#ifdef HAVE_HEIMDAL_VERSION
5109 +struct gss_name_t_desc_struct
5111 +struct gss_name_struct
5114 + GSSEAP_MUTEX mutex; /* mutex protects attrCtx */
5116 + gss_OID mechanismUsed; /* this is immutable */
5117 + krb5_principal krbPrincipal; /* this is immutable */
5118 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5119 + struct gss_eap_attr_ctx *attrCtx;
5123 +#define CRED_FLAG_INITIATE 0x00010000
5124 +#define CRED_FLAG_ACCEPT 0x00020000
5125 +#define CRED_FLAG_PASSWORD 0x00040000
5126 +#define CRED_FLAG_DEFAULT_CCACHE 0x00080000
5127 +#define CRED_FLAG_RESOLVED 0x00100000
5128 +#define CRED_FLAG_TARGET 0x00200000
5129 +#define CRED_FLAG_PUBLIC_MASK 0x0000FFFF
5131 +#ifdef HAVE_HEIMDAL_VERSION
5132 +struct gss_cred_id_t_desc_struct
5134 +struct gss_cred_id_struct
5137 + GSSEAP_MUTEX mutex;
5140 + gss_name_t target; /* for initiator */
5141 + gss_buffer_desc password;
5142 + gss_OID_set mechanisms;
5143 + time_t expiryTime;
5144 + gss_buffer_desc radiusConfigFile;
5145 + gss_buffer_desc radiusConfigStanza;
5146 + gss_buffer_desc caCertificate;
5147 + gss_buffer_desc subjectNameConstraint;
5148 + gss_buffer_desc subjectAltNameConstraint;
5149 +#ifdef GSSEAP_ENABLE_REAUTH
5150 + krb5_ccache krbCredCache;
5151 + gss_cred_id_t reauthCred;
5155 +#define CTX_FLAG_INITIATOR 0x00000001
5156 +#define CTX_FLAG_KRB_REAUTH 0x00000002
5158 +#define CTX_IS_INITIATOR(ctx) (((ctx)->flags & CTX_FLAG_INITIATOR) != 0)
5160 +#define CTX_IS_ESTABLISHED(ctx) ((ctx)->state == GSSEAP_STATE_ESTABLISHED)
5162 +/* Initiator context flags */
5163 +#define CTX_FLAG_EAP_SUCCESS 0x00010000
5164 +#define CTX_FLAG_EAP_RESTART 0x00020000
5165 +#define CTX_FLAG_EAP_FAIL 0x00040000
5166 +#define CTX_FLAG_EAP_RESP 0x00080000
5167 +#define CTX_FLAG_EAP_NO_RESP 0x00100000
5168 +#define CTX_FLAG_EAP_REQ 0x00200000
5169 +#define CTX_FLAG_EAP_PORT_ENABLED 0x00400000
5170 +#define CTX_FLAG_EAP_ALT_ACCEPT 0x00800000
5171 +#define CTX_FLAG_EAP_ALT_REJECT 0x01000000
5172 +#define CTX_FLAG_EAP_MASK 0xFFFF0000
5174 +struct gss_eap_initiator_ctx {
5175 + unsigned int idleWhile;
5176 + struct eap_peer_config eapPeerConfig;
5177 + struct eap_sm *eap;
5178 + struct wpabuf reqData;
5181 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5182 +struct gss_eap_acceptor_ctx {
5183 + struct rs_context *radContext;
5184 + struct rs_connection *radConn;
5186 + gss_buffer_desc state;
5191 +#ifdef HAVE_HEIMDAL_VERSION
5192 +struct gss_ctx_id_t_desc_struct
5194 +struct gss_ctx_id_struct
5197 + GSSEAP_MUTEX mutex;
5198 + enum gss_eap_state state;
5200 + OM_uint32 gssFlags;
5201 + gss_OID mechanismUsed;
5202 + krb5_cksumtype checksumType;
5203 + krb5_enctype encryptionType;
5204 + krb5_keyblock rfc3961Key;
5205 + gss_name_t initiatorName;
5206 + gss_name_t acceptorName;
5207 + time_t expiryTime;
5208 + uint64_t sendSeq, recvSeq;
5210 + gss_cred_id_t cred;
5212 + struct gss_eap_initiator_ctx initiator;
5213 + #define initiatorCtx ctxU.initiator
5214 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5215 + struct gss_eap_acceptor_ctx acceptor;
5216 + #define acceptorCtx ctxU.acceptor
5218 +#ifdef GSSEAP_ENABLE_REAUTH
5219 + gss_ctx_id_t reauth;
5220 + #define reauthCtx ctxU.reauth
5223 + const struct gss_eap_token_buffer_set *inputTokens;
5224 + const struct gss_eap_token_buffer_set *outputTokens;
5227 +#define TOK_FLAG_SENDER_IS_ACCEPTOR 0x01
5228 +#define TOK_FLAG_WRAP_CONFIDENTIAL 0x02
5229 +#define TOK_FLAG_ACCEPTOR_SUBKEY 0x04
5231 +#define KEY_USAGE_ACCEPTOR_SEAL 22
5232 +#define KEY_USAGE_ACCEPTOR_SIGN 23
5233 +#define KEY_USAGE_INITIATOR_SEAL 24
5234 +#define KEY_USAGE_INITIATOR_SIGN 25
5236 +/* accept_sec_context.c */
5238 +gssEapAcceptSecContext(OM_uint32 *minor,
5240 + gss_cred_id_t cred,
5241 + gss_buffer_t input_token,
5242 + gss_channel_bindings_t input_chan_bindings,
5243 + gss_name_t *src_name,
5244 + gss_OID *mech_type,
5245 + gss_buffer_t output_token,
5246 + OM_uint32 *ret_flags,
5247 + OM_uint32 *time_rec,
5248 + gss_cred_id_t *delegated_cred_handle);
5250 +/* init_sec_context.c */
5252 +gssEapInitSecContext(OM_uint32 *minor,
5253 + gss_cred_id_t cred,
5255 + gss_name_t target_name,
5256 + gss_OID mech_type,
5257 + OM_uint32 req_flags,
5258 + OM_uint32 time_req,
5259 + gss_channel_bindings_t input_chan_bindings,
5260 + gss_buffer_t input_token,
5261 + gss_OID *actual_mech_type,
5262 + gss_buffer_t output_token,
5263 + OM_uint32 *ret_flags,
5264 + OM_uint32 *time_rec);
5268 +gssEapWrapOrGetMIC(OM_uint32 *minor,
5270 + int conf_req_flag,
5272 + gss_iov_buffer_desc *iov,
5274 + enum gss_eap_token_type toktype);
5277 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor_status,
5280 + gss_qop_t *qop_state,
5281 + gss_iov_buffer_desc *iov,
5283 + enum gss_eap_token_type toktype);
5286 +gssEapWrapIovLength(OM_uint32 *minor,
5288 + int conf_req_flag,
5289 + gss_qop_t qop_req,
5291 + gss_iov_buffer_desc *iov,
5294 +gssEapWrap(OM_uint32 *minor,
5296 + int conf_req_flag,
5297 + gss_qop_t qop_req,
5298 + gss_buffer_t input_message_buffer,
5300 + gss_buffer_t output_message_buffer);
5303 +rfc4121Flags(gss_ctx_id_t ctx, int receiving);
5305 +/* display_status.c */
5307 +gssEapSaveStatusInfo(OM_uint32 minor, const char *format, ...);
5310 +gssEapDisplayStatus(OM_uint32 *minor,
5311 + OM_uint32 status_value,
5312 + gss_buffer_t status_string);
5314 +#define IS_WIRE_ERROR(err) ((err) > GSSEAP_RESERVED && \
5315 + (err) <= GSSEAP_RADIUS_PROT_FAILURE)
5317 +/* upper bound of RADIUS error range must be kept in sync with radsec.h */
5318 +#define IS_RADIUS_ERROR(err) ((err) >= ERROR_TABLE_BASE_rse && \
5319 + (err) <= ERROR_TABLE_BASE_rse + 20)
5321 +/* exchange_meta_data.c */
5322 +OM_uint32 GSSAPI_CALLCONV
5323 +gssEapExchangeMetaData(OM_uint32 *minor,
5324 + gss_const_OID mech,
5325 + gss_cred_id_t cred,
5326 + gss_ctx_id_t *ctx,
5327 + const gss_name_t name,
5328 + OM_uint32 req_flags,
5329 + gss_const_buffer_t meta_data);
5331 +/* export_sec_context.c */
5333 +gssEapExportSecContext(OM_uint32 *minor,
5335 + gss_buffer_t token);
5337 +/* import_sec_context.c */
5339 +gssEapImportContext(OM_uint32 *minor,
5340 + gss_buffer_t token,
5341 + gss_ctx_id_t ctx);
5343 +/* inquire_sec_context_by_oid.c */
5344 +#define NEGOEX_INITIATOR_SALT "gss-eap-negoex-initiator"
5345 +#define NEGOEX_INITIATOR_SALT_LEN (sizeof(NEGOEX_INITIATOR_SALT) - 1)
5347 +#define NEGOEX_ACCEPTOR_SALT "gss-eap-negoex-acceptor"
5348 +#define NEGOEX_ACCEPTOR_SALT_LEN (sizeof(NEGOEX_ACCEPTOR_SALT) - 1)
5350 +/* pseudo_random.c */
5352 +gssEapPseudoRandom(OM_uint32 *minor,
5355 + const gss_buffer_t prf_in,
5356 + ssize_t desired_output_len,
5357 + gss_buffer_t prf_out);
5359 +/* query_mechanism_info.c */
5361 +gssQueryMechanismInfo(OM_uint32 *minor,
5362 + gss_const_OID mech_oid,
5363 + unsigned char auth_scheme[16]);
5365 +/* query_meta_data.c */
5367 +gssEapQueryMetaData(OM_uint32 *minor,
5368 + gss_const_OID mech GSSEAP_UNUSED,
5369 + gss_cred_id_t cred,
5370 + gss_ctx_id_t *context_handle,
5371 + const gss_name_t name,
5372 + OM_uint32 req_flags GSSEAP_UNUSED,
5373 + gss_buffer_t meta_data);
5377 +gssEapInitiatorInit(OM_uint32 *minor);
5380 +gssEapFinalize(void);
5386 +#endif /* _GSSAPIP_EAP_H_ */
5387 diff --git a/mech_eap/gssapi_eap.h b/mech_eap/gssapi_eap.h
5388 new file mode 100644
5389 index 0000000..588665b
5391 +++ b/mech_eap/gssapi_eap.h
5394 + * Copyright (c) 2011, JANET(UK)
5395 + * All rights reserved.
5397 + * Redistribution and use in source and binary forms, with or without
5398 + * modification, are permitted provided that the following conditions
5401 + * 1. Redistributions of source code must retain the above copyright
5402 + * notice, this list of conditions and the following disclaimer.
5404 + * 2. Redistributions in binary form must reproduce the above copyright
5405 + * notice, this list of conditions and the following disclaimer in the
5406 + * documentation and/or other materials provided with the distribution.
5408 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5409 + * may be used to endorse or promote products derived from this software
5410 + * without specific prior written permission.
5412 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5413 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5414 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5415 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5416 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5417 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5418 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5419 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5420 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5421 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5425 +#ifndef _GSSAPI_EAP_H_
5426 +#define _GSSAPI_EAP_H_ 1
5428 +#include <gssapi/gssapi.h>
5432 +#endif /* __cplusplus */
5435 + * GSS EAP mechanism OIDs.
5437 +extern gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM;
5438 +extern gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM;
5441 + * Mechanism name OID.
5443 +extern gss_OID GSS_EAP_NT_EAP_NAME;
5446 + * The libradsec configuration file; defaults to radsec.conf
5447 + * in the system configuration directory if unspecified.
5449 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE;
5452 + * The stanza in the libradsec configuration file; defaults
5453 + * to "gss-eap" if unspecified.
5455 +extern gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA;
5458 + * Flags as a 32-bit integer in network byte order,
5459 + * followed by a boolean octet indicating whether to
5460 + * clear the specified flags (if absent, defaults to
5461 + * FALSE, ie. set flags).
5463 +extern gss_OID GSS_EAP_CRED_SET_CRED_FLAG;
5466 + * Password; for mechanism glues that do not support
5467 + * gss_acquire_cred_with_password(), this can be set
5468 + * on an existing credentials handle.
5470 +extern gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD;
5473 + * Credentials flag indicating the local attributes
5474 + * processing should be skipped.
5476 +#define GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG 0x00000001
5480 +#endif /* __cplusplus */
5482 +#endif /* _GSSAPI_EAP_H_ */
5483 diff --git a/mech_eap/gsseap_err.et b/mech_eap/gsseap_err.et
5484 new file mode 100644
5485 index 0000000..d60c2c7
5487 +++ b/mech_eap/gsseap_err.et
5490 +# Copyright (c) 2011, JANET(UK)
5491 +# All rights reserved.
5493 +# Redistribution and use in source and binary forms, with or without
5494 +# modification, are permitted provided that the following conditions
5497 +# 1. Redistributions of source code must retain the above copyright
5498 +# notice, this list of conditions and the following disclaimer.
5500 +# 2. Redistributions in binary form must reproduce the above copyright
5501 +# notice, this list of conditions and the following disclaimer in the
5502 +# documentation and/or other materials provided with the distribution.
5504 +# 3. Neither the name of JANET(UK) nor the names of its contributors
5505 +# may be used to endorse or promote products derived from this software
5506 +# without specific prior written permission.
5508 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5509 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5510 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5511 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5512 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5513 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5514 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5515 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5516 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5517 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5524 +# Protocol errors that can be returned in an error token. This should match
5525 +# up with makeErrorToken in accept_sec_context.c.
5527 +error_code GSSEAP_RESERVED, ""
5528 +error_code GSSEAP_WRONG_SIZE, "Buffer is incorrect size"
5529 +error_code GSSEAP_WRONG_MECH, "Mechanism OID is incorrect"
5530 +error_code GSSEAP_BAD_TOK_HEADER, "Token header is malformed or corrupt"
5531 +error_code GSSEAP_TOK_TRUNC, "Token is missing data"
5532 +error_code GSSEAP_BAD_DIRECTION, "Packet was replayed in wrong direction"
5533 +error_code GSSEAP_WRONG_TOK_ID, "Received token ID does not match expected token ID"
5534 +error_code GSSEAP_CRIT_ITOK_UNAVAILABLE, "Critical inner token type unavailable"
5535 +error_code GSSEAP_MISSING_REQUIRED_ITOK, "Missing required inner token"
5536 +error_code GSSEAP_DUPLICATE_ITOK, "Duplicate inner token received"
5537 +error_code GSSEAP_WRONG_ITOK, "Recieved invalid inner token for current state"
5538 +error_code GSSEAP_KEY_UNAVAILABLE, "EAP key unavailable"
5539 +error_code GSSEAP_KEY_TOO_SHORT, "EAP key too short"
5540 +error_code GSSEAP_RADIUS_AUTH_FAILURE, "Authentication rejected by RADIUS server"
5541 +error_code GSSEAP_UNKNOWN_RADIUS_CODE, "Received unknown response code from RADIUS server"
5542 +error_code GSSEAP_MISSING_EAP_REQUEST, "RADIUS response is missing EAP request"
5543 +error_code GSSEAP_RADIUS_PROT_FAILURE, "Generic RADIUS failure"
5548 +error_code GSSEAP_CONTEXT_ESTABLISHED, "Context is already fully established"
5549 +error_code GSSEAP_CONTEXT_INCOMPLETE, "Attempt to use incomplete security context"
5550 +error_code GSSEAP_BAD_CONTEXT_TOKEN, "Context token is malformed or corrupt"
5551 +error_code GSSEAP_BAD_ERROR_TOKEN, "Error token is malformed or corrupt"
5552 +error_code GSSEAP_BAD_CONTEXT_OPTION, "Bad context option"
5557 +error_code GSSEAP_BAD_SERVICE_NAME, "Name is not a valid service name"
5558 +error_code GSSEAP_BAD_INITIATOR_NAME, "Initiator identity must be a valid name"
5559 +error_code GSSEAP_NO_HOSTNAME, "Could not determine local host name"
5560 +error_code GSSEAP_NO_ACCEPTOR_NAME, "Could not determine acceptor identity"
5561 +error_code GSSEAP_BAD_NAME_TOKEN, "Name token is malformed or corrupt"
5562 +error_code GSSEAP_NO_LOCAL_MAPPING, "Unable to map name to a local identity"
5565 +# Credential errors
5567 +error_code GSSEAP_BAD_USAGE, "Credential usage type is unknown"
5568 +error_code GSSEAP_CRED_USAGE_MISMATCH, "Credential usage does not match requested usage"
5569 +error_code GSSEAP_CRED_MECH_MISMATCH, "Credential is not usable with this mechanism"
5570 +error_code GSSEAP_CRED_EXPIRED, "Attributes indicate credentials have expired"
5571 +error_code GSSEAP_BAD_CRED_OPTION, "Bad credential option"
5572 +error_code GSSEAP_NO_DEFAULT_IDENTITY, "Default credentials identity unavailable"
5573 +error_code GSSEAP_NO_DEFAULT_CRED, "Missing default password or other credentials"
5574 +error_code GSSEAP_CRED_RESOLVED, "Credential is already fully resolved"
5577 +# Local identity service errors
5579 +error_code GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE, "Unable to start identity service"
5580 +error_code GSSEAP_NO_IDENTITY_SELECTED, "No identity selected"
5581 +error_code GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR, "Identity service installation error"
5582 +error_code GSSEAP_IDENTITY_SERVICE_OS_ERROR, "Identity service OS error"
5583 +error_code GSSEAP_IDENTITY_SERVICE_IPC_ERROR, "Identity service IPC error"
5584 +error_code GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR, "Unknown identity service error"
5587 +# Wrap/unwrap/PRF errors
5589 +error_code GSSEAP_BAD_WRAP_TOKEN, "Bad RFC 4121 wrap or MIC token"
5590 +error_code GSSEAP_MISSING_IOV, "IOV is missing required buffer"
5591 +error_code GSSEAP_BAD_STREAM_IOV, "Stream IOV can only contain a single data buffer"
5592 +error_code GSSEAP_BAD_PADDING_IOV, "Padding IOV is not permitted for RFC 4121 tokens"
5593 +error_code GSSEAP_UNKNOWN_QOP, "Unknown quality of protection specified"
5594 +error_code GSSEAP_INPUT_TOO_LONG, "PRF input too long"
5595 +error_code GSSEAP_BAD_PRF_KEY, "PRF key usage type is unknown"
5600 +error_code GSSEAP_LIBEAP_INIT_FAILURE, "Failed to initialize EAP library"
5601 +error_code GSSEAP_PEER_SM_INIT_FAILURE, "Failed to create EAP state machine"
5602 +error_code GSSEAP_PEER_SM_STEP_FAILURE, "Failed to step EAP state machine"
5603 +error_code GSSEAP_PEER_AUTH_FAILURE, "EAP peer authentication failure"
5604 +error_code GSSEAP_PEER_BAD_MESSAGE, "Received bad EAP message"
5607 +# RadSec initialisation errors
5609 +error_code GSSEAP_RADSEC_INIT_FAILURE, "Failed to initialize RadSec library"
5610 +error_code GSSEAP_RADSEC_CONTEXT_FAILURE, "Failed to create RadSec context"
5615 +error_code GSSEAP_NO_ATTR_CONTEXT, "Name has no attributes"
5616 +error_code GSSEAP_NO_ATTR_PROVIDERS, "Failed to initialize attribute providers"
5617 +error_code GSSEAP_NO_SUCH_ATTR, "Unknown naming attribute"
5618 +error_code GSSEAP_BAD_ATTR_TOKEN, "Serialised attributes are malformed or corrupt"
5619 +error_code GSSEAP_ATTR_CONTEXT_FAILURE, "Failed to initialize attribute context"
5624 +error_code GSSEAP_SAML_INIT_FAILURE, "Failed to initialize SAML library"
5625 +error_code GSSEAP_SAML_SEC_POLICY_FAILURE, "Failed to process SAML security policy"
5626 +error_code GSSEAP_SAML_BINDING_FAILURE, "Failed in SAML binding processing"
5627 +error_code GSSEAP_SAML_PROFILE_FAILURE, "Failed to process SAML profile"
5628 +error_code GSSEAP_SAML_FATAL_PROFILE_FAILURE, "Non-recoverable failure in SAML profile processing"
5629 +error_code GSSEAP_SAML_RETRY_PROFILE_FAILURE, "Temporary failure in SAML profile processing"
5630 +error_code GSSEAP_SAML_METADATA_FAILURE, "Failure related to SAML metadata use"
5633 +# Shibboleth errors
5635 +error_code GSSEAP_SHIB_INIT_FAILURE, "Failed to initialize Shibboleth"
5636 +error_code GSSEAP_SHIB_ATTR_FAILURE, "Failure during local attribute processing"
5637 +error_code GSSEAP_SHIB_ATTR_EXTRACT_FAILURE, "Failed to extract local attributes"
5638 +error_code GSSEAP_SHIB_ATTR_FILTER_FAILURE, "Failed to filter local attributes"
5639 +error_code GSSEAP_SHIB_ATTR_RESOLVE_FAILURE, "Failed to resolve local attributes"
5640 +error_code GSSEAP_SHIB_CONFIG_FAILURE, "Local attribute configuration failure"
5641 +error_code GSSEAP_SHIB_LISTENER_FAILURE, "Failed to communicate with local attribute server"
5646 +error_code GSSEAP_BINDINGS_MISMATCH, "Channel bindings do not match"
5647 +error_code GSSEAP_NO_MECHGLUE_SYMBOL, "Could not find symbol in mechanism glue"
5648 +error_code GSSEAP_BAD_INVOCATION, "Bad mechanism invoke OID"
5651 diff --git a/mech_eap/import_name.c b/mech_eap/import_name.c
5652 new file mode 100644
5653 index 0000000..8049e01
5655 +++ b/mech_eap/import_name.c
5658 + * Copyright (c) 2011, JANET(UK)
5659 + * All rights reserved.
5661 + * Redistribution and use in source and binary forms, with or without
5662 + * modification, are permitted provided that the following conditions
5665 + * 1. Redistributions of source code must retain the above copyright
5666 + * notice, this list of conditions and the following disclaimer.
5668 + * 2. Redistributions in binary form must reproduce the above copyright
5669 + * notice, this list of conditions and the following disclaimer in the
5670 + * documentation and/or other materials provided with the distribution.
5672 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5673 + * may be used to endorse or promote products derived from this software
5674 + * without specific prior written permission.
5676 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5677 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5678 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5679 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5680 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5681 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5682 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5683 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5684 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5685 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5690 + * Deserialise a name.
5693 +#include "gssapiP_eap.h"
5695 +OM_uint32 GSSAPI_CALLCONV
5696 +gss_import_name(OM_uint32 *minor,
5697 + gss_buffer_t import_name_buffer,
5698 + gss_OID input_name_type,
5699 + gss_name_t *output_name)
5701 + return gssEapImportName(minor, import_name_buffer,
5702 + input_name_type, GSS_C_NO_OID, output_name);
5704 diff --git a/mech_eap/import_sec_context.c b/mech_eap/import_sec_context.c
5705 new file mode 100644
5706 index 0000000..1533a16
5708 +++ b/mech_eap/import_sec_context.c
5711 + * Copyright (c) 2011, JANET(UK)
5712 + * All rights reserved.
5714 + * Redistribution and use in source and binary forms, with or without
5715 + * modification, are permitted provided that the following conditions
5718 + * 1. Redistributions of source code must retain the above copyright
5719 + * notice, this list of conditions and the following disclaimer.
5721 + * 2. Redistributions in binary form must reproduce the above copyright
5722 + * notice, this list of conditions and the following disclaimer in the
5723 + * documentation and/or other materials provided with the distribution.
5725 + * 3. Neither the name of JANET(UK) nor the names of its contributors
5726 + * may be used to endorse or promote products derived from this software
5727 + * without specific prior written permission.
5729 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5730 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5731 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5732 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
5733 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5734 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5735 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5736 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5737 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5738 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5743 + * Deserialise a context handle.
5746 +#include "gssapiP_eap.h"
5748 +#define UPDATE_REMAIN(n) do { \
5753 +#define CHECK_REMAIN(n) do { \
5754 + if (remain < (n)) { \
5755 + *minor = GSSEAP_TOK_TRUNC; \
5756 + return GSS_S_DEFECTIVE_TOKEN; \
5760 +#ifdef GSSEAP_ENABLE_ACCEPTOR
5762 +gssEapImportPartialContext(OM_uint32 *minor,
5763 + unsigned char **pBuf,
5768 + unsigned char *p = *pBuf;
5769 + size_t remain = *pRemain;
5770 + gss_buffer_desc buf;
5771 + size_t ctxLength, serverLen;
5773 + /* Length of partial RADIUS context */
5775 + ctxLength = load_uint32_be(p);
5778 + CHECK_REMAIN(ctxLength);
5779 + remain = ctxLength; /* check against partial context length */
5781 + /* Selected RADIUS server */
5783 + serverLen = load_uint32_be(p);
5786 + if (serverLen != 0) {
5787 + CHECK_REMAIN(serverLen);
5789 + ctx->acceptorCtx.radServer = GSSEAP_MALLOC(serverLen + 1);
5790 + if (ctx->acceptorCtx.radServer == NULL) {
5792 + return GSS_S_FAILURE;
5794 + memcpy(ctx->acceptorCtx.radServer, p, serverLen);
5795 + ctx->acceptorCtx.radServer[serverLen] = '\0';
5797 + UPDATE_REMAIN(serverLen);
5800 + /* RADIUS state blob */
5802 + buf.length = load_uint32_be(p);
5805 + if (buf.length != 0) {
5806 + CHECK_REMAIN(buf.length);
5810 + major = duplicateBuffer(minor, &buf, &ctx->acceptorCtx.state);
5811 + if (GSS_ERROR(major))
5814 + UPDATE_REMAIN(buf.length);
5817 +#ifdef GSSEAP_DEBUG
5818 + GSSEAP_ASSERT(remain == 0);
5822 + *pRemain -= 4 + ctxLength;
5824 + return GSS_S_COMPLETE;
5826 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
5829 +importMechanismOid(OM_uint32 *minor,
5830 + unsigned char **pBuf,
5835 + unsigned char *p = *pBuf;
5836 + size_t remain = *pRemain;
5837 + gss_OID_desc oidBuf;
5839 + oidBuf.length = load_uint32_be(p);
5840 + if (remain < 4 + oidBuf.length || oidBuf.length == 0) {
5841 + *minor = GSSEAP_TOK_TRUNC;
5842 + return GSS_S_DEFECTIVE_TOKEN;
5845 + oidBuf.elements = &p[4];
5847 + major = gssEapCanonicalizeOid(minor, &oidBuf, 0, pOid);
5848 + if (GSS_ERROR(major))
5851 + *pBuf += 4 + oidBuf.length;
5852 + *pRemain -= 4 + oidBuf.length;
5855 + return GSS_S_COMPLETE;
5859 +importKerberosKey(OM_uint32 *minor,
5860 + unsigned char **pBuf,
5862 + krb5_cksumtype *checksumType,
5863 + krb5_enctype *pEncryptionType,
5864 + krb5_keyblock *pKey)
5866 + unsigned char *p = *pBuf;
5867 + size_t remain = *pRemain;
5868 + OM_uint32 encryptionType;
5870 + krb5_context krbContext;
5871 + krb5_keyblock key;
5872 + krb5_error_code code;
5874 + GSSEAP_KRB_INIT(&krbContext);
5876 + KRB_KEY_INIT(pKey);
5878 + if (remain < 12) {
5879 + *minor = GSSEAP_TOK_TRUNC;
5880 + return GSS_S_DEFECTIVE_TOKEN;
5883 + *checksumType = load_uint32_be(&p[0]);
5884 + encryptionType = load_uint32_be(&p[4]);
5885 + length = load_uint32_be(&p[8]);
5887 + if ((length != 0) != (encryptionType != ENCTYPE_NULL)) {
5888 + *minor = GSSEAP_BAD_CONTEXT_TOKEN;
5889 + return GSS_S_DEFECTIVE_TOKEN;
5892 + if (remain - 12 < length) {
5893 + *minor = GSSEAP_TOK_TRUNC;
5894 + return GSS_S_DEFECTIVE_TOKEN;
5897 + if (encryptionType != ENCTYPE_NULL) {
5898 + KRB_KEY_INIT(&key);
5900 + KRB_KEY_TYPE(&key) = encryptionType;
5901 + KRB_KEY_LENGTH(&key) = length;
5902 + KRB_KEY_DATA(&key) = &p[12];
5904 + code = krb5_copy_keyblock_contents(krbContext, &key, pKey);
5907 + return GSS_S_FAILURE;
5911 + *pBuf += 12 + length;
5912 + *pRemain -= 12 + length;
5913 + *pEncryptionType = encryptionType;
5916 + return GSS_S_COMPLETE;
5920 +importName(OM_uint32 *minor,
5921 + unsigned char **pBuf,
5923 + gss_name_t *pName)
5926 + unsigned char *p = *pBuf;
5927 + size_t remain = *pRemain;
5928 + gss_buffer_desc tmp;
5931 + *minor = GSSEAP_TOK_TRUNC;
5932 + return GSS_S_DEFECTIVE_TOKEN;
5935 + tmp.length = load_uint32_be(p);
5936 + if (tmp.length != 0) {
5937 + if (remain - 4 < tmp.length) {
5938 + *minor = GSSEAP_TOK_TRUNC;
5939 + return GSS_S_DEFECTIVE_TOKEN;
5942 + tmp.value = p + 4;
5944 + major = gssEapImportNameInternal(minor, &tmp, pName,
5945 + EXPORT_NAME_FLAG_COMPOSITE);
5946 + if (GSS_ERROR(major))
5950 + *pBuf += 4 + tmp.length;
5951 + *pRemain -= 4 + tmp.length;
5954 + return GSS_S_COMPLETE;
5958 +gssEapImportContext(OM_uint32 *minor,
5959 + gss_buffer_t token,
5963 + unsigned char *p = (unsigned char *)token->value;
5964 + size_t remain = token->length;
5966 + if (remain < 16) {
5967 + *minor = GSSEAP_TOK_TRUNC;
5968 + return GSS_S_DEFECTIVE_TOKEN;
5970 + if (load_uint32_be(&p[0]) != EAP_EXPORT_CONTEXT_V1) {
5971 + *minor = GSSEAP_BAD_CONTEXT_TOKEN;
5972 + return GSS_S_DEFECTIVE_TOKEN;
5974 + ctx->state = load_uint32_be(&p[4]);
5975 + ctx->flags = load_uint32_be(&p[8]);
5976 + ctx->gssFlags = load_uint32_be(&p[12]);
5980 + /* Validate state */
5981 + if (GSSEAP_SM_STATE(ctx) < GSSEAP_STATE_INITIAL ||
5982 + GSSEAP_SM_STATE(ctx) > GSSEAP_STATE_ESTABLISHED)
5983 + return GSS_S_DEFECTIVE_TOKEN;
5985 + /* Only acceptor can export partial context tokens */
5986 + if (CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx))
5987 + return GSS_S_DEFECTIVE_TOKEN;
5989 + major = importMechanismOid(minor, &p, &remain, &ctx->mechanismUsed);
5990 + if (GSS_ERROR(major))
5993 + major = importKerberosKey(minor, &p, &remain,
5994 + &ctx->checksumType,
5995 + &ctx->encryptionType,
5996 + &ctx->rfc3961Key);
5997 + if (GSS_ERROR(major))
6000 + major = importName(minor, &p, &remain, &ctx->initiatorName);
6001 + if (GSS_ERROR(major))
6004 + major = importName(minor, &p, &remain, &ctx->acceptorName);
6005 + if (GSS_ERROR(major))
6008 + /* Check that, if context is established, names are valid */
6009 + if (CTX_IS_ESTABLISHED(ctx) &&
6010 + (CTX_IS_INITIATOR(ctx) ? ctx->acceptorName == GSS_C_NO_NAME
6011 + : ctx->initiatorName == GSS_C_NO_NAME)) {
6012 + return GSS_S_DEFECTIVE_TOKEN;
6015 + if (remain < 24 + sequenceSize(ctx->seqState)) {
6016 + *minor = GSSEAP_TOK_TRUNC;
6017 + return GSS_S_DEFECTIVE_TOKEN;
6019 + ctx->expiryTime = (time_t)load_uint64_be(&p[0]);
6020 + ctx->sendSeq = load_uint64_be(&p[8]);
6021 + ctx->recvSeq = load_uint64_be(&p[16]);
6025 + major = sequenceInternalize(minor, &ctx->seqState, &p, &remain);
6026 + if (GSS_ERROR(major))
6029 +#ifdef GSSEAP_ENABLE_ACCEPTOR
6031 + * The partial context should only be expected for unestablished
6032 + * acceptor contexts.
6034 + if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
6035 + (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
6036 + major = gssEapImportPartialContext(minor, &p, &remain, ctx);
6037 + if (GSS_ERROR(major))
6041 +#ifdef GSSEAP_DEBUG
6042 + GSSEAP_ASSERT(remain == 0);
6044 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
6046 + major = GSS_S_COMPLETE;
6052 +OM_uint32 GSSAPI_CALLCONV
6053 +gss_import_sec_context(OM_uint32 *minor,
6054 + gss_buffer_t interprocess_token,
6055 + gss_ctx_id_t *context_handle)
6057 + OM_uint32 major, tmpMinor;
6058 + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
6060 + *context_handle = GSS_C_NO_CONTEXT;
6062 + if (interprocess_token == GSS_C_NO_BUFFER ||
6063 + interprocess_token->length == 0) {
6064 + *minor = GSSEAP_TOK_TRUNC;
6065 + return GSS_S_DEFECTIVE_TOKEN;
6068 + major = gssEapAllocContext(minor, &ctx);
6069 + if (GSS_ERROR(major))
6072 + major = gssEapImportContext(minor, interprocess_token, ctx);
6073 + if (GSS_ERROR(major))
6076 + *context_handle = ctx;
6079 + if (GSS_ERROR(major))
6080 + gssEapReleaseContext(&tmpMinor, &ctx);
6084 diff --git a/mech_eap/indicate_mechs.c b/mech_eap/indicate_mechs.c
6085 new file mode 100644
6086 index 0000000..d4d275e
6088 +++ b/mech_eap/indicate_mechs.c
6091 + * Copyright (c) 2011, JANET(UK)
6092 + * All rights reserved.
6094 + * Redistribution and use in source and binary forms, with or without
6095 + * modification, are permitted provided that the following conditions
6098 + * 1. Redistributions of source code must retain the above copyright
6099 + * notice, this list of conditions and the following disclaimer.
6101 + * 2. Redistributions in binary form must reproduce the above copyright
6102 + * notice, this list of conditions and the following disclaimer in the
6103 + * documentation and/or other materials provided with the distribution.
6105 + * 3. Neither the name of JANET(UK) nor the names of its contributors
6106 + * may be used to endorse or promote products derived from this software
6107 + * without specific prior written permission.
6109 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6110 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6111 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6112 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
6113 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6114 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6115 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6116 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6117 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6118 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6123 + * Enumerate the supported mechanism OIDs.
6126 +#include "gssapiP_eap.h"
6128 +OM_uint32 GSSAPI_CALLCONV
6129 +gss_indicate_mechs(OM_uint32 *minor,
6130 + gss_OID_set *mech_set)
6132 + return gssEapIndicateMechs(minor, mech_set);
6134 diff --git a/mech_eap/init_sec_context.c b/mech_eap/init_sec_context.c
6135 new file mode 100644
6136 index 0000000..e99b479
6138 +++ b/mech_eap/init_sec_context.c
6141 + * Copyright (c) 2011, JANET(UK)
6142 + * All rights reserved.
6144 + * Redistribution and use in source and binary forms, with or without
6145 + * modification, are permitted provided that the following conditions
6148 + * 1. Redistributions of source code must retain the above copyright
6149 + * notice, this list of conditions and the following disclaimer.
6151 + * 2. Redistributions in binary form must reproduce the above copyright
6152 + * notice, this list of conditions and the following disclaimer in the
6153 + * documentation and/or other materials provided with the distribution.
6155 + * 3. Neither the name of JANET(UK) nor the names of its contributors
6156 + * may be used to endorse or promote products derived from this software
6157 + * without specific prior written permission.
6159 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6160 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6161 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6162 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
6163 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6164 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6165 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6166 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6167 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6168 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6173 + * Establish a security context on the initiator (client). These functions
6174 + * wrap around libeap.
6177 +#include "gssapiP_eap.h"
6180 +policyVariableToFlag(enum eapol_bool_var variable)
6182 + OM_uint32 flag = 0;
6184 + switch (variable) {
6185 + case EAPOL_eapSuccess:
6186 + flag = CTX_FLAG_EAP_SUCCESS;
6188 + case EAPOL_eapRestart:
6189 + flag = CTX_FLAG_EAP_RESTART;
6191 + case EAPOL_eapFail:
6192 + flag = CTX_FLAG_EAP_FAIL;
6194 + case EAPOL_eapResp:
6195 + flag = CTX_FLAG_EAP_RESP;
6197 + case EAPOL_eapNoResp:
6198 + flag = CTX_FLAG_EAP_NO_RESP;
6200 + case EAPOL_eapReq:
6201 + flag = CTX_FLAG_EAP_REQ;
6203 + case EAPOL_portEnabled:
6204 + flag = CTX_FLAG_EAP_PORT_ENABLED;
6206 + case EAPOL_altAccept:
6207 + flag = CTX_FLAG_EAP_ALT_ACCEPT;
6209 + case EAPOL_altReject:
6210 + flag = CTX_FLAG_EAP_ALT_REJECT;
6217 +static struct eap_peer_config *
6218 +peerGetConfig(void *ctx)
6220 + gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
6222 + return &gssCtx->initiatorCtx.eapPeerConfig;
6226 +peerGetBool(void *data, enum eapol_bool_var variable)
6228 + gss_ctx_id_t ctx = data;
6231 + if (ctx == GSS_C_NO_CONTEXT)
6234 + flag = policyVariableToFlag(variable);
6236 + return ((ctx->flags & flag) != 0);
6240 +peerSetBool(void *data, enum eapol_bool_var variable,
6243 + gss_ctx_id_t ctx = data;
6246 + if (ctx == GSS_C_NO_CONTEXT)
6249 + flag = policyVariableToFlag(variable);
6252 + ctx->flags |= flag;
6254 + ctx->flags &= ~(flag);
6257 +static unsigned int
6258 +peerGetInt(void *data, enum eapol_int_var variable)
6260 + gss_ctx_id_t ctx = data;
6262 + if (ctx == GSS_C_NO_CONTEXT)
6265 + GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
6267 + switch (variable) {
6268 + case EAPOL_idleWhile:
6269 + return ctx->initiatorCtx.idleWhile;
6277 +peerSetInt(void *data, enum eapol_int_var variable,
6278 + unsigned int value)
6280 + gss_ctx_id_t ctx = data;
6282 + if (ctx == GSS_C_NO_CONTEXT)
6285 + GSSEAP_ASSERT(CTX_IS_INITIATOR(ctx));
6287 + switch (variable) {
6288 + case EAPOL_idleWhile:
6289 + ctx->initiatorCtx.idleWhile = value;
6294 +static struct wpabuf *
6295 +peerGetEapReqData(void *ctx)
6297 + gss_ctx_id_t gssCtx = (gss_ctx_id_t)ctx;
6299 + return &gssCtx->initiatorCtx.reqData;
6303 +peerSetConfigBlob(void *ctx GSSEAP_UNUSED,
6304 + struct wpa_config_blob *blob GSSEAP_UNUSED)
6308 +static const struct wpa_config_blob *
6309 +peerGetConfigBlob(void *ctx GSSEAP_UNUSED,
6310 + const char *name GSSEAP_UNUSED)
6316 +peerNotifyPending(void *ctx GSSEAP_UNUSED)
6320 +static struct eapol_callbacks gssEapPolicyCallbacks = {
6326 + peerGetEapReqData,
6327 + peerSetConfigBlob,
6328 + peerGetConfigBlob,
6329 + peerNotifyPending,
6332 +#ifdef GSSEAP_DEBUG
6333 +extern int wpa_debug_level;
6337 +peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
6340 + krb5_context krbContext;
6341 + struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
6342 + gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
6343 + gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
6344 + gss_cred_id_t cred = ctx->cred;
6346 + eapPeerConfig->identity = NULL;
6347 + eapPeerConfig->identity_len = 0;
6348 + eapPeerConfig->anonymous_identity = NULL;
6349 + eapPeerConfig->anonymous_identity_len = 0;
6350 + eapPeerConfig->password = NULL;
6351 + eapPeerConfig->password_len = 0;
6353 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6355 + GSSEAP_KRB_INIT(&krbContext);
6357 + eapPeerConfig->fragment_size = 1024;
6358 +#ifdef GSSEAP_DEBUG
6359 + wpa_debug_level = 0;
6362 + GSSEAP_ASSERT(cred->name != GSS_C_NO_NAME);
6364 + if ((cred->name->flags & (NAME_FLAG_NAI | NAME_FLAG_SERVICE)) == 0) {
6365 + *minor = GSSEAP_BAD_INITIATOR_NAME;
6366 + return GSS_S_BAD_NAME;
6370 + major = gssEapDisplayName(minor, cred->name, &identity, NULL);
6371 + if (GSS_ERROR(major))
6374 + eapPeerConfig->identity = (unsigned char *)identity.value;
6375 + eapPeerConfig->identity_len = identity.length;
6377 + krbPrincRealmToGssBuffer(cred->name->krbPrincipal, &realm);
6379 + /* anonymous_identity */
6380 + eapPeerConfig->anonymous_identity = GSSEAP_MALLOC(realm.length + 2);
6381 + if (eapPeerConfig->anonymous_identity == NULL) {
6383 + return GSS_S_FAILURE;
6386 + eapPeerConfig->anonymous_identity[0] = '@';
6387 + memcpy(eapPeerConfig->anonymous_identity + 1, realm.value, realm.length);
6388 + eapPeerConfig->anonymous_identity[1 + realm.length] = '\0';
6389 + eapPeerConfig->anonymous_identity_len = 1 + realm.length;
6392 + eapPeerConfig->password = (unsigned char *)cred->password.value;
6393 + eapPeerConfig->password_len = cred->password.length;
6396 + eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
6397 + eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
6398 + eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
6401 + return GSS_S_COMPLETE;
6405 +peerConfigFree(OM_uint32 *minor,
6408 + struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
6410 + if (eapPeerConfig->identity != NULL) {
6411 + GSSEAP_FREE(eapPeerConfig->identity);
6412 + eapPeerConfig->identity = NULL;
6413 + eapPeerConfig->identity_len = 0;
6416 + if (eapPeerConfig->anonymous_identity != NULL) {
6417 + GSSEAP_FREE(eapPeerConfig->anonymous_identity);
6418 + eapPeerConfig->anonymous_identity = NULL;
6419 + eapPeerConfig->anonymous_identity_len = 0;
6423 + return GSS_S_COMPLETE;
6427 + * Mark an initiator context as ready for cryptographic operations
6430 +initReady(OM_uint32 *minor, gss_ctx_id_t ctx, OM_uint32 reqFlags)
6433 + const unsigned char *key;
6437 + /* XXX actually check for mutual auth */
6438 + if (reqFlags & GSS_C_MUTUAL_FLAG)
6439 + ctx->gssFlags |= GSS_C_MUTUAL_FLAG;
6442 + /* Cache encryption type derived from selected mechanism OID */
6443 + major = gssEapOidToEnctype(minor, ctx->mechanismUsed, &ctx->encryptionType);
6444 + if (GSS_ERROR(major))
6447 + if (!eap_key_available(ctx->initiatorCtx.eap)) {
6448 + *minor = GSSEAP_KEY_UNAVAILABLE;
6449 + return GSS_S_UNAVAILABLE;
6452 + key = eap_get_eapKeyData(ctx->initiatorCtx.eap, &keyLength);
6454 + if (keyLength < EAP_EMSK_LEN) {
6455 + *minor = GSSEAP_KEY_TOO_SHORT;
6456 + return GSS_S_UNAVAILABLE;
6459 + major = gssEapDeriveRfc3961Key(minor,
6460 + &key[EAP_EMSK_LEN / 2],
6462 + ctx->encryptionType,
6463 + &ctx->rfc3961Key);
6464 + if (GSS_ERROR(major))
6467 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
6468 + &ctx->checksumType);
6469 + if (GSS_ERROR(major))
6472 + major = sequenceInit(minor,
6475 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
6476 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
6478 + if (GSS_ERROR(major))
6482 + return GSS_S_COMPLETE;
6486 +initBegin(OM_uint32 *minor,
6488 + gss_name_t target,
6490 + OM_uint32 reqFlags GSSEAP_UNUSED,
6491 + OM_uint32 timeReq,
6492 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED)
6495 + gss_cred_id_t cred = ctx->cred;
6497 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6499 + if (cred->expiryTime)
6500 + ctx->expiryTime = cred->expiryTime;
6501 + else if (timeReq == 0 || timeReq == GSS_C_INDEFINITE)
6502 + ctx->expiryTime = 0;
6504 + ctx->expiryTime = time(NULL) + timeReq;
6507 + * The credential mutex protects its name, however we need to
6508 + * explicitly lock the acceptor name (unlikely as it may be
6509 + * that it has attributes set on it).
6511 + major = gssEapDuplicateName(minor, cred->name, &ctx->initiatorName);
6512 + if (GSS_ERROR(major))
6515 + if (target != GSS_C_NO_NAME) {
6516 + GSSEAP_MUTEX_LOCK(&target->mutex);
6518 + major = gssEapDuplicateName(minor, target, &ctx->acceptorName);
6519 + if (GSS_ERROR(major)) {
6520 + GSSEAP_MUTEX_UNLOCK(&target->mutex);
6524 + GSSEAP_MUTEX_UNLOCK(&target->mutex);
6527 + major = gssEapCanonicalizeOid(minor,
6529 + OID_FLAG_NULL_VALID | OID_FLAG_MAP_NULL_TO_DEFAULT_MECH,
6530 + &ctx->mechanismUsed);
6531 + if (GSS_ERROR(major))
6534 + /* If credentials were provided, check they're usable with this mech */
6535 + if (!gssEapCredAvailable(cred, ctx->mechanismUsed)) {
6536 + *minor = GSSEAP_CRED_MECH_MISMATCH;
6537 + return GSS_S_BAD_MECH;
6541 + return GSS_S_COMPLETE;
6545 +eapGssSmInitError(OM_uint32 *minor,
6546 + gss_cred_id_t cred GSSEAP_UNUSED,
6547 + gss_ctx_id_t ctx GSSEAP_UNUSED,
6548 + gss_name_t target GSSEAP_UNUSED,
6549 + gss_OID mech GSSEAP_UNUSED,
6550 + OM_uint32 reqFlags GSSEAP_UNUSED,
6551 + OM_uint32 timeReq GSSEAP_UNUSED,
6552 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6553 + gss_buffer_t inputToken,
6554 + gss_buffer_t outputToken GSSEAP_UNUSED,
6555 + OM_uint32 *smFlags GSSEAP_UNUSED)
6560 + if (inputToken->length < 8) {
6561 + *minor = GSSEAP_TOK_TRUNC;
6562 + return GSS_S_DEFECTIVE_TOKEN;
6565 + p = (unsigned char *)inputToken->value;
6567 + major = load_uint32_be(&p[0]);
6568 + *minor = ERROR_TABLE_BASE_eapg + load_uint32_be(&p[4]);
6570 + if (!GSS_ERROR(major) || !IS_WIRE_ERROR(*minor)) {
6571 + major = GSS_S_FAILURE;
6572 + *minor = GSSEAP_BAD_ERROR_TOKEN;
6575 + GSSEAP_ASSERT(GSS_ERROR(major));
6580 +#ifdef GSSEAP_ENABLE_REAUTH
6582 +eapGssSmInitGssReauth(OM_uint32 *minor,
6583 + gss_cred_id_t cred,
6585 + gss_name_t target,
6586 + gss_OID mech GSSEAP_UNUSED,
6587 + OM_uint32 reqFlags,
6588 + OM_uint32 timeReq,
6589 + gss_channel_bindings_t chanBindings,
6590 + gss_buffer_t inputToken,
6591 + gss_buffer_t outputToken,
6592 + OM_uint32 *smFlags GSSEAP_UNUSED)
6594 + OM_uint32 major, tmpMinor;
6595 + gss_name_t mechTarget = GSS_C_NO_NAME;
6596 + gss_OID actualMech = GSS_C_NO_OID;
6597 + OM_uint32 gssFlags, timeRec;
6600 + * Here we use the passed in credential handle because the resolved
6601 + * context credential does not currently have the reauth creds.
6603 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL) {
6604 + if (!gssEapCanReauthP(cred, target, timeReq))
6605 + return GSS_S_CONTINUE_NEEDED;
6607 + ctx->flags |= CTX_FLAG_KRB_REAUTH;
6608 + } else if ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
6609 + major = GSS_S_DEFECTIVE_TOKEN;
6610 + *minor = GSSEAP_WRONG_ITOK;
6614 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
6616 + major = gssEapMechToGlueName(minor, target, &mechTarget);
6617 + if (GSS_ERROR(major))
6620 + major = gssInitSecContext(minor,
6624 + (gss_OID)gss_mech_krb5,
6625 + reqFlags | GSS_C_MUTUAL_FLAG,
6633 + if (GSS_ERROR(major))
6636 + ctx->gssFlags = gssFlags;
6638 + if (major == GSS_S_COMPLETE) {
6639 + GSSEAP_ASSERT(GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE);
6641 + major = gssEapReauthComplete(minor, ctx, cred, actualMech, timeRec);
6642 + if (GSS_ERROR(major))
6644 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
6646 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_REAUTHENTICATE);
6650 + gssReleaseName(&tmpMinor, &mechTarget);
6654 +#endif /* GSSEAP_ENABLE_REAUTH */
6656 +#ifdef GSSEAP_DEBUG
6658 +eapGssSmInitVendorInfo(OM_uint32 *minor,
6659 + gss_cred_id_t cred GSSEAP_UNUSED,
6660 + gss_ctx_id_t ctx GSSEAP_UNUSED,
6661 + gss_name_t target GSSEAP_UNUSED,
6662 + gss_OID mech GSSEAP_UNUSED,
6663 + OM_uint32 reqFlags GSSEAP_UNUSED,
6664 + OM_uint32 timeReq GSSEAP_UNUSED,
6665 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6666 + gss_buffer_t inputToken GSSEAP_UNUSED,
6667 + gss_buffer_t outputToken,
6668 + OM_uint32 *smFlags GSSEAP_UNUSED)
6672 + major = makeStringBuffer(minor, "JANET(UK)", outputToken);
6673 + if (GSS_ERROR(major))
6676 + return GSS_S_CONTINUE_NEEDED;
6681 +eapGssSmInitAcceptorName(OM_uint32 *minor,
6682 + gss_cred_id_t cred GSSEAP_UNUSED,
6684 + gss_name_t target GSSEAP_UNUSED,
6685 + gss_OID mech GSSEAP_UNUSED,
6686 + OM_uint32 reqFlags GSSEAP_UNUSED,
6687 + OM_uint32 timeReq GSSEAP_UNUSED,
6688 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6689 + gss_buffer_t inputToken GSSEAP_UNUSED,
6690 + gss_buffer_t outputToken,
6691 + OM_uint32 *smFlags GSSEAP_UNUSED)
6695 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_INITIAL &&
6696 + ctx->acceptorName != GSS_C_NO_NAME) {
6698 + /* Send desired target name to acceptor */
6699 + major = gssEapDisplayName(minor, ctx->acceptorName,
6700 + outputToken, NULL);
6701 + if (GSS_ERROR(major))
6703 + } else if (inputToken != GSS_C_NO_BUFFER &&
6704 + ctx->acceptorName == GSS_C_NO_NAME) {
6705 + /* Accept target name hint from acceptor */
6706 + major = gssEapImportName(minor, inputToken,
6707 + GSS_C_NT_USER_NAME,
6708 + ctx->mechanismUsed,
6709 + &ctx->acceptorName);
6710 + if (GSS_ERROR(major))
6715 + * Currently, other parts of the code assume that the acceptor name
6716 + * is available, hence this check.
6718 + if (ctx->acceptorName == GSS_C_NO_NAME) {
6719 + *minor = GSSEAP_NO_ACCEPTOR_NAME;
6720 + return GSS_S_FAILURE;
6723 + return GSS_S_CONTINUE_NEEDED;
6727 +eapGssSmInitIdentity(OM_uint32 *minor,
6728 + gss_cred_id_t cred GSSEAP_UNUSED,
6730 + gss_name_t target GSSEAP_UNUSED,
6731 + gss_OID mech GSSEAP_UNUSED,
6732 + OM_uint32 reqFlags GSSEAP_UNUSED,
6733 + OM_uint32 timeReq GSSEAP_UNUSED,
6734 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6735 + gss_buffer_t inputToken GSSEAP_UNUSED,
6736 + gss_buffer_t outputToken GSSEAP_UNUSED,
6737 + OM_uint32 *smFlags)
6739 + struct eap_config eapConfig;
6741 +#ifdef GSSEAP_ENABLE_REAUTH
6742 + if (GSSEAP_SM_STATE(ctx) == GSSEAP_STATE_REAUTHENTICATE) {
6743 + OM_uint32 tmpMinor;
6745 + /* server didn't support reauthentication, sent EAP request */
6746 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
6747 + ctx->flags &= ~(CTX_FLAG_KRB_REAUTH);
6748 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_INITIAL);
6751 + *smFlags |= SM_FLAG_FORCE_SEND_TOKEN;
6753 + GSSEAP_ASSERT((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0);
6754 + GSSEAP_ASSERT(inputToken == GSS_C_NO_BUFFER);
6756 + memset(&eapConfig, 0, sizeof(eapConfig));
6758 + ctx->initiatorCtx.eap = eap_peer_sm_init(ctx,
6759 + &gssEapPolicyCallbacks,
6762 + if (ctx->initiatorCtx.eap == NULL) {
6763 + *minor = GSSEAP_PEER_SM_INIT_FAILURE;
6764 + return GSS_S_FAILURE;
6767 + ctx->flags |= CTX_FLAG_EAP_RESTART | CTX_FLAG_EAP_PORT_ENABLED;
6769 + /* poke EAP state machine */
6770 + if (eap_peer_sm_step(ctx->initiatorCtx.eap) != 0) {
6771 + *minor = GSSEAP_PEER_SM_STEP_FAILURE;
6772 + return GSS_S_FAILURE;
6775 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6779 + return GSS_S_CONTINUE_NEEDED;
6783 +eapGssSmInitAuthenticate(OM_uint32 *minor,
6784 + gss_cred_id_t cred GSSEAP_UNUSED,
6786 + gss_name_t target GSSEAP_UNUSED,
6787 + gss_OID mech GSSEAP_UNUSED,
6788 + OM_uint32 reqFlags GSSEAP_UNUSED,
6789 + OM_uint32 timeReq GSSEAP_UNUSED,
6790 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6791 + gss_buffer_t inputToken GSSEAP_UNUSED,
6792 + gss_buffer_t outputToken,
6793 + OM_uint32 *smFlags)
6796 + OM_uint32 tmpMinor;
6797 + struct wpabuf *resp = NULL;
6801 + GSSEAP_ASSERT(inputToken != GSS_C_NO_BUFFER);
6803 + major = peerConfigInit(minor, ctx);
6804 + if (GSS_ERROR(major))
6807 + GSSEAP_ASSERT(ctx->initiatorCtx.eap != NULL);
6808 + GSSEAP_ASSERT(ctx->flags & CTX_FLAG_EAP_PORT_ENABLED);
6810 + ctx->flags |= CTX_FLAG_EAP_REQ; /* we have a Request from the acceptor */
6812 + wpabuf_set(&ctx->initiatorCtx.reqData,
6813 + inputToken->value, inputToken->length);
6815 + major = GSS_S_CONTINUE_NEEDED;
6817 + eap_peer_sm_step(ctx->initiatorCtx.eap);
6818 + if (ctx->flags & CTX_FLAG_EAP_RESP) {
6819 + ctx->flags &= ~(CTX_FLAG_EAP_RESP);
6821 + resp = eap_get_eapRespData(ctx->initiatorCtx.eap);
6822 + } else if (ctx->flags & CTX_FLAG_EAP_SUCCESS) {
6823 + major = initReady(minor, ctx, reqFlags);
6824 + if (GSS_ERROR(major))
6827 + ctx->flags &= ~(CTX_FLAG_EAP_SUCCESS);
6828 + major = GSS_S_CONTINUE_NEEDED;
6829 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6830 + } else if (ctx->flags & CTX_FLAG_EAP_FAIL) {
6831 + major = GSS_S_DEFECTIVE_CREDENTIAL;
6832 + *minor = GSSEAP_PEER_AUTH_FAILURE;
6834 + major = GSS_S_DEFECTIVE_TOKEN;
6835 + *minor = GSSEAP_PEER_BAD_MESSAGE;
6839 + if (resp != NULL) {
6840 + OM_uint32 tmpMajor;
6841 + gss_buffer_desc respBuf;
6843 + GSSEAP_ASSERT(major == GSS_S_CONTINUE_NEEDED);
6845 + respBuf.length = wpabuf_len(resp);
6846 + respBuf.value = (void *)wpabuf_head(resp);
6848 + tmpMajor = duplicateBuffer(&tmpMinor, &respBuf, outputToken);
6849 + if (GSS_ERROR(tmpMajor)) {
6851 + *minor = tmpMinor;
6854 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6857 + wpabuf_set(&ctx->initiatorCtx.reqData, NULL, 0);
6858 + peerConfigFree(&tmpMinor, ctx);
6864 +eapGssSmInitGssFlags(OM_uint32 *minor,
6865 + gss_cred_id_t cred GSSEAP_UNUSED,
6867 + gss_name_t target GSSEAP_UNUSED,
6868 + gss_OID mech GSSEAP_UNUSED,
6869 + OM_uint32 reqFlags GSSEAP_UNUSED,
6870 + OM_uint32 timeReq GSSEAP_UNUSED,
6871 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6872 + gss_buffer_t inputToken GSSEAP_UNUSED,
6873 + gss_buffer_t outputToken,
6874 + OM_uint32 *smFlags GSSEAP_UNUSED)
6876 + unsigned char wireFlags[4];
6877 + gss_buffer_desc flagsBuf;
6879 + store_uint32_be(ctx->gssFlags & GSSEAP_WIRE_FLAGS_MASK, wireFlags);
6881 + flagsBuf.length = sizeof(wireFlags);
6882 + flagsBuf.value = wireFlags;
6884 + return duplicateBuffer(minor, &flagsBuf, outputToken);
6888 +eapGssSmInitGssChannelBindings(OM_uint32 *minor,
6889 + gss_cred_id_t cred GSSEAP_UNUSED,
6891 + gss_name_t target GSSEAP_UNUSED,
6892 + gss_OID mech GSSEAP_UNUSED,
6893 + OM_uint32 reqFlags GSSEAP_UNUSED,
6894 + OM_uint32 timeReq GSSEAP_UNUSED,
6895 + gss_channel_bindings_t chanBindings,
6896 + gss_buffer_t inputToken GSSEAP_UNUSED,
6897 + gss_buffer_t outputToken,
6898 + OM_uint32 *smFlags)
6901 + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
6903 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS)
6904 + buffer = chanBindings->application_data;
6906 + major = gssEapWrap(minor, ctx, TRUE, GSS_C_QOP_DEFAULT,
6907 + &buffer, NULL, outputToken);
6908 + if (GSS_ERROR(major))
6911 + GSSEAP_ASSERT(outputToken->value != NULL);
6914 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6916 + return GSS_S_CONTINUE_NEEDED;
6920 +eapGssSmInitInitiatorMIC(OM_uint32 *minor,
6921 + gss_cred_id_t cred GSSEAP_UNUSED,
6923 + gss_name_t target GSSEAP_UNUSED,
6924 + gss_OID mech GSSEAP_UNUSED,
6925 + OM_uint32 reqFlags GSSEAP_UNUSED,
6926 + OM_uint32 timeReq GSSEAP_UNUSED,
6927 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6928 + gss_buffer_t inputToken GSSEAP_UNUSED,
6929 + gss_buffer_t outputToken,
6930 + OM_uint32 *smFlags)
6934 + major = gssEapMakeTokenMIC(minor, ctx, outputToken);
6935 + if (GSS_ERROR(major))
6938 + GSSEAP_SM_TRANSITION_NEXT(ctx);
6941 + *smFlags |= SM_FLAG_OUTPUT_TOKEN_CRITICAL;
6943 + return GSS_S_CONTINUE_NEEDED;
6946 +#ifdef GSSEAP_ENABLE_REAUTH
6948 +eapGssSmInitReauthCreds(OM_uint32 *minor,
6949 + gss_cred_id_t cred,
6951 + gss_name_t target GSSEAP_UNUSED,
6952 + gss_OID mech GSSEAP_UNUSED,
6953 + OM_uint32 reqFlags GSSEAP_UNUSED,
6954 + OM_uint32 timeReq GSSEAP_UNUSED,
6955 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6956 + gss_buffer_t inputToken,
6957 + gss_buffer_t outputToken GSSEAP_UNUSED,
6958 + OM_uint32 *smFlags GSSEAP_UNUSED)
6962 + if (ctx->gssFlags & GSS_C_MUTUAL_FLAG) {
6963 + major = gssEapStoreReauthCreds(minor, ctx, cred, inputToken);
6964 + if (GSS_ERROR(major))
6969 + return GSS_S_CONTINUE_NEEDED;
6971 +#endif /* GSSEAP_ENABLE_REAUTH */
6974 +eapGssSmInitAcceptorMIC(OM_uint32 *minor,
6975 + gss_cred_id_t cred GSSEAP_UNUSED,
6977 + gss_name_t target GSSEAP_UNUSED,
6978 + gss_OID mech GSSEAP_UNUSED,
6979 + OM_uint32 reqFlags GSSEAP_UNUSED,
6980 + OM_uint32 timeReq GSSEAP_UNUSED,
6981 + gss_channel_bindings_t chanBindings GSSEAP_UNUSED,
6982 + gss_buffer_t inputToken,
6983 + gss_buffer_t outputToken GSSEAP_UNUSED,
6984 + OM_uint32 *smFlags GSSEAP_UNUSED)
6988 + major = gssEapVerifyTokenMIC(minor, ctx, inputToken);
6989 + if (GSS_ERROR(major))
6992 + GSSEAP_SM_TRANSITION(ctx, GSSEAP_STATE_ESTABLISHED);
6996 + return GSS_S_COMPLETE;
6999 +static struct gss_eap_sm eapGssInitiatorSm[] = {
7001 + ITOK_TYPE_CONTEXT_ERR,
7003 + GSSEAP_STATE_ALL & ~(GSSEAP_STATE_INITIAL),
7008 + ITOK_TYPE_ACCEPTOR_NAME_RESP,
7009 + ITOK_TYPE_ACCEPTOR_NAME_REQ,
7010 + GSSEAP_STATE_INITIAL | GSSEAP_STATE_AUTHENTICATE,
7012 + eapGssSmInitAcceptorName
7014 +#ifdef GSSEAP_DEBUG
7017 + ITOK_TYPE_VENDOR_INFO,
7018 + GSSEAP_STATE_INITIAL,
7020 + eapGssSmInitVendorInfo
7023 +#ifdef GSSEAP_ENABLE_REAUTH
7025 + ITOK_TYPE_REAUTH_RESP,
7026 + ITOK_TYPE_REAUTH_REQ,
7027 + GSSEAP_STATE_INITIAL | GSSEAP_STATE_REAUTHENTICATE,
7029 + eapGssSmInitGssReauth
7035 +#ifdef GSSEAP_ENABLE_REAUTH
7036 + GSSEAP_STATE_REAUTHENTICATE |
7038 + GSSEAP_STATE_INITIAL,
7039 + SM_ITOK_FLAG_REQUIRED,
7040 + eapGssSmInitIdentity
7043 + ITOK_TYPE_EAP_REQ,
7044 + ITOK_TYPE_EAP_RESP,
7045 + GSSEAP_STATE_AUTHENTICATE,
7046 + SM_ITOK_FLAG_REQUIRED,
7047 + eapGssSmInitAuthenticate
7051 + ITOK_TYPE_GSS_FLAGS,
7052 + GSSEAP_STATE_INITIATOR_EXTS,
7054 + eapGssSmInitGssFlags
7058 + ITOK_TYPE_GSS_CHANNEL_BINDINGS,
7059 + GSSEAP_STATE_INITIATOR_EXTS,
7060 + SM_ITOK_FLAG_REQUIRED,
7061 + eapGssSmInitGssChannelBindings
7065 + ITOK_TYPE_INITIATOR_MIC,
7066 + GSSEAP_STATE_INITIATOR_EXTS,
7067 + SM_ITOK_FLAG_REQUIRED,
7068 + eapGssSmInitInitiatorMIC
7070 +#ifdef GSSEAP_ENABLE_REAUTH
7072 + ITOK_TYPE_REAUTH_CREDS,
7074 + GSSEAP_STATE_ACCEPTOR_EXTS,
7076 + eapGssSmInitReauthCreds
7079 + /* other extensions go here */
7081 + ITOK_TYPE_ACCEPTOR_MIC,
7083 + GSSEAP_STATE_ACCEPTOR_EXTS,
7084 + SM_ITOK_FLAG_REQUIRED,
7085 + eapGssSmInitAcceptorMIC
7090 +gssEapInitSecContext(OM_uint32 *minor,
7091 + gss_cred_id_t cred,
7093 + gss_name_t target_name,
7094 + gss_OID mech_type,
7095 + OM_uint32 req_flags,
7096 + OM_uint32 time_req,
7097 + gss_channel_bindings_t input_chan_bindings,
7098 + gss_buffer_t input_token,
7099 + gss_OID *actual_mech_type,
7100 + gss_buffer_t output_token,
7101 + OM_uint32 *ret_flags,
7102 + OM_uint32 *time_rec)
7104 + OM_uint32 major, tmpMinor;
7105 + int initialContextToken = (ctx->mechanismUsed == GSS_C_NO_OID);
7108 + * XXX is acquiring the credential lock here necessary? The password is
7109 + * mutable but the contract could specify that this is not updated whilst
7110 + * a context is being initialized.
7112 + if (cred != GSS_C_NO_CREDENTIAL)
7113 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7115 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
7116 + major = gssEapResolveInitiatorCred(minor, cred, target_name, &ctx->cred);
7117 + if (GSS_ERROR(major))
7120 + GSSEAP_ASSERT(ctx->cred != GSS_C_NO_CREDENTIAL);
7123 + GSSEAP_MUTEX_LOCK(&ctx->cred->mutex);
7125 + GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_RESOLVED);
7126 + GSSEAP_ASSERT(ctx->cred->flags & CRED_FLAG_INITIATE);
7128 + if (initialContextToken) {
7129 + major = initBegin(minor, ctx, target_name, mech_type,
7130 + req_flags, time_req, input_chan_bindings);
7131 + if (GSS_ERROR(major))
7135 + major = gssEapSmStep(minor,
7142 + input_chan_bindings,
7145 + eapGssInitiatorSm,
7146 + sizeof(eapGssInitiatorSm) / sizeof(eapGssInitiatorSm[0]));
7147 + if (GSS_ERROR(major))
7150 + if (actual_mech_type != NULL) {
7151 + OM_uint32 tmpMajor;
7153 + tmpMajor = gssEapCanonicalizeOid(&tmpMinor, ctx->mechanismUsed, 0, actual_mech_type);
7154 + if (GSS_ERROR(tmpMajor)) {
7156 + *minor = tmpMinor;
7160 + if (ret_flags != NULL)
7161 + *ret_flags = ctx->gssFlags;
7162 + if (time_rec != NULL)
7163 + gssEapContextTime(&tmpMinor, ctx, time_rec);
7165 + GSSEAP_ASSERT(CTX_IS_ESTABLISHED(ctx) || major == GSS_S_CONTINUE_NEEDED);
7168 + if (cred != GSS_C_NO_CREDENTIAL)
7169 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7170 + if (ctx->cred != GSS_C_NO_CREDENTIAL)
7171 + GSSEAP_MUTEX_UNLOCK(&ctx->cred->mutex);
7176 +OM_uint32 GSSAPI_CALLCONV
7177 +gss_init_sec_context(OM_uint32 *minor,
7178 + gss_cred_id_t cred,
7179 + gss_ctx_id_t *context_handle,
7180 + gss_name_t target_name,
7181 + gss_OID mech_type,
7182 + OM_uint32 req_flags,
7183 + OM_uint32 time_req,
7184 + gss_channel_bindings_t input_chan_bindings,
7185 + gss_buffer_t input_token,
7186 + gss_OID *actual_mech_type,
7187 + gss_buffer_t output_token,
7188 + OM_uint32 *ret_flags,
7189 + OM_uint32 *time_rec)
7191 + OM_uint32 major, tmpMinor;
7192 + gss_ctx_id_t ctx = *context_handle;
7196 + output_token->length = 0;
7197 + output_token->value = NULL;
7199 + if (ctx == GSS_C_NO_CONTEXT) {
7200 + if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
7201 + *minor = GSSEAP_WRONG_SIZE;
7202 + return GSS_S_DEFECTIVE_TOKEN;
7205 + major = gssEapAllocContext(minor, &ctx);
7206 + if (GSS_ERROR(major))
7209 + ctx->flags |= CTX_FLAG_INITIATOR;
7211 + *context_handle = ctx;
7214 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
7216 + major = gssEapInitSecContext(minor,
7223 + input_chan_bindings,
7230 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
7232 + if (GSS_ERROR(major))
7233 + gssEapReleaseContext(&tmpMinor, context_handle);
7237 diff --git a/mech_eap/inquire_attrs_for_mech.c b/mech_eap/inquire_attrs_for_mech.c
7238 new file mode 100644
7239 index 0000000..a359f68
7241 +++ b/mech_eap/inquire_attrs_for_mech.c
7244 + * Copyright (c) 2011, JANET(UK)
7245 + * All rights reserved.
7247 + * Redistribution and use in source and binary forms, with or without
7248 + * modification, are permitted provided that the following conditions
7251 + * 1. Redistributions of source code must retain the above copyright
7252 + * notice, this list of conditions and the following disclaimer.
7254 + * 2. Redistributions in binary form must reproduce the above copyright
7255 + * notice, this list of conditions and the following disclaimer in the
7256 + * documentation and/or other materials provided with the distribution.
7258 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7259 + * may be used to endorse or promote products derived from this software
7260 + * without specific prior written permission.
7262 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7263 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7264 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7265 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7266 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7267 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7268 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7269 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7270 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7271 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7276 + * Enumerate the features supported by the GSS EAP mechanism.
7279 +#include "gssapiP_eap.h"
7281 +#define MA_ADD(ma, set) do { \
7282 + major = gss_add_oid_set_member(minor, (gss_OID)(ma), (set)); \
7283 + if (GSS_ERROR(major)) \
7287 +#define MA_SUPPORTED(ma) MA_ADD((ma), mech_attrs)
7288 +#define MA_KNOWN(ma) MA_ADD((ma), known_mech_attrs)
7290 +OM_uint32 GSSAPI_CALLCONV
7291 +gss_inquire_attrs_for_mech(OM_uint32 *minor,
7292 + gss_const_OID mech_oid,
7293 + gss_OID_set *mech_attrs,
7294 + gss_OID_set *known_mech_attrs)
7296 + OM_uint32 major, tmpMinor;
7298 + if (mech_attrs != NULL)
7299 + *mech_attrs = GSS_C_NO_OID_SET;
7300 + if (known_mech_attrs != NULL)
7301 + *known_mech_attrs = GSS_C_NO_OID_SET;
7303 + if (!gssEapIsConcreteMechanismOid((const gss_OID)mech_oid)) {
7304 + *minor = GSSEAP_WRONG_MECH;
7305 + return GSS_S_BAD_MECH;
7308 + if (mech_attrs != NULL) {
7309 + major = gss_create_empty_oid_set(minor, mech_attrs);
7310 + if (GSS_ERROR(major))
7313 +#ifdef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
7314 + if (oidEqual(mech_oid, GSS_EAP_MECHANISM))
7315 + MA_SUPPORTED(GSS_C_MA_MECH_PSEUDO);
7317 + MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE);
7318 + MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
7319 + MA_SUPPORTED(GSS_C_MA_AUTH_INIT);
7320 + MA_SUPPORTED(GSS_C_MA_AUTH_TARG);
7321 + MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT);
7322 + MA_SUPPORTED(GSS_C_MA_INTEG_PROT);
7323 + MA_SUPPORTED(GSS_C_MA_CONF_PROT);
7324 + MA_SUPPORTED(GSS_C_MA_MIC);
7325 + MA_SUPPORTED(GSS_C_MA_WRAP);
7326 + MA_SUPPORTED(GSS_C_MA_REPLAY_DET);
7327 + MA_SUPPORTED(GSS_C_MA_OOS_DET);
7328 + MA_SUPPORTED(GSS_C_MA_CBINDINGS);
7329 + MA_SUPPORTED(GSS_C_MA_CTX_TRANS);
7333 + if (known_mech_attrs != NULL) {
7334 + major = gss_create_empty_oid_set(minor, known_mech_attrs);
7335 + if (GSS_ERROR(major))
7338 +#ifdef HAVE_GSS_INQUIRE_ATTRS_FOR_MECH
7339 + MA_KNOWN(GSS_C_MA_MECH_CONCRETE);
7340 + MA_KNOWN(GSS_C_MA_MECH_PSEUDO);
7341 + MA_KNOWN(GSS_C_MA_MECH_COMPOSITE);
7342 + MA_KNOWN(GSS_C_MA_MECH_NEGO);
7343 + MA_KNOWN(GSS_C_MA_MECH_GLUE);
7344 + MA_KNOWN(GSS_C_MA_NOT_MECH);
7345 + MA_KNOWN(GSS_C_MA_DEPRECATED);
7346 + MA_KNOWN(GSS_C_MA_NOT_DFLT_MECH);
7347 + MA_KNOWN(GSS_C_MA_ITOK_FRAMED);
7348 + MA_KNOWN(GSS_C_MA_AUTH_INIT);
7349 + MA_KNOWN(GSS_C_MA_AUTH_TARG);
7350 + MA_KNOWN(GSS_C_MA_AUTH_INIT_INIT);
7351 + MA_KNOWN(GSS_C_MA_AUTH_TARG_INIT);
7352 + MA_KNOWN(GSS_C_MA_AUTH_INIT_ANON);
7353 + MA_KNOWN(GSS_C_MA_AUTH_TARG_ANON);
7354 + MA_KNOWN(GSS_C_MA_DELEG_CRED);
7355 + MA_KNOWN(GSS_C_MA_INTEG_PROT);
7356 + MA_KNOWN(GSS_C_MA_CONF_PROT);
7357 + MA_KNOWN(GSS_C_MA_MIC);
7358 + MA_KNOWN(GSS_C_MA_WRAP);
7359 + MA_KNOWN(GSS_C_MA_PROT_READY);
7360 + MA_KNOWN(GSS_C_MA_REPLAY_DET);
7361 + MA_KNOWN(GSS_C_MA_OOS_DET);
7362 + MA_KNOWN(GSS_C_MA_CBINDINGS);
7363 + MA_KNOWN(GSS_C_MA_PFS);
7364 + MA_KNOWN(GSS_C_MA_COMPRESS);
7365 + MA_KNOWN(GSS_C_MA_CTX_TRANS);
7369 + major = GSS_S_COMPLETE;
7373 + if (GSS_ERROR(major)) {
7374 + gss_release_oid_set(&tmpMinor, mech_attrs);
7375 + gss_release_oid_set(&tmpMinor, known_mech_attrs);
7380 diff --git a/mech_eap/inquire_context.c b/mech_eap/inquire_context.c
7381 new file mode 100644
7382 index 0000000..d37818d
7384 +++ b/mech_eap/inquire_context.c
7387 + * Copyright (c) 2011, JANET(UK)
7388 + * All rights reserved.
7390 + * Redistribution and use in source and binary forms, with or without
7391 + * modification, are permitted provided that the following conditions
7394 + * 1. Redistributions of source code must retain the above copyright
7395 + * notice, this list of conditions and the following disclaimer.
7397 + * 2. Redistributions in binary form must reproduce the above copyright
7398 + * notice, this list of conditions and the following disclaimer in the
7399 + * documentation and/or other materials provided with the distribution.
7401 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7402 + * may be used to endorse or promote products derived from this software
7403 + * without specific prior written permission.
7405 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7406 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7407 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7408 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7409 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7410 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7411 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7412 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7413 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7414 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7419 + * Return context handle properties.
7422 +#include "gssapiP_eap.h"
7424 +OM_uint32 GSSAPI_CALLCONV
7425 +gss_inquire_context(OM_uint32 *minor,
7427 + gss_name_t *src_name,
7428 + gss_name_t *targ_name,
7429 + OM_uint32 *lifetime_rec,
7430 + gss_OID *mech_type,
7431 + OM_uint32 *ctx_flags,
7432 + int *locally_initiated,
7435 + OM_uint32 major, tmpMinor;
7437 + if (ctx == GSS_C_NO_CONTEXT) {
7439 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
7442 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
7444 + if (src_name != NULL) {
7445 + major = gssEapDuplicateName(minor, ctx->initiatorName, src_name);
7446 + if (GSS_ERROR(major))
7450 + if (targ_name != NULL) {
7451 + major = gssEapDuplicateName(minor, ctx->acceptorName, targ_name);
7452 + if (GSS_ERROR(major))
7456 + if (lifetime_rec != NULL) {
7457 + time_t now, lifetime;
7459 + if (ctx->expiryTime == 0) {
7460 + lifetime = GSS_C_INDEFINITE;
7463 + lifetime = now - ctx->expiryTime;
7468 + *lifetime_rec = lifetime;
7471 + if (mech_type != NULL) {
7472 + major = gssEapCanonicalizeOid(minor, ctx->mechanismUsed, 0, mech_type);
7473 + if (GSS_ERROR(major))
7477 + if (ctx_flags != NULL) {
7478 + *ctx_flags = ctx->gssFlags;
7481 + if (locally_initiated != NULL) {
7482 + *locally_initiated = CTX_IS_INITIATOR(ctx);
7485 + if (open != NULL) {
7486 + *open = CTX_IS_ESTABLISHED(ctx);
7489 + major = GSS_S_COMPLETE;
7493 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
7495 + if (GSS_ERROR(major)) {
7496 + gssEapReleaseName(&tmpMinor, src_name);
7497 + gssEapReleaseName(&tmpMinor, targ_name);
7502 diff --git a/mech_eap/inquire_cred.c b/mech_eap/inquire_cred.c
7503 new file mode 100644
7504 index 0000000..227ab16
7506 +++ b/mech_eap/inquire_cred.c
7509 + * Copyright (c) 2011, JANET(UK)
7510 + * All rights reserved.
7512 + * Redistribution and use in source and binary forms, with or without
7513 + * modification, are permitted provided that the following conditions
7516 + * 1. Redistributions of source code must retain the above copyright
7517 + * notice, this list of conditions and the following disclaimer.
7519 + * 2. Redistributions in binary form must reproduce the above copyright
7520 + * notice, this list of conditions and the following disclaimer in the
7521 + * documentation and/or other materials provided with the distribution.
7523 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7524 + * may be used to endorse or promote products derived from this software
7525 + * without specific prior written permission.
7527 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7528 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7529 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7530 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7531 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7532 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7533 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7534 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7535 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7536 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7541 + * Return credential handle properties.
7544 +#include "gssapiP_eap.h"
7546 +OM_uint32 GSSAPI_CALLCONV
7547 +gss_inquire_cred(OM_uint32 *minor,
7548 + gss_cred_id_t cred,
7550 + OM_uint32 *pLifetime,
7551 + gss_cred_usage_t *cred_usage,
7552 + gss_OID_set *mechanisms)
7556 + if (cred == NULL) {
7558 + return GSS_S_NO_CRED;
7561 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7563 + major = gssEapInquireCred(minor, cred, name, pLifetime, cred_usage, mechanisms);
7565 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7569 diff --git a/mech_eap/inquire_cred_by_mech.c b/mech_eap/inquire_cred_by_mech.c
7570 new file mode 100644
7571 index 0000000..191902d
7573 +++ b/mech_eap/inquire_cred_by_mech.c
7576 + * Copyright (c) 2011, JANET(UK)
7577 + * All rights reserved.
7579 + * Redistribution and use in source and binary forms, with or without
7580 + * modification, are permitted provided that the following conditions
7583 + * 1. Redistributions of source code must retain the above copyright
7584 + * notice, this list of conditions and the following disclaimer.
7586 + * 2. Redistributions in binary form must reproduce the above copyright
7587 + * notice, this list of conditions and the following disclaimer in the
7588 + * documentation and/or other materials provided with the distribution.
7590 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7591 + * may be used to endorse or promote products derived from this software
7592 + * without specific prior written permission.
7594 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7595 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7596 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7597 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7598 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7599 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7600 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7601 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7602 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7603 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7608 + * Return credential handle properties.
7611 +#include "gssapiP_eap.h"
7613 +OM_uint32 GSSAPI_CALLCONV
7614 +gss_inquire_cred_by_mech(OM_uint32 *minor,
7615 + gss_cred_id_t cred,
7616 + gss_OID mech_type,
7618 + OM_uint32 *pInitiatorLifetime,
7619 + OM_uint32 *pAcceptorLifetime,
7620 + gss_cred_usage_t *cred_usage)
7622 + OM_uint32 major, lifetime;
7624 + if (cred == NULL) {
7626 + return GSS_S_NO_CRED;
7629 + GSSEAP_MUTEX_LOCK(&cred->mutex);
7631 + if (!gssEapCredAvailable(cred, mech_type)) {
7632 + major = GSS_S_BAD_MECH;
7633 + *minor = GSSEAP_CRED_MECH_MISMATCH;
7637 + major = gssEapInquireCred(minor, cred, name, &lifetime, cred_usage, NULL);
7638 + if (GSS_ERROR(major))
7641 + if (pInitiatorLifetime != NULL)
7642 + *pInitiatorLifetime = (cred->flags & CRED_FLAG_INITIATE) ? lifetime : 0;
7643 + if (pAcceptorLifetime != NULL)
7644 + *pAcceptorLifetime = (cred->flags & CRED_FLAG_ACCEPT) ? lifetime : 0;
7647 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
7651 diff --git a/mech_eap/inquire_cred_by_oid.c b/mech_eap/inquire_cred_by_oid.c
7652 new file mode 100644
7653 index 0000000..2ad34ed
7655 +++ b/mech_eap/inquire_cred_by_oid.c
7658 + * Copyright (c) 2011, JANET(UK)
7659 + * All rights reserved.
7661 + * Redistribution and use in source and binary forms, with or without
7662 + * modification, are permitted provided that the following conditions
7665 + * 1. Redistributions of source code must retain the above copyright
7666 + * notice, this list of conditions and the following disclaimer.
7668 + * 2. Redistributions in binary form must reproduce the above copyright
7669 + * notice, this list of conditions and the following disclaimer in the
7670 + * documentation and/or other materials provided with the distribution.
7672 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7673 + * may be used to endorse or promote products derived from this software
7674 + * without specific prior written permission.
7676 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7677 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7678 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7679 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7680 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7681 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7682 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7683 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7684 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7685 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7690 + * Return extended credential handle properties.
7693 +#include "gssapiP_eap.h"
7698 + OM_uint32 (*inquire)(OM_uint32 *, const gss_cred_id_t,
7699 + const gss_OID, gss_buffer_set_t *);
7700 +} inquireCredOps[] = {
7704 +OM_uint32 GSSAPI_CALLCONV
7705 +gss_inquire_cred_by_oid(OM_uint32 *minor,
7706 + const gss_cred_id_t cred_handle,
7707 + const gss_OID desired_object GSSEAP_UNUSED,
7708 + gss_buffer_set_t *data_set)
7714 + *data_set = GSS_C_NO_BUFFER_SET;
7716 + if (cred_handle == GSS_C_NO_CREDENTIAL) {
7718 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
7721 + GSSEAP_MUTEX_LOCK(&cred_handle->mutex);
7723 + major = GSS_S_UNAVAILABLE;
7724 + *minor = GSSEAP_BAD_CRED_OPTION;
7727 + for (i = 0; i < sizeof(inquireCredOps) / sizeof(inquireCredOps[0]); i++) {
7728 + if (oidEqual(&inquireCredOps[i].oid, desired_object)) {
7729 + major = (*inquireCredOps[i].inquire)(minor, cred_handle,
7730 + desired_object, data_set);
7736 + GSSEAP_MUTEX_UNLOCK(&cred_handle->mutex);
7740 diff --git a/mech_eap/inquire_mech_for_saslname.c b/mech_eap/inquire_mech_for_saslname.c
7741 new file mode 100644
7742 index 0000000..bd518c0
7744 +++ b/mech_eap/inquire_mech_for_saslname.c
7747 + * Copyright (c) 2011, JANET(UK)
7748 + * All rights reserved.
7750 + * Redistribution and use in source and binary forms, with or without
7751 + * modification, are permitted provided that the following conditions
7754 + * 1. Redistributions of source code must retain the above copyright
7755 + * notice, this list of conditions and the following disclaimer.
7757 + * 2. Redistributions in binary form must reproduce the above copyright
7758 + * notice, this list of conditions and the following disclaimer in the
7759 + * documentation and/or other materials provided with the distribution.
7761 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7762 + * may be used to endorse or promote products derived from this software
7763 + * without specific prior written permission.
7765 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7766 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7767 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7768 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7769 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7770 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7771 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7772 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7773 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7774 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7779 + * Map mechanism OID to a SASL mechanism name.
7782 +#include "gssapiP_eap.h"
7784 +OM_uint32 GSSAPI_CALLCONV
7785 +gss_inquire_saslname_for_mech(OM_uint32 *minor,
7786 + const gss_OID mech,
7787 + gss_buffer_t sasl_mech_name,
7788 + gss_buffer_t mech_name,
7789 + gss_buffer_t mech_description)
7792 + gss_buffer_t name;
7793 + krb5_enctype etype = ENCTYPE_NULL;
7795 + /* Dynamically construct mechanism name from Kerberos string enctype */
7796 + major = gssEapOidToEnctype(minor, mech, &etype);
7797 + if (GSS_ERROR(major))
7800 + if (mech_name != GSS_C_NO_BUFFER) {
7801 + krb5_context krbContext;
7803 + GSSEAP_KRB_INIT(&krbContext);
7805 + *minor = krbEnctypeToString(krbContext, etype, "eap-", mech_name);
7807 + return GSS_S_FAILURE;
7810 + if (mech_description != GSS_C_NO_BUFFER) {
7811 + major = makeStringBuffer(minor,
7812 + "Extensible Authentication Protocol GSS-API Mechanism",
7813 + mech_description);
7814 + if (GSS_ERROR(major))
7818 + if (sasl_mech_name != GSS_C_NO_BUFFER) {
7819 + name = gssEapOidToSaslName(mech);
7820 + if (name == GSS_C_NO_BUFFER) {
7821 + major = GSS_S_BAD_MECH;
7822 + *minor = GSSEAP_WRONG_MECH;
7824 + major = duplicateBuffer(minor, name, sasl_mech_name);
7830 diff --git a/mech_eap/inquire_mechs_for_name.c b/mech_eap/inquire_mechs_for_name.c
7831 new file mode 100644
7832 index 0000000..89c869c
7834 +++ b/mech_eap/inquire_mechs_for_name.c
7837 + * Copyright (c) 2011, JANET(UK)
7838 + * All rights reserved.
7840 + * Redistribution and use in source and binary forms, with or without
7841 + * modification, are permitted provided that the following conditions
7844 + * 1. Redistributions of source code must retain the above copyright
7845 + * notice, this list of conditions and the following disclaimer.
7847 + * 2. Redistributions in binary form must reproduce the above copyright
7848 + * notice, this list of conditions and the following disclaimer in the
7849 + * documentation and/or other materials provided with the distribution.
7851 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7852 + * may be used to endorse or promote products derived from this software
7853 + * without specific prior written permission.
7855 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7856 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7857 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7858 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7859 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7860 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7861 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7862 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7863 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7864 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7869 + * Determine mechanism OIDs supported by name.
7872 +#include "gssapiP_eap.h"
7874 +OM_uint32 GSSAPI_CALLCONV
7875 +gss_inquire_mechs_for_name(OM_uint32 *minor,
7876 + const gss_name_t input_name,
7877 + gss_OID_set *mech_types)
7879 + OM_uint32 major, tmpMinor;
7882 + *mech_types = GSS_C_NO_OID_SET;
7884 + if (input_name != GSS_C_NO_NAME &&
7885 + input_name->mechanismUsed != GSS_C_NO_OID) {
7886 + major = gss_create_empty_oid_set(minor, mech_types);
7887 + if (GSS_ERROR(major))
7890 + major = gss_add_oid_set_member(minor,
7891 + input_name->mechanismUsed,
7893 + if (GSS_ERROR(major)) {
7894 + gss_release_oid_set(&tmpMinor, mech_types);
7898 + major = gssEapIndicateMechs(minor, mech_types);
7899 + if (GSS_ERROR(major))
7905 diff --git a/mech_eap/inquire_name.c b/mech_eap/inquire_name.c
7906 new file mode 100644
7907 index 0000000..78b08a0
7909 +++ b/mech_eap/inquire_name.c
7912 + * Copyright (c) 2011, JANET(UK)
7913 + * All rights reserved.
7915 + * Redistribution and use in source and binary forms, with or without
7916 + * modification, are permitted provided that the following conditions
7919 + * 1. Redistributions of source code must retain the above copyright
7920 + * notice, this list of conditions and the following disclaimer.
7922 + * 2. Redistributions in binary form must reproduce the above copyright
7923 + * notice, this list of conditions and the following disclaimer in the
7924 + * documentation and/or other materials provided with the distribution.
7926 + * 3. Neither the name of JANET(UK) nor the names of its contributors
7927 + * may be used to endorse or promote products derived from this software
7928 + * without specific prior written permission.
7930 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
7931 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7932 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7933 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
7934 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
7935 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
7936 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7937 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
7938 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7939 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7944 + * Enumerate name attributes.
7947 +#include "gssapiP_eap.h"
7949 +OM_uint32 GSSAPI_CALLCONV
7950 +gss_inquire_name(OM_uint32 *minor,
7954 + gss_buffer_set_t *attrs)
7956 + OM_uint32 major, tmpMinor;
7960 + if (name_is_MN != NULL)
7962 + if (MN_mech != NULL)
7963 + *MN_mech = GSS_C_NO_OID;
7964 + if (attrs != NULL)
7965 + *attrs = GSS_C_NO_BUFFER_SET;
7967 + if (name == GSS_C_NO_NAME) {
7969 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
7972 + if (attrs == NULL)
7973 + return GSS_S_COMPLETE;
7975 + GSSEAP_MUTEX_LOCK(&name->mutex);
7977 + major = gssEapInquireName(minor, name, name_is_MN, MN_mech, attrs);
7979 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
7981 + if (GSS_ERROR(major))
7982 + gss_release_buffer_set(&tmpMinor, attrs);
7986 diff --git a/mech_eap/inquire_names_for_mech.c b/mech_eap/inquire_names_for_mech.c
7987 new file mode 100644
7988 index 0000000..0e60340
7990 +++ b/mech_eap/inquire_names_for_mech.c
7993 + * Copyright (c) 2011, JANET(UK)
7994 + * All rights reserved.
7996 + * Redistribution and use in source and binary forms, with or without
7997 + * modification, are permitted provided that the following conditions
8000 + * 1. Redistributions of source code must retain the above copyright
8001 + * notice, this list of conditions and the following disclaimer.
8003 + * 2. Redistributions in binary form must reproduce the above copyright
8004 + * notice, this list of conditions and the following disclaimer in the
8005 + * documentation and/or other materials provided with the distribution.
8007 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8008 + * may be used to endorse or promote products derived from this software
8009 + * without specific prior written permission.
8011 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8012 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8013 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8014 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8015 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8016 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8017 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8018 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8019 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8020 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8025 + * Return supported name OID types.
8028 +#include "gssapiP_eap.h"
8030 +OM_uint32 GSSAPI_CALLCONV
8031 +gss_inquire_names_for_mech(OM_uint32 *minor,
8032 + gss_OID mechanism,
8033 + gss_OID_set *ret_name_types)
8035 + OM_uint32 major, tmpMinor;
8036 + gss_OID nameTypes[] = {
8037 + GSS_C_NT_USER_NAME,
8038 + GSS_C_NT_HOSTBASED_SERVICE,
8039 + GSS_C_NT_EXPORT_NAME,
8040 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
8041 + GSS_C_NT_COMPOSITE_EXPORT,
8043 + GSS_EAP_NT_EAP_NAME,
8044 + GSS_C_NT_ANONYMOUS,
8048 + if (!gssEapIsMechanismOid(mechanism)) {
8049 + *minor = GSSEAP_WRONG_MECH;
8050 + return GSS_S_BAD_MECH;
8053 + major = gss_create_empty_oid_set(minor, ret_name_types);
8054 + if (GSS_ERROR(major))
8057 + for (i = 0; i < sizeof(nameTypes)/sizeof(nameTypes[0]); i++) {
8058 + major = gss_add_oid_set_member(minor, nameTypes[i], ret_name_types);
8059 + if (GSS_ERROR(major))
8064 + if (GSS_ERROR(major))
8065 + gss_release_oid_set(&tmpMinor, ret_name_types);
8069 diff --git a/mech_eap/inquire_saslname_for_mech.c b/mech_eap/inquire_saslname_for_mech.c
8070 new file mode 100644
8071 index 0000000..d6d7c14
8073 +++ b/mech_eap/inquire_saslname_for_mech.c
8076 + * Copyright (c) 2011, JANET(UK)
8077 + * All rights reserved.
8079 + * Redistribution and use in source and binary forms, with or without
8080 + * modification, are permitted provided that the following conditions
8083 + * 1. Redistributions of source code must retain the above copyright
8084 + * notice, this list of conditions and the following disclaimer.
8086 + * 2. Redistributions in binary form must reproduce the above copyright
8087 + * notice, this list of conditions and the following disclaimer in the
8088 + * documentation and/or other materials provided with the distribution.
8090 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8091 + * may be used to endorse or promote products derived from this software
8092 + * without specific prior written permission.
8094 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8095 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8096 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8097 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8098 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8099 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8100 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8101 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8102 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8103 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8108 + * Map SASL mechanism name to a mechanism OID.
8111 +#include "gssapiP_eap.h"
8113 +OM_uint32 GSSAPI_CALLCONV
8114 +gss_inquire_mech_for_saslname(OM_uint32 *minor,
8115 + const gss_buffer_t sasl_mech_name,
8116 + gss_OID *mech_type)
8118 + *mech_type = gssEapSaslNameToOid(sasl_mech_name);
8119 + if (*mech_type == GSS_C_NO_OID) {
8120 + *minor = GSSEAP_WRONG_MECH;
8121 + return GSS_S_BAD_MECH;
8124 + return GSS_S_COMPLETE;
8126 diff --git a/mech_eap/inquire_sec_context_by_oid.c b/mech_eap/inquire_sec_context_by_oid.c
8127 new file mode 100644
8128 index 0000000..7435f2e
8130 +++ b/mech_eap/inquire_sec_context_by_oid.c
8133 + * Copyright (c) 2011, JANET(UK)
8134 + * All rights reserved.
8136 + * Redistribution and use in source and binary forms, with or without
8137 + * modification, are permitted provided that the following conditions
8140 + * 1. Redistributions of source code must retain the above copyright
8141 + * notice, this list of conditions and the following disclaimer.
8143 + * 2. Redistributions in binary form must reproduce the above copyright
8144 + * notice, this list of conditions and the following disclaimer in the
8145 + * documentation and/or other materials provided with the distribution.
8147 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8148 + * may be used to endorse or promote products derived from this software
8149 + * without specific prior written permission.
8151 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8152 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8153 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8154 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8155 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8156 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8157 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8158 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8159 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8160 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8165 + * Return extended properties of a context handle.
8168 +#include "gssapiP_eap.h"
8171 +addEnctypeOidToBufferSet(OM_uint32 *minor,
8172 + krb5_enctype encryptionType,
8173 + gss_buffer_set_t *dataSet)
8176 + unsigned char oidBuf[16];
8178 + gss_buffer_desc buf;
8180 + oid.length = sizeof(oidBuf);
8181 + oid.elements = oidBuf;
8183 + major = composeOid(minor,
8184 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04",
8188 + if (GSS_ERROR(major))
8191 + buf.length = oid.length;
8192 + buf.value = oid.elements;
8194 + major = gss_add_buffer_set_member(minor, &buf, dataSet);
8200 +zeroAndReleaseBufferSet(gss_buffer_set_t *dataSet)
8202 + OM_uint32 tmpMinor;
8203 + gss_buffer_set_t set = *dataSet;
8206 + if (set == GSS_C_NO_BUFFER_SET)
8209 + for (i = 0; i <set->count; i++)
8210 + memset(set->elements[i].value, 0, set->elements[i].length);
8212 + gss_release_buffer_set(&tmpMinor, dataSet);
8216 +inquireSessionKey(OM_uint32 *minor,
8217 + const gss_ctx_id_t ctx,
8218 + const gss_OID desired_object GSSEAP_UNUSED,
8219 + gss_buffer_set_t *dataSet)
8222 + gss_buffer_desc buf;
8224 + if (ctx->encryptionType == ENCTYPE_NULL) {
8225 + major = GSS_S_UNAVAILABLE;
8226 + *minor = GSSEAP_KEY_UNAVAILABLE;
8230 + buf.length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
8231 + buf.value = KRB_KEY_DATA(&ctx->rfc3961Key);
8233 + major = gss_add_buffer_set_member(minor, &buf, dataSet);
8234 + if (GSS_ERROR(major))
8237 + major = addEnctypeOidToBufferSet(minor, ctx->encryptionType, dataSet);
8238 + if (GSS_ERROR(major))
8241 + major = GSS_S_COMPLETE;
8245 + if (GSS_ERROR(major))
8246 + zeroAndReleaseBufferSet(dataSet);
8252 +inquireNegoExKey(OM_uint32 *minor,
8253 + const gss_ctx_id_t ctx,
8254 + const gss_OID desired_object,
8255 + gss_buffer_set_t *dataSet)
8257 + OM_uint32 major, tmpMinor;
8258 + int bInitiatorKey;
8259 + gss_buffer_desc salt;
8260 + gss_buffer_desc key = GSS_C_EMPTY_BUFFER;
8263 + bInitiatorKey = CTX_IS_INITIATOR(ctx);
8265 + if (ctx->encryptionType == ENCTYPE_NULL) {
8266 + major = GSS_S_UNAVAILABLE;
8267 + *minor = GSSEAP_KEY_UNAVAILABLE;
8272 + * If the caller supplied the verify key OID, then we need the acceptor
8273 + * key if we are the initiator, and vice versa.
8275 + if (desired_object->length == 11 &&
8276 + memcmp(desired_object->elements,
8277 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07", 11) == 0)
8278 + bInitiatorKey ^= 1;
8280 + if (bInitiatorKey) {
8281 + salt.length = NEGOEX_INITIATOR_SALT_LEN;
8282 + salt.value = NEGOEX_INITIATOR_SALT;
8284 + salt.length = NEGOEX_ACCEPTOR_SALT_LEN;
8285 + salt.value = NEGOEX_ACCEPTOR_SALT;
8288 + keySize = KRB_KEY_LENGTH(&ctx->rfc3961Key);
8290 + major = gssEapPseudoRandom(minor, ctx, GSS_C_PRF_KEY_FULL, &salt,
8292 + if (GSS_ERROR(major))
8295 + major = gss_add_buffer_set_member(minor, &key, dataSet);
8296 + if (GSS_ERROR(major))
8299 + major = addEnctypeOidToBufferSet(minor, ctx->encryptionType, dataSet);
8300 + if (GSS_ERROR(major))
8303 + major = GSS_S_COMPLETE;
8307 + if (key.value != NULL) {
8308 + memset(key.value, 0, key.length);
8309 + gss_release_buffer(&tmpMinor, &key);
8311 + if (GSS_ERROR(major))
8312 + zeroAndReleaseBufferSet(dataSet);
8319 + OM_uint32 (*inquire)(OM_uint32 *, const gss_ctx_id_t,
8320 + const gss_OID, gss_buffer_set_t *);
8321 +} inquireCtxOps[] = {
8323 + /* GSS_C_INQ_SSPI_SESSION_KEY */
8324 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" },
8328 + /* GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT + v1 */
8329 + { 12, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06\x01" },
8330 + gssEapExportLucidSecContext
8333 + /* GSS_C_INQ_NEGOEX_KEY */
8334 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06" },
8338 + /* GSS_C_INQ_NEGOEX_VERIFY_KEY */
8339 + { 11, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07" },
8344 +OM_uint32 GSSAPI_CALLCONV
8345 +gss_inquire_sec_context_by_oid(OM_uint32 *minor,
8346 + const gss_ctx_id_t ctx,
8347 + const gss_OID desired_object,
8348 + gss_buffer_set_t *data_set)
8353 + *data_set = GSS_C_NO_BUFFER_SET;
8355 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
8358 + if (!CTX_IS_ESTABLISHED(ctx)) {
8359 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
8360 + major = GSS_S_NO_CONTEXT;
8365 + major = GSS_S_UNAVAILABLE;
8366 + *minor = GSSEAP_BAD_CONTEXT_OPTION;
8368 + for (i = 0; i < sizeof(inquireCtxOps) / sizeof(inquireCtxOps[0]); i++) {
8369 + if (oidEqual(&inquireCtxOps[i].oid, desired_object)) {
8370 + major = (*inquireCtxOps[i].inquire)(minor, ctx,
8371 + desired_object, data_set);
8376 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
8380 diff --git a/mech_eap/install-sh b/mech_eap/install-sh
8381 new file mode 100755
8382 index 0000000..6781b98
8384 +++ b/mech_eap/install-sh
8387 +# install - install a program, script, or datafile
8389 +scriptversion=2009-04-28.21; # UTC
8391 +# This originates from X11R5 (mit/util/scripts/install.sh), which was
8392 +# later released in X11R6 (xc/config/util/install.sh) with the
8393 +# following copyright and license.
8395 +# Copyright (C) 1994 X Consortium
8397 +# Permission is hereby granted, free of charge, to any person obtaining a copy
8398 +# of this software and associated documentation files (the "Software"), to
8399 +# deal in the Software without restriction, including without limitation the
8400 +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8401 +# sell copies of the Software, and to permit persons to whom the Software is
8402 +# furnished to do so, subject to the following conditions:
8404 +# The above copyright notice and this permission notice shall be included in
8405 +# all copies or substantial portions of the Software.
8407 +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8408 +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8409 +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8410 +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
8411 +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
8412 +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8414 +# Except as contained in this notice, the name of the X Consortium shall not
8415 +# be used in advertising or otherwise to promote the sale, use or other deal-
8416 +# ings in this Software without prior written authorization from the X Consor-
8420 +# FSF changes to this file are in the public domain.
8422 +# Calling this script install-sh is preferred over install.sh, to prevent
8423 +# `make' implicit rules from creating a file called install from it
8424 +# when there is no Makefile.
8426 +# This script is compatible with the BSD install script, but was written
8433 +# set DOITPROG to echo to test this script
8435 +# Don't use :- since 4.3BSD and earlier shells don't like it.
8437 +if test -z "$doit"; then
8443 +# Put in absolute file names if you don't have them in your path;
8444 +# or use environment vars.
8446 +chgrpprog=${CHGRPPROG-chgrp}
8447 +chmodprog=${CHMODPROG-chmod}
8448 +chownprog=${CHOWNPROG-chown}
8449 +cmpprog=${CMPPROG-cmp}
8450 +cpprog=${CPPROG-cp}
8451 +mkdirprog=${MKDIRPROG-mkdir}
8452 +mvprog=${MVPROG-mv}
8453 +rmprog=${RMPROG-rm}
8454 +stripprog=${STRIPPROG-strip}
8457 +initialize_posix_glob='
8458 + test "$posix_glob" != "?" || {
8459 + if (set -f) 2>/dev/null; then
8469 +# Desired mode of installed file.
8473 +chmodcmd=$chmodprog
8484 +copy_on_change=false
8485 +no_target_directory=
8488 +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8489 + or: $0 [OPTION]... SRCFILES... DIRECTORY
8490 + or: $0 [OPTION]... -t DIRECTORY SRCFILES...
8491 + or: $0 [OPTION]... -d DIRECTORIES...
8493 +In the 1st form, copy SRCFILE to DSTFILE.
8494 +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
8495 +In the 4th, create DIRECTORIES.
8498 + --help display this help and exit.
8499 + --version display version info and exit.
8502 + -C install only if different (preserve the last data modification time)
8503 + -d create directories instead of installing files.
8504 + -g GROUP $chgrpprog installed files to GROUP.
8505 + -m MODE $chmodprog installed files to MODE.
8506 + -o USER $chownprog installed files to USER.
8507 + -s $stripprog installed files.
8508 + -t DIRECTORY install into DIRECTORY.
8509 + -T report an error if DSTFILE is a directory.
8511 +Environment variables override the default commands:
8512 + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
8516 +while test $# -ne 0; do
8520 + -C) copy_on_change=true;;
8522 + -d) dir_arg=true;;
8524 + -g) chgrpcmd="$chgrpprog $2"
8527 + --help) echo "$usage"; exit $?;;
8531 + *' '* | *' '* | *'
8532 +'* | *'*'* | *'?'* | *'['*)
8533 + echo "$0: invalid mode: $mode" >&2
8538 + -o) chowncmd="$chownprog $2"
8541 + -s) stripcmd=$stripprog;;
8546 + -T) no_target_directory=true;;
8548 + --version) echo "$0 $scriptversion"; exit $?;;
8553 + -*) echo "$0: invalid option: $1" >&2
8561 +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
8562 + # When -d is used, all remaining arguments are directories to create.
8563 + # When -t is used, the destination is already specified.
8564 + # Otherwise, the last argument is the destination. Remove it from $@.
8567 + if test -n "$dst_arg"; then
8568 + # $@ is not empty: it contains at least $arg.
8569 + set fnord "$@" "$dst_arg"
8577 +if test $# -eq 0; then
8578 + if test -z "$dir_arg"; then
8579 + echo "$0: no input file specified." >&2
8582 + # It's OK to call `install-sh -d' without argument.
8583 + # This can happen when creating conditional directories.
8587 +if test -z "$dir_arg"; then
8588 + trap '(exit $?); exit' 1 2 13 15
8590 + # Set umask so as not to create temps with too-generous modes.
8591 + # However, 'strip' requires both read and write access to temps.
8593 + # Optimize common cases.
8594 + *644) cp_umask=133;;
8595 + *755) cp_umask=22;;
8598 + if test -z "$stripcmd"; then
8603 + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
8605 + if test -z "$stripcmd"; then
8610 + cp_umask=$mode$u_plus_rw;;
8616 + # Protect names starting with `-'.
8621 + if test -n "$dir_arg"; then
8628 + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
8629 + # might cause directories to be created, which would be especially bad
8630 + # if $src (and thus $dsttmp) contains '*'.
8631 + if test ! -f "$src" && test ! -d "$src"; then
8632 + echo "$0: $src does not exist." >&2
8636 + if test -z "$dst_arg"; then
8637 + echo "$0: no destination specified." >&2
8642 + # Protect names starting with `-'.
8647 + # If destination is a directory, append the input filename; won't work
8648 + # if double slashes aren't ignored.
8649 + if test -d "$dst"; then
8650 + if test -n "$no_target_directory"; then
8651 + echo "$0: $dst_arg: Is a directory" >&2
8655 + dst=$dstdir/`basename "$src"`
8658 + # Prefer dirname, but fall back on a substitute if dirname fails.
8660 + (dirname "$dst") 2>/dev/null ||
8661 + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
8662 + X"$dst" : 'X\(//\)[^/]' \| \
8663 + X"$dst" : 'X\(//\)$' \| \
8664 + X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
8666 + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
8670 + /^X\(\/\/\)[^/].*/{
8690 + obsolete_mkdir_used=false
8692 + if test $dstdir_status != 0; then
8693 + case $posix_mkdir in
8695 + # Create intermediate dirs using mode 755 as modified by the umask.
8696 + # This is like FreeBSD 'install' as of 1997-10-28.
8698 + case $stripcmd.$umask in
8699 + # Optimize common cases.
8700 + *[2367][2367]) mkdir_umask=$umask;;
8701 + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
8704 + mkdir_umask=`expr $umask + 22 \
8705 + - $umask % 100 % 40 + $umask % 20 \
8706 + - $umask % 10 % 4 + $umask % 2
8708 + *) mkdir_umask=$umask,go-w;;
8711 + # With -d, create the new directory with the user-specified mode.
8712 + # Otherwise, rely on $mkdir_umask.
8713 + if test -n "$dir_arg"; then
8714 + mkdir_mode=-m$mode
8721 + *[123567][0-7][0-7])
8722 + # POSIX mkdir -p sets u+wx bits regardless of umask, which
8723 + # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
8726 + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
8727 + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
8729 + if (umask $mkdir_umask &&
8730 + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
8732 + if test -z "$dir_arg" || {
8733 + # Check for POSIX incompatibilities with -m.
8734 + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
8735 + # other-writeable bit of parent directory when it shouldn't.
8736 + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
8737 + ls_ld_tmpdir=`ls -ld "$tmpdir"`
8738 + case $ls_ld_tmpdir in
8739 + d????-?r-*) different_mode=700;;
8740 + d????-?--*) different_mode=755;;
8743 + $mkdirprog -m$different_mode -p -- "$tmpdir" && {
8744 + ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
8745 + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
8748 + then posix_mkdir=:
8750 + rmdir "$tmpdir/d" "$tmpdir"
8752 + # Remove any dirs left behind by ancient mkdir implementations.
8753 + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
8761 + umask $mkdir_umask &&
8762 + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
8767 + # The umask is ridiculous, or mkdir does not conform to POSIX,
8768 + # or it failed possibly due to a race condition. Create the
8769 + # directory the slow way, step by step, checking for races as we go.
8777 + eval "$initialize_posix_glob"
8781 + $posix_glob set -f
8784 + $posix_glob set +f
8791 + test -z "$d" && continue
8794 + if test -d "$prefix"; then
8797 + if $posix_mkdir; then
8798 + (umask=$mkdir_umask &&
8799 + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
8800 + # Don't fail if two instances are running concurrently.
8801 + test -d "$prefix" || exit 1
8804 + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
8805 + *) qprefix=$prefix;;
8807 + prefixes="$prefixes '$qprefix'"
8813 + if test -n "$prefixes"; then
8814 + # Don't fail if two instances are running concurrently.
8815 + (umask $mkdir_umask &&
8816 + eval "\$doit_exec \$mkdirprog $prefixes") ||
8817 + test -d "$dstdir" || exit 1
8818 + obsolete_mkdir_used=true
8823 + if test -n "$dir_arg"; then
8824 + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
8825 + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
8826 + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
8827 + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
8830 + # Make a couple of temp file names in the proper directory.
8831 + dsttmp=$dstdir/_inst.$$_
8832 + rmtmp=$dstdir/_rm.$$_
8834 + # Trap to clean up those temp files at exit.
8835 + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
8837 + # Copy the file name to the temp name.
8838 + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
8840 + # and set any options; do chmod last to preserve setuid bits.
8842 + # If any of these fail, we abort the whole thing. If we want to
8843 + # ignore errors from any of these, just make sure not to ignore
8844 + # errors from the above "$doit $cpprog $src $dsttmp" command.
8846 + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
8847 + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
8848 + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
8849 + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
8851 + # If -C, don't bother to copy if it wouldn't change the file.
8852 + if $copy_on_change &&
8853 + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
8854 + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
8856 + eval "$initialize_posix_glob" &&
8857 + $posix_glob set -f &&
8858 + set X $old && old=:$2:$4:$5:$6 &&
8859 + set X $new && new=:$2:$4:$5:$6 &&
8860 + $posix_glob set +f &&
8862 + test "$old" = "$new" &&
8863 + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
8867 + # Rename the file to the real destination.
8868 + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
8870 + # The rename failed, perhaps because mv can't rename something else
8871 + # to itself, or perhaps because mv is so ancient that it does not
8874 + # Now remove or move aside any old file at destination location.
8875 + # We try this two ways since rm can't unlink itself on some
8876 + # systems and the destination file might be busy for other
8877 + # reasons. In this case, the final cleanup might fail but the new
8878 + # file should still install successfully.
8880 + test ! -f "$dst" ||
8881 + $doit $rmcmd -f "$dst" 2>/dev/null ||
8882 + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
8883 + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
8885 + { echo "$0: cannot unlink or rename $dst" >&2
8890 + # Now rename the file to the real destination.
8891 + $doit $mvcmd "$dsttmp" "$dst"
8900 +# eval: (add-hook 'write-file-hooks 'time-stamp)
8901 +# time-stamp-start: "scriptversion="
8902 +# time-stamp-format: "%:y-%02m-%02d.%02H"
8903 +# time-stamp-time-zone: "UTC"
8904 +# time-stamp-end: "; # UTC"
8906 diff --git a/mech_eap/map_name_to_any.c b/mech_eap/map_name_to_any.c
8907 new file mode 100644
8908 index 0000000..2a8a96c
8910 +++ b/mech_eap/map_name_to_any.c
8913 + * Copyright (c) 2011, JANET(UK)
8914 + * All rights reserved.
8916 + * Redistribution and use in source and binary forms, with or without
8917 + * modification, are permitted provided that the following conditions
8920 + * 1. Redistributions of source code must retain the above copyright
8921 + * notice, this list of conditions and the following disclaimer.
8923 + * 2. Redistributions in binary form must reproduce the above copyright
8924 + * notice, this list of conditions and the following disclaimer in the
8925 + * documentation and/or other materials provided with the distribution.
8927 + * 3. Neither the name of JANET(UK) nor the names of its contributors
8928 + * may be used to endorse or promote products derived from this software
8929 + * without specific prior written permission.
8931 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8932 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8933 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8934 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
8935 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8936 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8937 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8938 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8939 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
8940 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
8944 +#include "gssapiP_eap.h"
8946 +OM_uint32 GSSAPI_CALLCONV
8947 +gss_map_name_to_any(OM_uint32 *minor,
8949 + int authenticated,
8950 + gss_buffer_t type_id,
8951 + gss_any_t *output)
8955 + *output = (gss_any_t)NULL;
8957 + if (name == GSS_C_NO_NAME) {
8959 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
8962 + GSSEAP_MUTEX_LOCK(&name->mutex);
8964 + major = gssEapMapNameToAny(minor, name, authenticated, type_id, output);
8966 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
8970 diff --git a/mech_eap/mech b/mech_eap/mech
8971 new file mode 100644
8972 index 0000000..258a43a
8977 +# Sample mechanism glue configuration for EAP GSS mechanism.
8979 +# Any encryption type supported by Kerberos can be defined as the
8980 +# last element of the OID arc.
8982 +eap-aes128 1.3.6.1.4.1.5322.22.1.17 mech_eap.so
8983 +eap-aes256 1.3.6.1.4.1.5322.22.1.18 mech_eap.so
8984 diff --git a/mech_eap/mech_eap-noacceptor.exports b/mech_eap/mech_eap-noacceptor.exports
8985 new file mode 100644
8986 index 0000000..f00df8a
8988 +++ b/mech_eap/mech_eap-noacceptor.exports
8992 +gss_add_cred_with_password
8993 +gss_canonicalize_name
8996 +gss_delete_sec_context
8998 +gss_display_name_ext
9001 +gss_exchange_meta_data
9003 +gss_export_sec_context
9006 +gss_import_sec_context
9008 +gss_init_sec_context
9009 +gss_inquire_attrs_for_mech
9010 +gss_inquire_context
9012 +gss_inquire_cred_by_mech
9013 +gss_inquire_cred_by_oid
9014 +gss_inquire_mechs_for_name
9015 +gss_inquire_mech_for_saslname
9016 +gss_inquire_names_for_mech
9017 +gss_inquire_saslname_for_mech
9018 +gss_inquire_sec_context_by_oid
9019 +gss_process_context_token
9021 +gss_query_mechanism_info
9022 +gss_query_meta_data
9025 +gss_internal_release_oid
9026 +gss_set_sec_context_option
9033 +gss_wrap_iov_length
9034 +gss_wrap_size_limit
9035 +GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
9036 +GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
9037 +GSS_EAP_NT_EAP_NAME
9038 +GSS_EAP_CRED_SET_CRED_FLAG
9039 +GSS_EAP_CRED_SET_CRED_PASSWORD
9040 +GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
9041 +GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
9042 +gssspi_acquire_cred_with_password
9043 +gssspi_authorize_localname
9044 +gssspi_set_cred_option
9045 diff --git a/mech_eap/mech_eap.exports b/mech_eap/mech_eap.exports
9046 new file mode 100644
9047 index 0000000..6a17a17
9049 +++ b/mech_eap/mech_eap.exports
9051 +gss_accept_sec_context
9054 +gss_add_cred_with_password
9055 +gss_canonicalize_name
9058 +gss_delete_name_attribute
9059 +gss_delete_sec_context
9061 +gss_display_name_ext
9064 +gss_exchange_meta_data
9066 +gss_export_name_composite
9067 +gss_export_sec_context
9069 +gss_get_name_attribute
9071 +gss_import_sec_context
9073 +gss_init_sec_context
9074 +gss_inquire_attrs_for_mech
9075 +gss_inquire_context
9077 +gss_inquire_cred_by_mech
9078 +gss_inquire_cred_by_oid
9079 +gss_inquire_mechs_for_name
9080 +gss_inquire_mech_for_saslname
9082 +gss_inquire_names_for_mech
9083 +gss_inquire_saslname_for_mech
9084 +gss_inquire_sec_context_by_oid
9085 +gss_map_name_to_any
9086 +gss_process_context_token
9088 +gss_query_mechanism_info
9089 +gss_query_meta_data
9090 +gss_release_any_name_mapping
9093 +gss_internal_release_oid
9094 +gss_set_name_attribute
9095 +gss_set_sec_context_option
9102 +gss_wrap_iov_length
9103 +gss_wrap_size_limit
9104 +GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM
9105 +GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM
9106 +GSS_EAP_NT_EAP_NAME
9107 +GSS_EAP_CRED_SET_CRED_FLAG
9108 +GSS_EAP_CRED_SET_CRED_PASSWORD
9109 +GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE
9110 +GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA
9111 +gssspi_acquire_cred_with_password
9112 +gssspi_authorize_localname
9113 +gssspi_set_cred_option
9114 diff --git a/mech_eap/mech_invoke.c b/mech_eap/mech_invoke.c
9115 new file mode 100644
9116 index 0000000..bc9bba3
9118 +++ b/mech_eap/mech_invoke.c
9121 + * Copyright (c) 2011, JANET(UK)
9122 + * All rights reserved.
9124 + * Redistribution and use in source and binary forms, with or without
9125 + * modification, are permitted provided that the following conditions
9128 + * 1. Redistributions of source code must retain the above copyright
9129 + * notice, this list of conditions and the following disclaimer.
9131 + * 2. Redistributions in binary form must reproduce the above copyright
9132 + * notice, this list of conditions and the following disclaimer in the
9133 + * documentation and/or other materials provided with the distribution.
9135 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9136 + * may be used to endorse or promote products derived from this software
9137 + * without specific prior written permission.
9139 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9140 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9141 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9142 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9143 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9144 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9145 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9146 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9147 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9148 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9152 +#include "gssapiP_eap.h"
9154 +OM_uint32 GSSAPI_CALLCONV
9155 +gssspi_mech_invoke(OM_uint32 *minor,
9156 + const gss_OID desired_mech,
9157 + const gss_OID desired_object,
9158 + gss_buffer_t value)
9160 + *minor = GSSEAP_BAD_INVOCATION;
9162 + return GSS_S_UNAVAILABLE;
9164 diff --git a/mech_eap/process_context_token.c b/mech_eap/process_context_token.c
9165 new file mode 100644
9166 index 0000000..02a4b6d
9168 +++ b/mech_eap/process_context_token.c
9171 + * Copyright (c) 2011, JANET(UK)
9172 + * All rights reserved.
9174 + * Redistribution and use in source and binary forms, with or without
9175 + * modification, are permitted provided that the following conditions
9178 + * 1. Redistributions of source code must retain the above copyright
9179 + * notice, this list of conditions and the following disclaimer.
9181 + * 2. Redistributions in binary form must reproduce the above copyright
9182 + * notice, this list of conditions and the following disclaimer in the
9183 + * documentation and/or other materials provided with the distribution.
9185 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9186 + * may be used to endorse or promote products derived from this software
9187 + * without specific prior written permission.
9189 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9190 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9191 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9192 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9193 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9194 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9195 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9196 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9197 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9198 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9202 +#include "gssapiP_eap.h"
9204 +OM_uint32 GSSAPI_CALLCONV
9205 +gss_process_context_token(OM_uint32 *minor,
9207 + gss_buffer_t token_buffer)
9210 + gss_iov_buffer_desc iov[1];
9214 + if (ctx == NULL) {
9216 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
9219 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9221 + if (!CTX_IS_ESTABLISHED(ctx)) {
9222 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9223 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
9224 + return GSS_S_NO_CONTEXT;
9227 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
9228 + iov[0].buffer = *token_buffer;
9230 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
9231 + iov, 1, TOK_TYPE_DELETE_CONTEXT);
9232 + if (GSS_ERROR(major)) {
9233 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9237 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9239 + return gssEapReleaseContext(minor, &ctx);
9241 diff --git a/mech_eap/pseudo_random.c b/mech_eap/pseudo_random.c
9242 new file mode 100644
9243 index 0000000..61d1f2a
9245 +++ b/mech_eap/pseudo_random.c
9248 + * Copyright (c) 2011, JANET(UK)
9249 + * All rights reserved.
9251 + * Redistribution and use in source and binary forms, with or without
9252 + * modification, are permitted provided that the following conditions
9255 + * 1. Redistributions of source code must retain the above copyright
9256 + * notice, this list of conditions and the following disclaimer.
9258 + * 2. Redistributions in binary form must reproduce the above copyright
9259 + * notice, this list of conditions and the following disclaimer in the
9260 + * documentation and/or other materials provided with the distribution.
9262 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9263 + * may be used to endorse or promote products derived from this software
9264 + * without specific prior written permission.
9266 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9267 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9268 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9269 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9270 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9271 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9272 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9273 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9274 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9275 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9279 + * Copyright 2009 by the Massachusetts Institute of Technology.
9280 + * All Rights Reserved.
9282 + * Export of this software from the United States of America may
9283 + * require a specific license from the United States Government.
9284 + * It is the responsibility of any person or organization contemplating
9285 + * export to obtain such a license before exporting.
9287 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
9288 + * distribute this software and its documentation for any purpose and
9289 + * without fee is hereby granted, provided that the above copyright
9290 + * notice appear in all copies and that both that copyright notice and
9291 + * this permission notice appear in supporting documentation, and that
9292 + * the name of M.I.T. not be used in advertising or publicity pertaining
9293 + * to distribution of the software without specific, written prior
9294 + * permission. Furthermore if you modify this software you must label
9295 + * your software as modified software and not distribute it in such a
9296 + * fashion that it might be confused with the original M.I.T. software.
9297 + * M.I.T. makes no representations about the suitability of
9298 + * this software for any purpose. It is provided "as is" without express
9299 + * or implied warranty.
9306 +#include "gssapiP_eap.h"
9309 +gssEapPseudoRandom(OM_uint32 *minor,
9312 + const gss_buffer_t prf_in,
9313 + ssize_t desired_output_len,
9314 + gss_buffer_t prf_out)
9316 + krb5_error_code code;
9318 + OM_uint32 tmpMinor;
9322 + krb5_context krbContext;
9324 + prf_out->length = 0;
9325 + prf_out->value = NULL;
9329 + GSSEAP_KRB_INIT(&krbContext);
9331 + KRB_DATA_INIT(&t);
9332 + KRB_DATA_INIT(&ns);
9334 + if (prf_key != GSS_C_PRF_KEY_PARTIAL &&
9335 + prf_key != GSS_C_PRF_KEY_FULL) {
9336 + code = GSSEAP_BAD_PRF_KEY;
9340 + prf_out->value = GSSEAP_MALLOC(desired_output_len);
9341 + if (prf_out->value == NULL) {
9345 + prf_out->length = desired_output_len;
9347 + code = krb5_c_prf_length(krbContext,
9348 + ctx->encryptionType,
9353 + ns.length = 4 + prf_in->length;
9354 + ns.data = GSSEAP_MALLOC(ns.length);
9355 + if (ns.data == NULL) {
9360 +#ifndef HAVE_HEIMDAL_VERSION
9361 + /* Same API, but different allocation rules, unfortunately. */
9362 + t.length = prflen;
9363 + t.data = GSSEAP_MALLOC(t.length);
9364 + if (t.data == NULL) {
9370 + memcpy((unsigned char *)ns.data + 4, prf_in->value, prf_in->length);
9372 + p = (unsigned char *)prf_out->value;
9373 + while (desired_output_len > 0) {
9374 + store_uint32_be(i, ns.data);
9376 + code = krb5_c_prf(krbContext, &ctx->rfc3961Key, &ns, &t);
9380 + memcpy(p, t.data, MIN(t.length, desired_output_len));
9383 + desired_output_len -= t.length;
9389 + gss_release_buffer(&tmpMinor, prf_out);
9390 + if (ns.data != NULL) {
9391 + memset(ns.data, 0, ns.length);
9392 + GSSEAP_FREE(ns.data);
9394 +#ifdef HAVE_HEIMDAL_VERSION
9395 + krb5_free_data_contents(krbContext, &t);
9397 + if (t.data != NULL) {
9398 + memset(t.data, 0, t.length);
9399 + GSSEAP_FREE(t.data);
9405 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
9408 +OM_uint32 GSSAPI_CALLCONV
9409 +gss_pseudo_random(OM_uint32 *minor,
9412 + const gss_buffer_t prf_in,
9413 + ssize_t desired_output_len,
9414 + gss_buffer_t prf_out)
9418 + if (ctx == GSS_C_NO_CONTEXT) {
9420 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
9423 + prf_out->length = 0;
9424 + prf_out->value = NULL;
9428 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9430 + if (CTX_IS_ESTABLISHED(ctx)) {
9431 + major = gssEapPseudoRandom(minor, ctx, prf_key,
9432 + prf_in, desired_output_len, prf_out);
9434 + major = GSS_S_NO_CONTEXT;
9435 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
9438 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9442 diff --git a/mech_eap/query_mechanism_info.c b/mech_eap/query_mechanism_info.c
9443 new file mode 100644
9444 index 0000000..acd3115
9446 +++ b/mech_eap/query_mechanism_info.c
9449 + * Copyright (c) 2011, JANET(UK)
9450 + * All rights reserved.
9452 + * Redistribution and use in source and binary forms, with or without
9453 + * modification, are permitted provided that the following conditions
9456 + * 1. Redistributions of source code must retain the above copyright
9457 + * notice, this list of conditions and the following disclaimer.
9459 + * 2. Redistributions in binary form must reproduce the above copyright
9460 + * notice, this list of conditions and the following disclaimer in the
9461 + * documentation and/or other materials provided with the distribution.
9463 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9464 + * may be used to endorse or promote products derived from this software
9465 + * without specific prior written permission.
9467 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9468 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9469 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9470 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9471 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9472 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9473 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9474 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9475 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9476 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9484 +#include "gssapiP_eap.h"
9487 +gssQueryMechanismInfo(OM_uint32 *minor,
9488 + gss_const_OID mech_oid,
9489 + unsigned char auth_scheme[16])
9492 + krb5_enctype enctype;
9494 + major = gssEapOidToEnctype(minor, (const gss_OID)mech_oid, &enctype);
9495 + if (GSS_ERROR(major))
9498 + /* the enctype is encoded in the increasing part of the GUID */
9499 + memcpy(auth_scheme,
9500 + "\x39\xd7\x7d\x00\xe5\x00\x11\xe0\xac\x64\xcd\x53\x46\x50\xac\xb9", 16);
9502 + auth_scheme[3] = (unsigned char)enctype;
9505 + return GSS_S_COMPLETE;
9508 +OM_uint32 GSSAPI_CALLCONV
9509 +gss_query_mechanism_info(OM_uint32 *minor,
9510 + gss_const_OID mech_oid,
9511 + unsigned char auth_scheme[16])
9513 + return gssQueryMechanismInfo(minor, mech_oid, auth_scheme);
9515 diff --git a/mech_eap/query_meta_data.c b/mech_eap/query_meta_data.c
9516 new file mode 100644
9517 index 0000000..abc7e71
9519 +++ b/mech_eap/query_meta_data.c
9522 + * Copyright (c) 2011, JANET(UK)
9523 + * All rights reserved.
9525 + * Redistribution and use in source and binary forms, with or without
9526 + * modification, are permitted provided that the following conditions
9529 + * 1. Redistributions of source code must retain the above copyright
9530 + * notice, this list of conditions and the following disclaimer.
9532 + * 2. Redistributions in binary form must reproduce the above copyright
9533 + * notice, this list of conditions and the following disclaimer in the
9534 + * documentation and/or other materials provided with the distribution.
9536 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9537 + * may be used to endorse or promote products derived from this software
9538 + * without specific prior written permission.
9540 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9541 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9542 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9543 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9544 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9545 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9546 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9547 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9548 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9549 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9557 +#include "gssapiP_eap.h"
9560 +gssEapQueryMetaData(OM_uint32 *minor,
9561 + gss_const_OID mech GSSEAP_UNUSED,
9562 + gss_cred_id_t cred,
9563 + gss_ctx_id_t *context_handle,
9564 + const gss_name_t name,
9565 + OM_uint32 req_flags GSSEAP_UNUSED,
9566 + gss_buffer_t meta_data)
9568 + OM_uint32 major = GSS_S_COMPLETE;
9569 + int isInitiator = (name != GSS_C_NO_NAME);
9570 + gss_ctx_id_t ctx = *context_handle;
9572 + meta_data->length = 0;
9573 + meta_data->value = NULL;
9575 + if (ctx == GSS_C_NO_CONTEXT) {
9576 + major = gssEapAllocContext(minor, &ctx);
9577 + if (GSS_ERROR(major))
9581 + ctx->flags |= CTX_FLAG_INITIATOR;
9584 + if (ctx->cred == GSS_C_NO_CREDENTIAL) {
9585 + if (isInitiator) {
9586 + major = gssEapResolveInitiatorCred(minor, cred,
9587 + name, &ctx->cred);
9589 + major = gssEapAcquireCred(minor,
9600 + if (*context_handle == GSS_C_NO_CONTEXT)
9601 + *context_handle = ctx;
9606 +OM_uint32 GSSAPI_CALLCONV
9607 +gss_query_meta_data(OM_uint32 *minor,
9608 + gss_const_OID mech,
9609 + gss_cred_id_t cred,
9610 + gss_ctx_id_t *context_handle,
9611 + const gss_name_t name,
9612 + OM_uint32 req_flags,
9613 + gss_buffer_t meta_data)
9615 + gss_ctx_id_t ctx = *context_handle;
9618 + if (cred != GSS_C_NO_CREDENTIAL)
9619 + GSSEAP_MUTEX_LOCK(&cred->mutex);
9621 + if (*context_handle != GSS_C_NO_CONTEXT)
9622 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
9624 + major = gssEapQueryMetaData(minor, mech, cred, &ctx,
9625 + name, req_flags, meta_data);
9627 + if (*context_handle != GSS_C_NO_CONTEXT)
9628 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
9630 + *context_handle = ctx;
9632 + if (cred != GSS_C_NO_CREDENTIAL)
9633 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
9637 diff --git a/mech_eap/radius_ad.exports b/mech_eap/radius_ad.exports
9638 new file mode 100644
9639 index 0000000..8d5d5c4
9641 +++ b/mech_eap/radius_ad.exports
9644 diff --git a/mech_eap/radsec.conf b/mech_eap/radsec.conf
9645 new file mode 100644
9646 index 0000000..27f895a
9648 +++ b/mech_eap/radsec.conf
9650 +dictionary = "/usr/local/etc/raddb/dictionary"
9657 + hostname = "localhost"
9659 + secret = "testing123"
9662 diff --git a/mech_eap/radsec_err.et b/mech_eap/radsec_err.et
9663 new file mode 100644
9664 index 0000000..3b7fae2
9666 +++ b/mech_eap/radsec_err.et
9669 +# Copyright (c) 2011, JANET(UK)
9670 +# All rights reserved.
9672 +# Redistribution and use in source and binary forms, with or without
9673 +# modification, are permitted provided that the following conditions
9676 +# 1. Redistributions of source code must retain the above copyright
9677 +# notice, this list of conditions and the following disclaimer.
9679 +# 2. Redistributions in binary form must reproduce the above copyright
9680 +# notice, this list of conditions and the following disclaimer in the
9681 +# documentation and/or other materials provided with the distribution.
9683 +# 3. Neither the name of JANET(UK) nor the names of its contributors
9684 +# may be used to endorse or promote products derived from this software
9685 +# without specific prior written permission.
9687 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9688 +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9689 +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9690 +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9691 +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9692 +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9693 +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9694 +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9695 +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9696 +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9700 +# Placeholders only
9703 +error_code GSSEAP_RSE_OK, ""
9706 diff --git a/mech_eap/release_any_name_mapping.c b/mech_eap/release_any_name_mapping.c
9707 new file mode 100644
9708 index 0000000..d68fb45
9710 +++ b/mech_eap/release_any_name_mapping.c
9713 + * Copyright (c) 2011, JANET(UK)
9714 + * All rights reserved.
9716 + * Redistribution and use in source and binary forms, with or without
9717 + * modification, are permitted provided that the following conditions
9720 + * 1. Redistributions of source code must retain the above copyright
9721 + * notice, this list of conditions and the following disclaimer.
9723 + * 2. Redistributions in binary form must reproduce the above copyright
9724 + * notice, this list of conditions and the following disclaimer in the
9725 + * documentation and/or other materials provided with the distribution.
9727 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9728 + * may be used to endorse or promote products derived from this software
9729 + * without specific prior written permission.
9731 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9732 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9733 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9734 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9735 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9736 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9737 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9738 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9739 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9740 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9744 +#include "gssapiP_eap.h"
9746 +OM_uint32 GSSAPI_CALLCONV
9747 +gss_release_any_name_mapping(OM_uint32 *minor,
9749 + gss_buffer_t type_id,
9756 + if (name == GSS_C_NO_NAME) {
9758 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
9761 + GSSEAP_MUTEX_LOCK(&name->mutex);
9763 + major = gssEapReleaseAnyNameMapping(minor, name, type_id, input);
9767 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
9771 diff --git a/mech_eap/release_cred.c b/mech_eap/release_cred.c
9772 new file mode 100644
9773 index 0000000..8bb7e54
9775 +++ b/mech_eap/release_cred.c
9778 + * Copyright (c) 2011, JANET(UK)
9779 + * All rights reserved.
9781 + * Redistribution and use in source and binary forms, with or without
9782 + * modification, are permitted provided that the following conditions
9785 + * 1. Redistributions of source code must retain the above copyright
9786 + * notice, this list of conditions and the following disclaimer.
9788 + * 2. Redistributions in binary form must reproduce the above copyright
9789 + * notice, this list of conditions and the following disclaimer in the
9790 + * documentation and/or other materials provided with the distribution.
9792 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9793 + * may be used to endorse or promote products derived from this software
9794 + * without specific prior written permission.
9796 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9797 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9798 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9799 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9800 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9801 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9802 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9803 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9804 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9805 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9810 + * Release a credential handle.
9813 +#include "gssapiP_eap.h"
9815 +OM_uint32 GSSAPI_CALLCONV
9816 +gss_release_cred(OM_uint32 *minor,
9817 + gss_cred_id_t *cred_handle)
9819 + return gssEapReleaseCred(minor, cred_handle);
9821 diff --git a/mech_eap/release_name.c b/mech_eap/release_name.c
9822 new file mode 100644
9823 index 0000000..3d527ce
9825 +++ b/mech_eap/release_name.c
9828 + * Copyright (c) 2011, JANET(UK)
9829 + * All rights reserved.
9831 + * Redistribution and use in source and binary forms, with or without
9832 + * modification, are permitted provided that the following conditions
9835 + * 1. Redistributions of source code must retain the above copyright
9836 + * notice, this list of conditions and the following disclaimer.
9838 + * 2. Redistributions in binary form must reproduce the above copyright
9839 + * notice, this list of conditions and the following disclaimer in the
9840 + * documentation and/or other materials provided with the distribution.
9842 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9843 + * may be used to endorse or promote products derived from this software
9844 + * without specific prior written permission.
9846 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9847 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9848 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9849 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9850 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9851 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9852 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9853 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9854 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9855 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9863 +#include "gssapiP_eap.h"
9865 +OM_uint32 GSSAPI_CALLCONV
9866 +gss_release_name(OM_uint32 *minor,
9869 + return gssEapReleaseName(minor, name);
9871 diff --git a/mech_eap/release_oid.c b/mech_eap/release_oid.c
9872 new file mode 100644
9873 index 0000000..291da40
9875 +++ b/mech_eap/release_oid.c
9878 + * Copyright (c) 2011, JANET(UK)
9879 + * All rights reserved.
9881 + * Redistribution and use in source and binary forms, with or without
9882 + * modification, are permitted provided that the following conditions
9885 + * 1. Redistributions of source code must retain the above copyright
9886 + * notice, this list of conditions and the following disclaimer.
9888 + * 2. Redistributions in binary form must reproduce the above copyright
9889 + * notice, this list of conditions and the following disclaimer in the
9890 + * documentation and/or other materials provided with the distribution.
9892 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9893 + * may be used to endorse or promote products derived from this software
9894 + * without specific prior written permission.
9896 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9897 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9898 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9899 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9900 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9901 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9902 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9903 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9904 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9905 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9910 + * Mark an internalized OID as not required to be released.
9913 +#include "gssapiP_eap.h"
9915 +OM_uint32 GSSAPI_CALLCONV
9916 +gss_internal_release_oid(OM_uint32 *minor,
9919 + return gssEapReleaseOid(minor, oid);
9921 diff --git a/mech_eap/set_cred_option.c b/mech_eap/set_cred_option.c
9922 new file mode 100644
9923 index 0000000..7bb9b7b
9925 +++ b/mech_eap/set_cred_option.c
9928 + * Copyright (c) 2011, JANET(UK)
9929 + * All rights reserved.
9931 + * Redistribution and use in source and binary forms, with or without
9932 + * modification, are permitted provided that the following conditions
9935 + * 1. Redistributions of source code must retain the above copyright
9936 + * notice, this list of conditions and the following disclaimer.
9938 + * 2. Redistributions in binary form must reproduce the above copyright
9939 + * notice, this list of conditions and the following disclaimer in the
9940 + * documentation and/or other materials provided with the distribution.
9942 + * 3. Neither the name of JANET(UK) nor the names of its contributors
9943 + * may be used to endorse or promote products derived from this software
9944 + * without specific prior written permission.
9946 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
9947 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9948 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
9949 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
9950 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9951 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
9952 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9953 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
9954 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9955 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9960 + * Set an extended property on a credential handle.
9963 +#include "gssapiP_eap.h"
9966 +setCredRadiusConfigFile(OM_uint32 *minor,
9967 + gss_cred_id_t cred,
9968 + const gss_OID oid GSSEAP_UNUSED,
9969 + const gss_buffer_t buffer)
9971 + OM_uint32 major, tmpMinor;
9972 + gss_buffer_desc configFileBuffer = GSS_C_EMPTY_BUFFER;
9974 + if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
9975 + major = duplicateBuffer(minor, buffer, &configFileBuffer);
9976 + if (GSS_ERROR(major))
9980 + gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
9981 + cred->radiusConfigFile = configFileBuffer;
9984 + return GSS_S_COMPLETE;
9988 +setCredRadiusConfigStanza(OM_uint32 *minor,
9989 + gss_cred_id_t cred,
9990 + const gss_OID oid GSSEAP_UNUSED,
9991 + const gss_buffer_t buffer)
9993 + OM_uint32 major, tmpMinor;
9994 + gss_buffer_desc configStanzaBuffer = GSS_C_EMPTY_BUFFER;
9996 + if (buffer != GSS_C_NO_BUFFER && buffer->length != 0) {
9997 + major = duplicateBuffer(minor, buffer, &configStanzaBuffer);
9998 + if (GSS_ERROR(major))
10002 + gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
10003 + cred->radiusConfigStanza = configStanzaBuffer;
10006 + return GSS_S_COMPLETE;
10010 +setCredFlag(OM_uint32 *minor,
10011 + gss_cred_id_t cred,
10012 + const gss_OID oid GSSEAP_UNUSED,
10013 + const gss_buffer_t buffer)
10016 + unsigned char *p;
10018 + if (buffer == GSS_C_NO_BUFFER) {
10020 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_FAILURE;
10023 + if (buffer->length < 4) {
10024 + *minor = GSSEAP_WRONG_SIZE;
10025 + return GSS_S_FAILURE;
10028 + p = (unsigned char *)buffer->value;
10030 + flags = load_uint32_be(buffer->value) & CRED_FLAG_PUBLIC_MASK;
10032 + if (buffer->length > 4 && p[4])
10033 + cred->flags &= ~(flags);
10035 + cred->flags |= flags;
10038 + return GSS_S_COMPLETE;
10042 +setCredPassword(OM_uint32 *minor,
10043 + gss_cred_id_t cred,
10044 + const gss_OID oid GSSEAP_UNUSED,
10045 + const gss_buffer_t buffer)
10047 + return gssEapSetCredPassword(minor, cred, buffer);
10051 + gss_OID_desc oid;
10052 + OM_uint32 (*setOption)(OM_uint32 *, gss_cred_id_t cred,
10053 + const gss_OID, const gss_buffer_t);
10054 +} setCredOps[] = {
10055 + /* 1.3.6.1.4.1.5322.22.3.3.1 */
10057 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x01" },
10058 + setCredRadiusConfigFile,
10060 + /* 1.3.6.1.4.1.5322.22.3.3.2 */
10062 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x02" },
10063 + setCredRadiusConfigStanza,
10065 + /* 1.3.6.1.4.1.5322.22.3.3.3 */
10067 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x03" },
10070 + /* 1.3.6.1.4.1.5322.22.3.3.4 */
10072 + { 11, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x03\x03\x04" },
10077 +gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_FILE = &setCredOps[0].oid;
10078 +gss_OID GSS_EAP_CRED_SET_RADIUS_CONFIG_STANZA = &setCredOps[1].oid;
10079 +gss_OID GSS_EAP_CRED_SET_CRED_FLAG = &setCredOps[2].oid;
10080 +gss_OID GSS_EAP_CRED_SET_CRED_PASSWORD = &setCredOps[3].oid;
10082 +OM_uint32 GSSAPI_CALLCONV
10083 +gssspi_set_cred_option(OM_uint32 *minor,
10084 + gss_cred_id_t *pCred,
10085 + const gss_OID desired_object,
10086 + const gss_buffer_t value)
10089 + gss_cred_id_t cred = *pCred;
10092 + if (cred == GSS_C_NO_CREDENTIAL) {
10094 + return GSS_S_UNAVAILABLE;
10097 + GSSEAP_MUTEX_LOCK(&cred->mutex);
10099 + major = GSS_S_UNAVAILABLE;
10100 + *minor = GSSEAP_BAD_CRED_OPTION;
10102 + for (i = 0; i < sizeof(setCredOps) / sizeof(setCredOps[0]); i++) {
10103 + if (oidEqual(&setCredOps[i].oid, desired_object)) {
10104 + major = (*setCredOps[i].setOption)(minor, cred,
10105 + desired_object, value);
10110 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
10117 +gsseap_set_cred_flag(OM_uint32 *minor,
10118 + gss_cred_id_t cred,
10122 + unsigned char buf[5];
10123 + gss_buffer_desc value;
10125 + value.length = sizeof(buf);
10126 + value.value = buf;
10128 + store_uint32_be(flag, buf);
10129 + buf[4] = (clear != 0);
10131 + return gssspi_set_cred_option(minor, &cred,
10132 + GSS_EAP_CRED_SET_CRED_FLAG, &value);
10135 diff --git a/mech_eap/set_name_attribute.c b/mech_eap/set_name_attribute.c
10136 new file mode 100644
10137 index 0000000..2ccf5d7
10139 +++ b/mech_eap/set_name_attribute.c
10142 + * Copyright (c) 2011, JANET(UK)
10143 + * All rights reserved.
10145 + * Redistribution and use in source and binary forms, with or without
10146 + * modification, are permitted provided that the following conditions
10149 + * 1. Redistributions of source code must retain the above copyright
10150 + * notice, this list of conditions and the following disclaimer.
10152 + * 2. Redistributions in binary form must reproduce the above copyright
10153 + * notice, this list of conditions and the following disclaimer in the
10154 + * documentation and/or other materials provided with the distribution.
10156 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10157 + * may be used to endorse or promote products derived from this software
10158 + * without specific prior written permission.
10160 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10161 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10162 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10163 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10164 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10165 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10166 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10167 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10168 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10169 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10174 + * Set an attribute on a name.
10177 +#include "gssapiP_eap.h"
10179 +OM_uint32 GSSAPI_CALLCONV
10180 +gss_set_name_attribute(OM_uint32 *minor,
10183 + gss_buffer_t attr,
10184 + gss_buffer_t value)
10188 + if (name == GSS_C_NO_NAME) {
10190 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
10193 + GSSEAP_MUTEX_LOCK(&name->mutex);
10195 + major = gssEapSetNameAttribute(minor, name, complete, attr, value);
10197 + GSSEAP_MUTEX_UNLOCK(&name->mutex);
10201 diff --git a/mech_eap/set_sec_context_option.c b/mech_eap/set_sec_context_option.c
10202 new file mode 100644
10203 index 0000000..f9fa3a6
10205 +++ b/mech_eap/set_sec_context_option.c
10208 + * Copyright (c) 2011, JANET(UK)
10209 + * All rights reserved.
10211 + * Redistribution and use in source and binary forms, with or without
10212 + * modification, are permitted provided that the following conditions
10215 + * 1. Redistributions of source code must retain the above copyright
10216 + * notice, this list of conditions and the following disclaimer.
10218 + * 2. Redistributions in binary form must reproduce the above copyright
10219 + * notice, this list of conditions and the following disclaimer in the
10220 + * documentation and/or other materials provided with the distribution.
10222 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10223 + * may be used to endorse or promote products derived from this software
10224 + * without specific prior written permission.
10226 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10227 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10228 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10229 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10230 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10231 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10232 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10233 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10234 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10235 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10240 + * Set an extended property on a context handle.
10243 +#include "gssapiP_eap.h"
10247 + gss_OID_desc oid;
10248 + OM_uint32 (*setOption)(OM_uint32 *, gss_ctx_id_t *pCtx,
10249 + const gss_OID, const gss_buffer_t);
10254 +OM_uint32 GSSAPI_CALLCONV
10255 +gss_set_sec_context_option(OM_uint32 *minor,
10256 + gss_ctx_id_t *pCtx,
10257 + const gss_OID desired_object GSSEAP_UNUSED,
10258 + const gss_buffer_t value GSSEAP_UNUSED)
10261 + gss_ctx_id_t ctx;
10266 + major = GSS_S_UNAVAILABLE;
10267 + *minor = GSSEAP_BAD_CONTEXT_OPTION;
10269 + if (pCtx == NULL)
10270 + ctx = GSS_C_NO_CONTEXT;
10274 + if (ctx != GSS_C_NO_CONTEXT)
10275 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
10278 + for (i = 0; i < sizeof(setCtxOps) / sizeof(setCtxOps[0]); i++) {
10279 + if (oidEqual(&setCtxOps[i].oid, desired_object)) {
10280 + major = (*setCtxOps[i].setOption)(minor, &ctx,
10281 + desired_object, value);
10287 + if (pCtx != NULL && *pCtx == NULL)
10289 + else if (ctx != GSS_C_NO_CONTEXT)
10290 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
10294 diff --git a/mech_eap/store_cred.c b/mech_eap/store_cred.c
10295 new file mode 100644
10296 index 0000000..d17a3ac
10298 +++ b/mech_eap/store_cred.c
10301 + * Copyright (c) 2011, JANET(UK)
10302 + * All rights reserved.
10304 + * Redistribution and use in source and binary forms, with or without
10305 + * modification, are permitted provided that the following conditions
10308 + * 1. Redistributions of source code must retain the above copyright
10309 + * notice, this list of conditions and the following disclaimer.
10311 + * 2. Redistributions in binary form must reproduce the above copyright
10312 + * notice, this list of conditions and the following disclaimer in the
10313 + * documentation and/or other materials provided with the distribution.
10315 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10316 + * may be used to endorse or promote products derived from this software
10317 + * without specific prior written permission.
10319 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10320 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10321 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10322 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10323 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10324 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10325 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10326 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10327 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10328 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10332 +#include "gssapiP_eap.h"
10334 +OM_uint32 GSSAPI_CALLCONV
10335 +gss_store_cred(OM_uint32 *minor,
10336 + const gss_cred_id_t cred,
10337 + gss_cred_usage_t input_usage,
10338 + const gss_OID desired_mech GSSEAP_UNUSED,
10339 +#ifdef GSSEAP_ENABLE_REAUTH
10340 + OM_uint32 overwrite_cred,
10341 + OM_uint32 default_cred,
10343 + OM_uint32 overwrite_cred GSSEAP_UNUSED,
10344 + OM_uint32 default_cred GSSEAP_UNUSED,
10346 + gss_OID_set *elements_stored,
10347 + gss_cred_usage_t *cred_usage_stored)
10351 + if (elements_stored != NULL)
10352 + *elements_stored = GSS_C_NO_OID_SET;
10353 + if (cred_usage_stored != NULL)
10354 + *cred_usage_stored = input_usage;
10356 + if (cred == GSS_C_NO_CREDENTIAL) {
10358 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED;
10361 + GSSEAP_MUTEX_LOCK(&cred->mutex);
10363 + major = GSS_S_COMPLETE;
10366 +#ifdef GSSEAP_ENABLE_REAUTH
10367 + if (cred->reauthCred != GSS_C_NO_CREDENTIAL) {
10368 + major = gssStoreCred(minor,
10369 + cred->reauthCred,
10371 + (gss_OID)gss_mech_krb5,
10375 + cred_usage_stored);
10379 + GSSEAP_MUTEX_UNLOCK(&cred->mutex);
10383 diff --git a/mech_eap/unwrap.c b/mech_eap/unwrap.c
10384 new file mode 100644
10385 index 0000000..a185035
10387 +++ b/mech_eap/unwrap.c
10390 + * Copyright (c) 2011, JANET(UK)
10391 + * All rights reserved.
10393 + * Redistribution and use in source and binary forms, with or without
10394 + * modification, are permitted provided that the following conditions
10397 + * 1. Redistributions of source code must retain the above copyright
10398 + * notice, this list of conditions and the following disclaimer.
10400 + * 2. Redistributions in binary form must reproduce the above copyright
10401 + * notice, this list of conditions and the following disclaimer in the
10402 + * documentation and/or other materials provided with the distribution.
10404 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10405 + * may be used to endorse or promote products derived from this software
10406 + * without specific prior written permission.
10408 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10409 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10410 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10411 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10412 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10413 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10414 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10415 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10416 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10417 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10422 + * Message protection services: unwrap.
10425 +#include "gssapiP_eap.h"
10427 +OM_uint32 GSSAPI_CALLCONV
10428 +gss_unwrap(OM_uint32 *minor,
10429 + gss_ctx_id_t ctx,
10430 + gss_buffer_t input_message_buffer,
10431 + gss_buffer_t output_message_buffer,
10433 + gss_qop_t *qop_state)
10435 + OM_uint32 major, tmpMinor;
10436 + gss_iov_buffer_desc iov[2];
10438 + if (ctx == GSS_C_NO_CONTEXT) {
10440 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
10445 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
10447 + if (!CTX_IS_ESTABLISHED(ctx)) {
10448 + major = GSS_S_NO_CONTEXT;
10449 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
10453 + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
10454 + iov[0].buffer = *input_message_buffer;
10456 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;
10457 + iov[1].buffer.value = NULL;
10458 + iov[1].buffer.length = 0;
10460 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
10461 + iov, 2, TOK_TYPE_WRAP);
10462 + if (major == GSS_S_COMPLETE) {
10463 + *output_message_buffer = iov[1].buffer;
10465 + if (iov[1].type & GSS_IOV_BUFFER_FLAG_ALLOCATED)
10466 + gss_release_buffer(&tmpMinor, &iov[1].buffer);
10470 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
10474 diff --git a/mech_eap/unwrap_iov.c b/mech_eap/unwrap_iov.c
10475 new file mode 100644
10476 index 0000000..5ceefa2
10478 +++ b/mech_eap/unwrap_iov.c
10481 + * Copyright (c) 2011, JANET(UK)
10482 + * All rights reserved.
10484 + * Redistribution and use in source and binary forms, with or without
10485 + * modification, are permitted provided that the following conditions
10488 + * 1. Redistributions of source code must retain the above copyright
10489 + * notice, this list of conditions and the following disclaimer.
10491 + * 2. Redistributions in binary form must reproduce the above copyright
10492 + * notice, this list of conditions and the following disclaimer in the
10493 + * documentation and/or other materials provided with the distribution.
10495 + * 3. Neither the name of JANET(UK) nor the names of its contributors
10496 + * may be used to endorse or promote products derived from this software
10497 + * without specific prior written permission.
10499 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
10500 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10501 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10502 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
10503 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
10504 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10505 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10506 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
10507 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
10508 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
10512 + * Copyright 2008 by the Massachusetts Institute of Technology.
10513 + * All Rights Reserved.
10515 + * Export of this software from the United States of America may
10516 + * require a specific license from the United States Government.
10517 + * It is the responsibility of any person or organization contemplating
10518 + * export to obtain such a license before exporting.
10520 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10521 + * distribute this software and its documentation for any purpose and
10522 + * without fee is hereby granted, provided that the above copyright
10523 + * notice appear in all copies and that both that copyright notice and
10524 + * this permission notice appear in supporting documentation, and that
10525 + * the name of M.I.T. not be used in advertising or publicity pertaining
10526 + * to distribution of the software without specific, written prior
10527 + * permission. Furthermore if you modify this software you must label
10528 + * your software as modified software and not distribute it in such a
10529 + * fashion that it might be confused with the original M.I.T. software.
10530 + * M.I.T. makes no representations about the suitability of
10531 + * this software for any purpose. It is provided "as is" without express
10532 + * or implied warranty.
10536 + * Message protection services: unwrap with scatter-gather API.
10539 +#include "gssapiP_eap.h"
10542 + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except
10543 + * for DCE in which case it can just provide TOKEN | DATA (must
10544 + * guarantee that DATA is padded)
10547 +unwrapToken(OM_uint32 *minor,
10548 + gss_ctx_id_t ctx,
10549 +#ifdef HAVE_HEIMDAL_VERSION
10550 + krb5_crypto krbCrypto,
10552 + krb5_keyblock *unused GSSEAP_UNUSED,
10555 + gss_qop_t *qop_state,
10556 + gss_iov_buffer_desc *iov,
10558 + enum gss_eap_token_type toktype)
10560 + OM_uint32 major = GSS_S_FAILURE, code;
10561 + gss_iov_buffer_t header;
10562 + gss_iov_buffer_t padding;
10563 + gss_iov_buffer_t trailer;
10564 + unsigned char flags;
10565 + unsigned char *ptr = NULL;
10568 + size_t dataLen, assocDataLen;
10571 + int conf_flag = 0;
10572 + krb5_context krbContext;
10573 +#ifdef HAVE_HEIMDAL_VERSION
10574 + int freeCrypto = (krbCrypto == NULL);
10577 + GSSEAP_KRB_INIT(&krbContext);
10581 + if (qop_state != NULL)
10582 + *qop_state = GSS_C_QOP_DEFAULT;
10584 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
10585 + GSSEAP_ASSERT(header != NULL);
10587 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
10588 + if (padding != NULL && padding->buffer.length != 0) {
10589 + code = GSSEAP_BAD_PADDING_IOV;
10590 + major = GSS_S_DEFECTIVE_TOKEN;
10594 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
10596 + flags = rfc4121Flags(ctx, TRUE);
10598 + if (toktype == TOK_TYPE_WRAP) {
10599 + keyUsage = !CTX_IS_INITIATOR(ctx)
10600 + ? KEY_USAGE_INITIATOR_SEAL
10601 + : KEY_USAGE_ACCEPTOR_SEAL;
10603 + keyUsage = !CTX_IS_INITIATOR(ctx)
10604 + ? KEY_USAGE_INITIATOR_SIGN
10605 + : KEY_USAGE_ACCEPTOR_SIGN;
10608 + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
10610 + ptr = (unsigned char *)header->buffer.value;
10612 + if (header->buffer.length < 16) {
10613 + code = GSSEAP_TOK_TRUNC;
10614 + major = GSS_S_DEFECTIVE_TOKEN;
10618 + if ((ptr[2] & flags) != flags) {
10619 + code = GSSEAP_BAD_DIRECTION;
10620 + major = GSS_S_BAD_SIG;
10624 +#ifdef HAVE_HEIMDAL_VERSION
10625 + if (krbCrypto == NULL) {
10626 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key,
10627 + ETYPE_NULL, &krbCrypto);
10633 + if (toktype == TOK_TYPE_WRAP) {
10634 + size_t krbTrailerLen;
10636 + if (load_uint16_be(ptr) != TOK_TYPE_WRAP)
10638 + conf_flag = ((ptr[2] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
10639 + if (ptr[3] != 0xFF)
10641 + ec = load_uint16_be(ptr + 4);
10642 + rrc = load_uint16_be(ptr + 6);
10643 + seqnum = load_uint64_be(ptr + 8);
10645 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10646 + conf_flag ? KRB5_CRYPTO_TYPE_TRAILER :
10647 + KRB5_CRYPTO_TYPE_CHECKSUM,
10652 + /* Deal with RRC */
10653 + if (trailer == NULL) {
10654 + size_t desired_rrc = krbTrailerLen;
10657 + desired_rrc += 16; /* E(Header) */
10659 + if ((ctx->gssFlags & GSS_C_DCE_STYLE) == 0)
10660 + desired_rrc += ec;
10663 + /* According to MS, we only need to deal with a fixed RRC for DCE */
10664 + if (rrc != desired_rrc)
10666 + } else if (rrc != 0) {
10671 + unsigned char *althdr;
10674 + code = gssEapDecrypt(krbContext,
10675 + ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0),
10676 + ec, rrc, KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10679 + major = GSS_S_BAD_SIG;
10683 + /* Validate header integrity */
10684 + if (trailer == NULL)
10685 + althdr = (unsigned char *)header->buffer.value + 16 + ec;
10687 + althdr = (unsigned char *)trailer->buffer.value + ec;
10689 + if (load_uint16_be(althdr) != TOK_TYPE_WRAP
10690 + || althdr[2] != ptr[2]
10691 + || althdr[3] != ptr[3]
10692 + || memcmp(althdr + 8, ptr + 8, 8) != 0) {
10693 + code = GSSEAP_BAD_WRAP_TOKEN;
10694 + major = GSS_S_BAD_SIG;
10698 + /* Verify checksum: note EC is checksum size here, not padding */
10699 + if (ec != krbTrailerLen)
10702 + /* Zero EC, RRC before computing checksum */
10703 + store_uint16_be(0, ptr + 4);
10704 + store_uint16_be(0, ptr + 6);
10706 + code = gssEapVerify(krbContext, ctx->checksumType, rrc,
10707 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10708 + iov, iov_count, &valid);
10709 + if (code != 0 || valid == FALSE) {
10710 + major = GSS_S_BAD_SIG;
10715 + code = sequenceCheck(minor, &ctx->seqState, seqnum);
10716 + } else if (toktype == TOK_TYPE_MIC) {
10717 + if (load_uint16_be(ptr) != toktype)
10721 + if (ptr[3] != 0xFF)
10723 + seqnum = load_uint64_be(ptr + 8);
10726 + * Although MIC tokens don't have a RRC, they are similarly
10727 + * composed of a header and a checksum. So the verify_mic()
10728 + * can be implemented with a single header buffer, fake the
10729 + * RRC to the putative trailer length if no trailer buffer.
10731 + code = gssEapVerify(krbContext, ctx->checksumType,
10732 + trailer != NULL ? 0 : header->buffer.length - 16,
10733 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
10734 + iov, iov_count, &valid);
10735 + if (code != 0 || valid == FALSE) {
10736 + major = GSS_S_BAD_SIG;
10739 + code = sequenceCheck(minor, &ctx->seqState, seqnum);
10740 + } else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
10741 + if (load_uint16_be(ptr) != TOK_TYPE_DELETE_CONTEXT)
10743 + goto verify_mic_1;
10748 + if (conf_state != NULL)
10749 + *conf_state = conf_flag;
10752 + major = GSS_S_COMPLETE;
10756 + code = GSSEAP_BAD_WRAP_TOKEN;
10757 + major = GSS_S_DEFECTIVE_TOKEN;
10761 +#ifdef HAVE_HEIMDAL_VERSION
10762 + if (freeCrypto && krbCrypto != NULL)
10763 + krb5_crypto_destroy(krbContext, krbCrypto);
10770 +rotateLeft(void *ptr, size_t bufsiz, size_t rc)
10776 + rc = rc % bufsiz;
10780 + tbuf = GSSEAP_MALLOC(rc);
10781 + if (tbuf == NULL)
10784 + memcpy(tbuf, ptr, rc);
10785 + memmove(ptr, (char *)ptr + rc, bufsiz - rc);
10786 + memcpy((char *)ptr + bufsiz - rc, tbuf, rc);
10787 + GSSEAP_FREE(tbuf);
10793 + * Split a STREAM | SIGN_DATA | DATA into
10794 + * HEADER | SIGN_DATA | DATA | PADDING | TRAILER
10797 +unwrapStream(OM_uint32 *minor,
10798 + gss_ctx_id_t ctx,
10800 + gss_qop_t *qop_state,
10801 + gss_iov_buffer_desc *iov,
10803 + enum gss_eap_token_type toktype)
10805 + unsigned char *ptr;
10806 + OM_uint32 code = 0, major = GSS_S_FAILURE;
10807 + krb5_context krbContext;
10808 + int conf_req_flag;
10810 + gss_iov_buffer_desc *tiov = NULL;
10811 + gss_iov_buffer_t stream, data = NULL;
10812 + gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer;
10813 +#ifdef HAVE_HEIMDAL_VERSION
10814 + krb5_crypto krbCrypto = NULL;
10817 + GSSEAP_KRB_INIT(&krbContext);
10819 + GSSEAP_ASSERT(toktype == TOK_TYPE_WRAP);
10821 + if (toktype != TOK_TYPE_WRAP) {
10822 + code = GSSEAP_WRONG_TOK_ID;
10826 + stream = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM);
10827 + GSSEAP_ASSERT(stream != NULL);
10829 + if (stream->buffer.length < 16) {
10830 + major = GSS_S_DEFECTIVE_TOKEN;
10834 + ptr = (unsigned char *)stream->buffer.value;
10835 + ptr += 2; /* skip token type */
10837 + tiov = (gss_iov_buffer_desc *)GSSEAP_CALLOC((size_t)iov_count + 2,
10838 + sizeof(gss_iov_buffer_desc));
10839 + if (tiov == NULL) {
10845 + theader = &tiov[i++];
10846 + theader->type = GSS_IOV_BUFFER_TYPE_HEADER;
10847 + theader->buffer.value = stream->buffer.value;
10848 + theader->buffer.length = 16;
10850 + /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */
10851 + for (j = 0; j < iov_count; j++) {
10852 + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type);
10854 + if (type == GSS_IOV_BUFFER_TYPE_DATA) {
10855 + if (data != NULL) {
10856 + /* only a single DATA buffer can appear */
10857 + code = GSSEAP_BAD_STREAM_IOV;
10862 + tdata = &tiov[i];
10864 + if (type == GSS_IOV_BUFFER_TYPE_DATA ||
10865 + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
10866 + tiov[i++] = iov[j];
10869 + if (data == NULL) {
10870 + /* a single DATA buffer must be present */
10871 + code = GSSEAP_BAD_STREAM_IOV;
10875 + /* PADDING | TRAILER */
10876 + tpadding = &tiov[i++];
10877 + tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING;
10878 + tpadding->buffer.length = 0;
10879 + tpadding->buffer.value = NULL;
10881 + ttrailer = &tiov[i++];
10882 + ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER;
10884 +#ifdef HAVE_HEIMDAL_VERSION
10885 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
10892 + size_t krbHeaderLen = 0;
10893 + size_t krbTrailerLen = 0;
10895 + conf_req_flag = ((ptr[0] & TOK_FLAG_WRAP_CONFIDENTIAL) != 0);
10896 + ec = conf_req_flag ? load_uint16_be(ptr + 2) : 0;
10897 + rrc = load_uint16_be(ptr + 4);
10900 + code = rotateLeft((unsigned char *)stream->buffer.value + 16,
10901 + stream->buffer.length - 16, rrc);
10904 + store_uint16_be(0, ptr + 4); /* set RRC to zero */
10907 + if (conf_req_flag) {
10908 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10909 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
10912 + theader->buffer.length += krbHeaderLen; /* length validated later */
10915 + /* no PADDING for CFX, EC is used instead */
10916 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
10918 + ? KRB5_CRYPTO_TYPE_TRAILER
10919 + : KRB5_CRYPTO_TYPE_CHECKSUM,
10924 + ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) +
10926 + ttrailer->buffer.value = (unsigned char *)stream->buffer.value +
10927 + stream->buffer.length - ttrailer->buffer.length;
10930 + /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/
10931 + /* CFX: GSS-Header | Kerb-Header | Data | | EC | E(Header) | Kerb-Trailer */
10932 + /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/
10934 + /* validate lengths */
10935 + if (stream->buffer.length < theader->buffer.length +
10936 + tpadding->buffer.length +
10937 + ttrailer->buffer.length) {
10938 + major = GSS_S_DEFECTIVE_TOKEN;
10939 + code = GSSEAP_TOK_TRUNC;
10944 + tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length -
10945 + tpadding->buffer.length - theader->buffer.length;
10947 + GSSEAP_ASSERT(data != NULL);
10949 + if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
10950 + code = gssEapAllocIov(tdata, tdata->buffer.length);
10954 + memcpy(tdata->buffer.value,
10955 + (unsigned char *)stream->buffer.value + theader->buffer.length,
10956 + tdata->buffer.length);
10958 + tdata->buffer.value = (unsigned char *)stream->buffer.value +
10959 + theader->buffer.length;
10962 + GSSEAP_ASSERT(i <= iov_count + 2);
10964 + major = unwrapToken(&code, ctx, KRB_CRYPTO_CONTEXT(ctx),
10965 + conf_state, qop_state, tiov, i, toktype);
10966 + if (major == GSS_S_COMPLETE) {
10968 + } else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
10971 + gss_release_buffer(&tmp, &tdata->buffer);
10972 + tdata->type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
10976 + if (tiov != NULL)
10977 + GSSEAP_FREE(tiov);
10978 +#ifdef HAVE_HEIMDAL_VERSION
10979 + if (krbCrypto != NULL)
10980 + krb5_crypto_destroy(krbContext, krbCrypto);
10989 +gssEapUnwrapOrVerifyMIC(OM_uint32 *minor,
10990 + gss_ctx_id_t ctx,
10992 + gss_qop_t *qop_state,
10993 + gss_iov_buffer_desc *iov,
10995 + enum gss_eap_token_type toktype)
10999 + if (ctx->encryptionType == ENCTYPE_NULL) {
11000 + *minor = GSSEAP_KEY_UNAVAILABLE;
11001 + return GSS_S_UNAVAILABLE;
11004 + if (gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) {
11005 + major = unwrapStream(minor, ctx, conf_state, qop_state,
11006 + iov, iov_count, toktype);
11008 + major = unwrapToken(minor, ctx,
11009 + NULL, /* krbCrypto */
11010 + conf_state, qop_state,
11011 + iov, iov_count, toktype);
11017 +OM_uint32 GSSAPI_CALLCONV
11018 +gss_unwrap_iov(OM_uint32 *minor,
11019 + gss_ctx_id_t ctx,
11021 + gss_qop_t *qop_state,
11022 + gss_iov_buffer_desc *iov,
11027 + if (ctx == GSS_C_NO_CONTEXT) {
11029 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
11034 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
11036 + if (!CTX_IS_ESTABLISHED(ctx)) {
11037 + major = GSS_S_NO_CONTEXT;
11038 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
11042 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, conf_state, qop_state,
11043 + iov, iov_count, TOK_TYPE_WRAP);
11044 + if (GSS_ERROR(major))
11048 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
11052 diff --git a/mech_eap/util.h b/mech_eap/util.h
11053 new file mode 100644
11054 index 0000000..4f54d41
11056 +++ b/mech_eap/util.h
11059 + * Copyright (c) 2011, JANET(UK)
11060 + * All rights reserved.
11062 + * Redistribution and use in source and binary forms, with or without
11063 + * modification, are permitted provided that the following conditions
11066 + * 1. Redistributions of source code must retain the above copyright
11067 + * notice, this list of conditions and the following disclaimer.
11069 + * 2. Redistributions in binary form must reproduce the above copyright
11070 + * notice, this list of conditions and the following disclaimer in the
11071 + * documentation and/or other materials provided with the distribution.
11073 + * 3. Neither the name of JANET(UK) nor the names of its contributors
11074 + * may be used to endorse or promote products derived from this software
11075 + * without specific prior written permission.
11077 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
11078 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
11079 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11080 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
11081 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
11082 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
11083 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11084 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
11085 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
11086 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
11090 + * Portions Copyright 2003-2010 Massachusetts Institute of Technology.
11091 + * All Rights Reserved.
11093 + * Export of this software from the United States of America may
11094 + * require a specific license from the United States Government.
11095 + * It is the responsibility of any person or organization contemplating
11096 + * export to obtain such a license before exporting.
11098 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
11099 + * distribute this software and its documentation for any purpose and
11100 + * without fee is hereby granted, provided that the above copyright
11101 + * notice appear in all copies and that both that copyright notice and
11102 + * this permission notice appear in supporting documentation, and that
11103 + * the name of M.I.T. not be used in advertising or publicity pertaining
11104 + * to distribution of the software without specific, written prior
11105 + * permission. Furthermore if you modify this software you must label
11106 + * your software as modified software and not distribute it in such a
11107 + * fashion that it might be confused with the original M.I.T. software.
11108 + * M.I.T. makes no representations about the suitability of
11109 + * this software for any purpose. It is provided "as is" without express
11110 + * or implied warranty.
11115 + * Utility functions.
11119 +#define _UTIL_H_ 1
11121 +#ifdef HAVE_SYS_PARAM_H
11122 +#include <sys/param.h>
11124 +#ifdef HAVE_STDINT_H
11125 +#include <stdint.h>
11127 +#include <string.h>
11128 +#include <errno.h>
11133 +#define inline __inline
11134 +#define snprintf _snprintf
11137 +#ifdef __cplusplus
11142 +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
11145 +#if !defined(WIN32) && !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
11146 +#define GSSEAP_UNUSED __attribute__ ((__unused__))
11148 +#define GSSEAP_UNUSED
11151 +/* util_buffer.c */
11153 +makeStringBuffer(OM_uint32 *minor,
11154 + const char *string,
11155 + gss_buffer_t buffer);
11157 +#define makeStringBufferOrCleanup(src, dst) \
11159 + major = makeStringBuffer((minor), (src), (dst));\
11160 + if (GSS_ERROR(major)) \
11165 +bufferToString(OM_uint32 *minor,
11166 + const gss_buffer_t buffer,
11170 +duplicateBuffer(OM_uint32 *minor,
11171 + const gss_buffer_t src,
11172 + gss_buffer_t dst);
11174 +#define duplicateBufferOrCleanup(src, dst) \
11176 + major = duplicateBuffer((minor), (src), (dst)); \
11177 + if (GSS_ERROR(major)) \
11182 +bufferEqual(const gss_buffer_t b1, const gss_buffer_t b2)
11184 + return (b1->length == b2->length &&
11185 + memcmp(b1->value, b2->value, b2->length) == 0);
11189 +bufferEqualString(const gss_buffer_t b1, const char *s)
11191 + gss_buffer_desc b2;
11193 + b2.length = strlen(s);
11194 + b2.value = (char *)s;
11196 + return bufferEqual(b1, &b2);
11199 +/* util_cksum.c */
11201 +gssEapSign(krb5_context context,
11202 + krb5_cksumtype type,
11204 +#ifdef HAVE_HEIMDAL_VERSION
11205 + krb5_crypto crypto,
11207 + krb5_keyblock *key,
11209 + krb5_keyusage sign_usage,
11210 + gss_iov_buffer_desc *iov,
11214 +gssEapVerify(krb5_context context,
11215 + krb5_cksumtype type,
11217 +#ifdef HAVE_HEIMDAL_VERSION
11218 + krb5_crypto crypto,
11220 + krb5_keyblock *key,
11222 + krb5_keyusage sign_usage,
11223 + gss_iov_buffer_desc *iov,
11229 +gssEapEncodeGssChannelBindings(OM_uint32 *minor,
11230 + gss_channel_bindings_t chanBindings,
11231 + gss_buffer_t encodedBindings);
11234 +/* util_context.c */
11235 +#define EAP_EXPORT_CONTEXT_V1 1
11237 +enum gss_eap_token_type {
11238 + TOK_TYPE_NONE = 0x0000, /* no token */
11239 + TOK_TYPE_MIC = 0x0404, /* RFC 4121 MIC token */
11240 + TOK_TYPE_WRAP = 0x0504, /* RFC 4121 wrap token */
11241 + TOK_TYPE_EXPORT_NAME = 0x0401, /* RFC 2743 exported name */
11242 + TOK_TYPE_EXPORT_NAME_COMPOSITE = 0x0402, /* exported composite name */
11243 + TOK_TYPE_DELETE_CONTEXT = 0x0405, /* RFC 2743 delete context */
11244 + TOK_TYPE_INITIATOR_CONTEXT = 0x0601, /* initiator-sent context token */
11245 + TOK_TYPE_ACCEPTOR_CONTEXT = 0x0602, /* acceptor-sent context token */
11248 +/* inner token types and flags */
11249 +#define ITOK_TYPE_NONE 0x00000000
11250 +#define ITOK_TYPE_CONTEXT_ERR 0x00000001 /* critical */
11251 +#define ITOK_TYPE_ACCEPTOR_NAME_REQ 0x00000002 /* TBD */
11252 +#define ITOK_TYPE_ACCEPTOR_NAME_RESP 0x00000003 /* TBD */
11253 +#define ITOK_TYPE_EAP_RESP 0x00000004 /* critical, required, if not reauth */
11254 +#define ITOK_TYPE_EAP_REQ 0x00000005 /* critical, required, if not reauth */
11255 +#define ITOK_TYPE_GSS_CHANNEL_BINDINGS 0x00000006 /* critical, required, if not reauth */
11256 +#define ITOK_TYPE_REAUTH_CREDS 0x00000007 /* optional */
11257 +#define ITOK_TYPE_REAUTH_REQ 0x00000008 /* optional */
11258 +#define ITOK_TYPE_REAUTH_RESP 0x00000009 /* optional */
11259 +#define ITOK_TYPE_VERSION_INFO 0x0000000A /* optional */
11260 +#define ITOK_TYPE_VENDOR_INFO 0x0000000B /* optional */
11261 +#define ITOK_TYPE_GSS_FLAGS 0x0000000C /* optional */
11262 +#define ITOK_TYPE_INITIATOR_MIC 0x0000000D /* critical, required, if not reauth */
11263 +#define ITOK_TYPE_ACCEPTOR_MIC 0x0000000E /* TBD */
11265 +#define ITOK_FLAG_CRITICAL 0x80000000 /* critical, wire flag */
11266 +#define ITOK_FLAG_VERIFIED 0x40000000 /* verified, API flag */
11268 +#define ITOK_TYPE_MASK (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
11270 +#define GSSEAP_WIRE_FLAGS_MASK ( GSS_C_MUTUAL_FLAG | \
11271 + GSS_C_DCE_STYLE | \
11272 + GSS_C_IDENTIFY_FLAG | \
11273 + GSS_C_EXTENDED_ERROR_FLAG )
11275 +OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
11276 +OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
11279 +gssEapMakeToken(OM_uint32 *minor,
11280 + gss_ctx_id_t ctx,
11281 + const gss_buffer_t innerToken,
11282 + enum gss_eap_token_type tokenType,
11283 + gss_buffer_t outputToken);
11286 +gssEapVerifyToken(OM_uint32 *minor,
11287 + gss_ctx_id_t ctx,
11288 + const gss_buffer_t inputToken,
11289 + enum gss_eap_token_type *tokenType,
11290 + gss_buffer_t innerInputToken);
11293 +gssEapContextTime(OM_uint32 *minor,
11294 + gss_ctx_id_t context_handle,
11295 + OM_uint32 *time_rec);
11298 +gssEapMakeTokenMIC(OM_uint32 *minor,
11299 + gss_ctx_id_t ctx,
11300 + gss_buffer_t tokenMIC);
11303 +gssEapVerifyTokenMIC(OM_uint32 *minor,
11304 + gss_ctx_id_t ctx,
11305 + const gss_buffer_t tokenMIC);
11308 +OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
11309 +OM_uint32 gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred);
11312 +gssEapPrimaryMechForCred(gss_cred_id_t cred);
11315 +gssEapAcquireCred(OM_uint32 *minor,
11316 + const gss_name_t desiredName,
11317 + OM_uint32 timeReq,
11318 + const gss_OID_set desiredMechs,
11320 + gss_cred_id_t *pCred,
11321 + gss_OID_set *pActualMechs,
11322 + OM_uint32 *timeRec);
11325 +gssEapSetCredPassword(OM_uint32 *minor,
11326 + gss_cred_id_t cred,
11327 + const gss_buffer_t password);
11330 +gssEapSetCredService(OM_uint32 *minor,
11331 + gss_cred_id_t cred,
11332 + const gss_name_t target);
11335 +gssEapResolveInitiatorCred(OM_uint32 *minor,
11336 + const gss_cred_id_t cred,
11337 + const gss_name_t target,
11338 + gss_cred_id_t *resolvedCred);
11340 +int gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech);
11343 +gssEapInquireCred(OM_uint32 *minor,
11344 + gss_cred_id_t cred,
11345 + gss_name_t *name,
11346 + OM_uint32 *pLifetime,
11347 + gss_cred_usage_t *cred_usage,
11348 + gss_OID_set *mechanisms);
11350 +/* util_crypt.c */
11352 +gssEapEncrypt(krb5_context context, int dce_style, size_t ec,
11354 +#ifdef HAVE_HEIMDAL_VERSION
11355 + krb5_crypto crypto,
11357 + krb5_keyblock *key,
11360 + gss_iov_buffer_desc *iov, int iov_count);
11363 +gssEapDecrypt(krb5_context context, int dce_style, size_t ec,
11365 +#ifdef HAVE_HEIMDAL_VERSION
11366 + krb5_crypto crypto,
11368 + krb5_keyblock *key,
11371 + gss_iov_buffer_desc *iov, int iov_count);
11374 +gssEapMapCryptoFlag(OM_uint32 type);
11377 +gssEapLocateIov(gss_iov_buffer_desc *iov,
11382 +gssEapIovMessageLength(gss_iov_buffer_desc *iov,
11384 + size_t *data_length,
11385 + size_t *assoc_data_length);
11388 +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count);
11391 +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count);
11394 +gssEapAllocIov(gss_iov_buffer_t iov, size_t size);
11397 +gssEapDeriveRfc3961Key(OM_uint32 *minor,
11398 + const unsigned char *key,
11399 + size_t keyLength,
11400 + krb5_enctype enctype,
11401 + krb5_keyblock *pKey);
11405 +#ifndef KRB_MALLOC
11407 + * If your Kerberos library uses a different allocator to your
11408 + * GSS mechanism glue, then you might wish to define these in
11409 + * config.h or elsewhere. This should eventually go away when
11410 + * we no longer need to allocate memory that is freed by the
11411 + * Kerberos library.
11413 +#define KRB_CALLOC calloc
11414 +#define KRB_MALLOC malloc
11415 +#define KRB_FREE free
11416 +#define KRB_REALLOC realloc
11417 +#endif /* KRB_MALLOC */
11419 +#ifdef HAVE_HEIMDAL_VERSION
11421 +#define KRB_TIME_FOREVER ((time_t)~0L)
11423 +#define KRB_KEY_TYPE(key) ((key)->keytype)
11424 +#define KRB_KEY_DATA(key) ((key)->keyvalue.data)
11425 +#define KRB_KEY_LENGTH(key) ((key)->keyvalue.length)
11427 +#define KRB_PRINC_LENGTH(princ) ((princ)->name.name_string.len)
11428 +#define KRB_PRINC_TYPE(princ) ((princ)->name.name_type)
11429 +#define KRB_PRINC_NAME(princ) ((princ)->name.name_string.val)
11430 +#define KRB_PRINC_REALM(princ) ((princ)->realm)
11432 +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->keyblock)
11433 +#define KRB_KT_ENT_FREE(c, e) krb5_kt_free_entry((c), (e))
11435 +#define KRB_CRYPTO_CONTEXT(ctx) (krbCrypto)
11437 +#define KRB_DATA_INIT(d) krb5_data_zero((d))
11441 +#define KRB_TIME_FOREVER KRB5_INT32_MAX
11443 +#define KRB_KEY_TYPE(key) ((key)->enctype)
11444 +#define KRB_KEY_DATA(key) ((key)->contents)
11445 +#define KRB_KEY_LENGTH(key) ((key)->length)
11447 +#define KRB_PRINC_LENGTH(princ) (krb5_princ_size(NULL, (princ)))
11448 +#define KRB_PRINC_TYPE(princ) (krb5_princ_type(NULL, (princ)))
11449 +#define KRB_PRINC_NAME(princ) (krb5_princ_name(NULL, (princ)))
11450 +#define KRB_PRINC_REALM(princ) (krb5_princ_realm(NULL, (princ)))
11452 +#define KRB_KT_ENT_KEYBLOCK(e) (&(e)->key)
11453 +#define KRB_KT_ENT_FREE(c, e) krb5_free_keytab_entry_contents((c), (e))
11455 +#define KRB_CRYPTO_CONTEXT(ctx) (&(ctx)->rfc3961Key)
11457 +#define KRB_DATA_INIT(d) do { \
11458 + (d)->magic = KV5M_DATA; \
11459 + (d)->length = 0; \
11460 + (d)->data = NULL; \
11463 +#endif /* HAVE_HEIMDAL_VERSION */
11465 +#define KRB_KEY_INIT(key) do { \
11466 + KRB_KEY_TYPE(key) = ENCTYPE_NULL; \
11467 + KRB_KEY_DATA(key) = NULL; \
11468 + KRB_KEY_LENGTH(key) = 0; \
11471 +#define GSSEAP_KRB_INIT(ctx) do { \
11472 + OM_uint32 tmpMajor; \
11474 + tmpMajor = gssEapKerberosInit(minor, ctx); \
11475 + if (GSS_ERROR(tmpMajor)) { \
11476 + return tmpMajor; \
11481 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context);
11484 +rfc3961ChecksumTypeForKey(OM_uint32 *minor,
11485 + krb5_keyblock *key,
11486 + krb5_cksumtype *cksumtype);
11489 +krbCryptoLength(krb5_context krbContext,
11490 +#ifdef HAVE_HEIMDAL_VERSION
11491 + krb5_crypto krbCrypto,
11493 + krb5_keyblock *key,
11499 +krbPaddingLength(krb5_context krbContext,
11500 +#ifdef HAVE_HEIMDAL_VERSION
11501 + krb5_crypto krbCrypto,
11503 + krb5_keyblock *key,
11505 + size_t dataLength,
11506 + size_t *padLength);
11509 +krbBlockSize(krb5_context krbContext,
11510 +#ifdef HAVE_HEIMDAL_VERSION
11511 + krb5_crypto krbCrypto,
11513 + krb5_keyblock *key,
11515 + size_t *blockSize);
11518 +krbEnctypeToString(krb5_context krbContext,
11519 + krb5_enctype enctype,
11520 + const char *prefix,
11521 + gss_buffer_t string);
11524 +krbMakeAuthDataKdcIssued(krb5_context context,
11525 + const krb5_keyblock *key,
11526 + krb5_const_principal issuer,
11527 +#ifdef HAVE_HEIMDAL_VERSION
11528 + const AuthorizationData *authdata,
11529 + AuthorizationData *adKdcIssued
11531 + krb5_authdata *const *authdata,
11532 + krb5_authdata ***adKdcIssued
11537 +krbMakeCred(krb5_context context,
11538 + krb5_auth_context authcontext,
11539 + krb5_creds *creds,
11540 + krb5_data *data);
11542 +/* util_lucid.c */
11544 +gssEapExportLucidSecContext(OM_uint32 *minor,
11545 + gss_ctx_id_t ctx,
11546 + const gss_OID desiredObject,
11547 + gss_buffer_set_t *data_set);
11550 +extern gss_OID GSS_EAP_MECHANISM;
11552 +#define OID_FLAG_NULL_VALID 0x00000001
11553 +#define OID_FLAG_FAMILY_MECH_VALID 0x00000002
11554 +#define OID_FLAG_MAP_NULL_TO_DEFAULT_MECH 0x00000004
11555 +#define OID_FLAG_MAP_FAMILY_MECH_TO_NULL 0x00000008
11558 +gssEapCanonicalizeOid(OM_uint32 *minor,
11559 + const gss_OID oid,
11564 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid);
11567 +gssEapDefaultMech(OM_uint32 *minor,
11571 +gssEapIndicateMechs(OM_uint32 *minor,
11572 + gss_OID_set *mechs);
11575 +gssEapEnctypeToOid(OM_uint32 *minor,
11576 + krb5_enctype enctype,
11580 +gssEapOidToEnctype(OM_uint32 *minor,
11581 + const gss_OID oid,
11582 + krb5_enctype *enctype);
11585 +gssEapIsMechanismOid(const gss_OID oid);
11588 +gssEapIsConcreteMechanismOid(const gss_OID oid);
11591 +gssEapValidateMechs(OM_uint32 *minor,
11592 + const gss_OID_set mechs);
11595 +gssEapOidToSaslName(const gss_OID oid);
11598 +gssEapSaslNameToOid(const gss_buffer_t name);
11600 +/* util_moonshot.c */
11602 +libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
11603 + const gss_cred_id_t cred,
11604 + gss_name_t *pName);
11607 +libMoonshotResolveInitiatorCred(OM_uint32 *minor,
11608 + gss_cred_id_t cred,
11609 + const gss_name_t targetName);
11612 +#define EXPORT_NAME_FLAG_OID 0x1
11613 +#define EXPORT_NAME_FLAG_COMPOSITE 0x2
11614 +#define EXPORT_NAME_FLAG_ALLOW_COMPOSITE 0x4
11616 +OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
11617 +OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
11618 +OM_uint32 gssEapExportName(OM_uint32 *minor,
11619 + const gss_name_t name,
11620 + gss_buffer_t exportedName);
11621 +OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
11622 + const gss_name_t name,
11623 + gss_buffer_t exportedName,
11624 + OM_uint32 flags);
11625 +OM_uint32 gssEapImportName(OM_uint32 *minor,
11626 + const gss_buffer_t input_name_buffer,
11627 + const gss_OID input_name_type,
11628 + const gss_OID input_mech_type,
11629 + gss_name_t *output_name);
11630 +OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
11631 + const gss_buffer_t input_name_buffer,
11632 + gss_name_t *output_name,
11633 + OM_uint32 flags);
11635 +gssEapDuplicateName(OM_uint32 *minor,
11636 + const gss_name_t input_name,
11637 + gss_name_t *dest_name);
11640 +gssEapCanonicalizeName(OM_uint32 *minor,
11641 + const gss_name_t input_name,
11642 + const gss_OID mech_type,
11643 + gss_name_t *dest_name);
11646 +gssEapDisplayName(OM_uint32 *minor,
11648 + gss_buffer_t output_name_buffer,
11649 + gss_OID *output_name_type);
11652 +gssEapCompareName(OM_uint32 *minor,
11653 + gss_name_t name1,
11654 + gss_name_t name2,
11655 + int *name_equal);
11659 +composeOid(OM_uint32 *minor_status,
11660 + const char *prefix,
11661 + size_t prefix_len,
11663 + gss_OID_desc *oid);
11666 +decomposeOid(OM_uint32 *minor_status,
11667 + const char *prefix,
11668 + size_t prefix_len,
11669 + gss_OID_desc *oid,
11673 +duplicateOid(OM_uint32 *minor_status,
11674 + const gss_OID_desc * const oid,
11675 + gss_OID *new_oid);
11678 +duplicateOidSet(OM_uint32 *minor,
11679 + const gss_OID_set src,
11680 + gss_OID_set *dst);
11683 +oidEqual(const gss_OID_desc *o1, const gss_OID_desc *o2)
11685 + if (o1 == GSS_C_NO_OID)
11686 + return (o2 == GSS_C_NO_OID);
11687 + else if (o2 == GSS_C_NO_OID)
11688 + return (o1 == GSS_C_NO_OID);
11690 + return (o1->length == o2->length &&
11691 + memcmp(o1->elements, o2->elements, o1->length) == 0);
11694 +/* util_ordering.c */
11696 +sequenceInternalize(OM_uint32 *minor,
11698 + unsigned char **buf,
11699 + size_t *lenremain);
11702 +sequenceExternalize(OM_uint32 *minor,
11704 + unsigned char **buf,
11705 + size_t *lenremain);
11708 +sequenceSize(void *vqueue);
11711 +sequenceFree(OM_uint32 *minor, void **vqueue);
11714 +sequenceCheck(OM_uint32 *minor, void **vqueue, uint64_t seqnum);
11717 +sequenceInit(OM_uint32 *minor, void **vqueue, uint64_t seqnum,
11718 + int do_replay, int do_sequence, int wide_nums);
11721 +enum gss_eap_state {
11722 + GSSEAP_STATE_INITIAL = 0x01, /* initial state */
11723 + GSSEAP_STATE_AUTHENTICATE = 0x02, /* exchange EAP messages */
11724 + GSSEAP_STATE_INITIATOR_EXTS = 0x04, /* initiator extensions */
11725 + GSSEAP_STATE_ACCEPTOR_EXTS = 0x08, /* acceptor extensions */
11726 +#ifdef GSSEAP_ENABLE_REAUTH
11727 + GSSEAP_STATE_REAUTHENTICATE = 0x10, /* GSS reauthentication messages */
11729 + GSSEAP_STATE_ESTABLISHED = 0x20, /* context established */
11730 + GSSEAP_STATE_ALL = 0x3F
11733 +#define GSSEAP_STATE_NEXT(s) ((s) << 1)
11735 +#define GSSEAP_SM_STATE(ctx) ((ctx)->state)
11737 +#ifdef GSSEAP_DEBUG
11738 +void gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
11739 +#define GSSEAP_SM_TRANSITION(ctx, state) gssEapSmTransition((ctx), (state))
11741 +#define GSSEAP_SM_TRANSITION(ctx, newstate) do { (ctx)->state = (newstate); } while (0)
11744 +#define GSSEAP_SM_TRANSITION_NEXT(ctx) GSSEAP_SM_TRANSITION((ctx), GSSEAP_STATE_NEXT(GSSEAP_SM_STATE((ctx))))
11746 +/* state machine entry */
11747 +struct gss_eap_sm {
11748 + OM_uint32 inputTokenType;
11749 + OM_uint32 outputTokenType;
11750 + enum gss_eap_state validStates;
11751 + OM_uint32 itokFlags;
11752 + OM_uint32 (*processToken)(OM_uint32 *,
11759 + gss_channel_bindings_t,
11765 +/* state machine flags, set by handler */
11766 +#define SM_FLAG_FORCE_SEND_TOKEN 0x00000001 /* send token even if no inner tokens */
11767 +#define SM_FLAG_OUTPUT_TOKEN_CRITICAL 0x00000002 /* output token is critical */
11769 +/* state machine flags, set by state machine */
11770 +#define SM_FLAG_INPUT_TOKEN_CRITICAL 0x10000000 /* input token was critical */
11772 +#define SM_ITOK_FLAG_REQUIRED 0x00000001 /* received tokens must be present */
11775 +gssEapSmStep(OM_uint32 *minor,
11776 + gss_cred_id_t cred,
11777 + gss_ctx_id_t ctx,
11778 + gss_name_t target,
11780 + OM_uint32 reqFlags,
11781 + OM_uint32 timeReq,
11782 + gss_channel_bindings_t chanBindings,
11783 + gss_buffer_t inputToken,
11784 + gss_buffer_t outputToken,
11785 + struct gss_eap_sm *sm,
11789 +gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state);
11791 +/* util_token.c */
11792 +struct gss_eap_token_buffer_set {
11793 + gss_buffer_set_desc buffers; /* pointers only */
11794 + OM_uint32 *types;
11798 +gssEapEncodeInnerTokens(OM_uint32 *minor,
11799 + struct gss_eap_token_buffer_set *tokens,
11800 + gss_buffer_t buffer);
11802 +gssEapDecodeInnerTokens(OM_uint32 *minor,
11803 + const gss_buffer_t buffer,
11804 + struct gss_eap_token_buffer_set *tokens);
11807 +gssEapReleaseInnerTokens(OM_uint32 *minor,
11808 + struct gss_eap_token_buffer_set *tokens,
11809 + int freeBuffers);
11812 +gssEapAllocInnerTokens(OM_uint32 *minor,
11814 + struct gss_eap_token_buffer_set *tokens);
11817 +tokenSize(const gss_OID_desc *mech, size_t body_size);
11820 +makeTokenHeader(const gss_OID_desc *mech,
11821 + size_t body_size,
11822 + unsigned char **buf,
11823 + enum gss_eap_token_type tok_type);
11826 +verifyTokenHeader(OM_uint32 *minor,
11828 + size_t *body_size,
11829 + unsigned char **buf_in,
11830 + size_t toksize_in,
11831 + enum gss_eap_token_type *ret_tok_type);
11833 +/* Helper macros */
11835 +#ifndef GSSEAP_MALLOC
11836 +#define GSSEAP_CALLOC calloc
11837 +#define GSSEAP_MALLOC malloc
11838 +#define GSSEAP_FREE free
11839 +#define GSSEAP_REALLOC realloc
11842 +#ifndef GSSAPI_CALLCONV
11843 +#define GSSAPI_CALLCONV KRB5_CALLCONV
11846 +#ifndef GSSEAP_ASSERT
11847 +#include <assert.h>
11848 +#define GSSEAP_ASSERT(x) assert((x))
11849 +#endif /* !GSSEAP_ASSERT */
11852 +#define GSSEAP_CONSTRUCTOR
11853 +#define GSSEAP_DESTRUCTOR
11855 +#define GSSEAP_CONSTRUCTOR __attribute__((constructor))
11856 +#define GSSEAP_DESTRUCTOR __attribute__((destructor))
11859 +#define GSSEAP_NOT_IMPLEMENTED do { \
11860 + GSSEAP_ASSERT(0 && "not implemented"); \
11861 + *minor = ENOSYS; \
11862 + return GSS_S_FAILURE; \
11867 +#include <winbase.h>
11869 +#define GSSEAP_GET_LAST_ERROR() (GetLastError()) /* XXX FIXME */
11871 +#define GSSEAP_MUTEX CRITICAL_SECTION
11872 +#define GSSEAP_MUTEX_INIT(m) (InitializeCriticalSection((m)), 0)
11873 +#define GSSEAP_MUTEX_DESTROY(m) DeleteCriticalSection((m))
11874 +#define GSSEAP_MUTEX_LOCK(m) EnterCriticalSection((m))
11875 +#define GSSEAP_MUTEX_UNLOCK(m) LeaveCriticalSection((m))
11876 +#define GSSEAP_ONCE_LEAVE do { return TRUE; } while (0)
11878 +/* Thread-local is handled separately */
11880 +#define GSSEAP_THREAD_ONCE INIT_ONCE
11881 +#define GSSEAP_ONCE_CALLBACK(cb) BOOL CALLBACK cb(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
11882 +#define GSSEAP_ONCE(o, i) InitOnceExecuteOnce((o), (i), NULL, NULL)
11883 +#define GSSEAP_ONCE_INITIALIZER INIT_ONCE_STATIC_INIT
11887 +#include <pthread.h>
11889 +#define GSSEAP_GET_LAST_ERROR() (errno)
11891 +#define GSSEAP_MUTEX pthread_mutex_t
11892 +#define GSSEAP_MUTEX_INIT(m) pthread_mutex_init((m), NULL)
11893 +#define GSSEAP_MUTEX_DESTROY(m) pthread_mutex_destroy((m))
11894 +#define GSSEAP_MUTEX_LOCK(m) pthread_mutex_lock((m))
11895 +#define GSSEAP_MUTEX_UNLOCK(m) pthread_mutex_unlock((m))
11897 +#define GSSEAP_THREAD_KEY pthread_key_t
11898 +#define GSSEAP_KEY_CREATE(k, d) pthread_key_create((k), (d))
11899 +#define GSSEAP_GETSPECIFIC(k) pthread_getspecific((k))
11900 +#define GSSEAP_SETSPECIFIC(k, d) pthread_setspecific((k), (d))
11902 +#define GSSEAP_THREAD_ONCE pthread_once_t
11903 +#define GSSEAP_ONCE_CALLBACK(cb) void cb(void)
11904 +#define GSSEAP_ONCE(o, i) pthread_once((o), (i))
11905 +#define GSSEAP_ONCE_INITIALIZER PTHREAD_ONCE_INIT
11906 +#define GSSEAP_ONCE_LEAVE do { } while (0)
11908 +#endif /* WIN32 */
11910 +/* Helper functions */
11911 +static inline void
11912 +store_uint16_be(uint16_t val, void *vp)
11914 + unsigned char *p = (unsigned char *)vp;
11916 + p[0] = (val >> 8) & 0xff;
11917 + p[1] = (val ) & 0xff;
11920 +static inline uint16_t
11921 +load_uint16_be(const void *cvp)
11923 + const unsigned char *p = (const unsigned char *)cvp;
11925 + return (p[1] | (p[0] << 8));
11928 +static inline void
11929 +store_uint32_be(uint32_t val, void *vp)
11931 + unsigned char *p = (unsigned char *)vp;
11933 + p[0] = (val >> 24) & 0xff;
11934 + p[1] = (val >> 16) & 0xff;
11935 + p[2] = (val >> 8) & 0xff;
11936 + p[3] = (val ) & 0xff;
11939 +static inline uint32_t
11940 +load_uint32_be(const void *cvp)
11942 + const unsigned char *p = (const unsigned char *)cvp;
11944 + return (p[3] | (p[2] << 8)
11945 + | ((uint32_t) p[1] << 16)
11946 + | ((uint32_t) p[0] << 24));
11949 +static inline void
11950 +store_uint64_be(uint64_t val, void *vp)
11952 + unsigned char *p = (unsigned char *)vp;
11954 + p[0] = (unsigned char)((val >> 56) & 0xff);
11955 + p[1] = (unsigned char)((val >> 48) & 0xff);
11956 + p[2] = (unsigned char)((val >> 40) & 0xff);
11957 + p[3] = (unsigned char)((val >> 32) & 0xff);
11958 + p[4] = (unsigned char)((val >> 24) & 0xff);
11959 + p[5] = (unsigned char)((val >> 16) & 0xff);
11960 + p[6] = (unsigned char)((val >> 8) & 0xff);
11961 + p[7] = (unsigned char)((val ) & 0xff);
11964 +static inline uint64_t
11965 +load_uint64_be(const void *cvp)
11967 + const unsigned char *p = (const unsigned char *)cvp;
11969 + return ((uint64_t)load_uint32_be(p) << 32) | load_uint32_be(p + 4);
11972 +static inline unsigned char *
11973 +store_buffer(gss_buffer_t buffer, void *vp, int wide_nums)
11975 + unsigned char *p = (unsigned char *)vp;
11978 + store_uint64_be(buffer->length, p);
11981 + store_uint32_be(buffer->length, p);
11985 + if (buffer->value != NULL) {
11986 + memcpy(p, buffer->value, buffer->length);
11987 + p += buffer->length;
11993 +static inline unsigned char *
11994 +load_buffer(const void *cvp, size_t length, gss_buffer_t buffer)
11996 + buffer->length = 0;
11997 + buffer->value = GSSEAP_MALLOC(length);
11998 + if (buffer->value == NULL)
12000 + buffer->length = length;
12001 + memcpy(buffer->value, cvp, length);
12002 + return (unsigned char *)cvp + length;
12005 +static inline unsigned char *
12006 +store_oid(gss_OID oid, void *vp)
12008 + gss_buffer_desc buf;
12010 + if (oid != GSS_C_NO_OID) {
12011 + buf.length = oid->length;
12012 + buf.value = oid->elements;
12015 + buf.value = NULL;
12018 + return store_buffer(&buf, vp, FALSE);
12021 +static inline void
12022 +krbDataToGssBuffer(krb5_data *data, gss_buffer_t buffer)
12024 + buffer->value = (void *)data->data;
12025 + buffer->length = data->length;
12028 +static inline void
12029 +krbPrincComponentToGssBuffer(krb5_principal krbPrinc,
12030 + int index, gss_buffer_t buffer)
12032 +#ifdef HAVE_HEIMDAL_VERSION
12033 + buffer->value = (void *)KRB_PRINC_NAME(krbPrinc)[index];
12034 + buffer->length = strlen((char *)buffer->value);
12036 + buffer->value = (void *)krb5_princ_component(NULL, krbPrinc, index)->data;
12037 + buffer->length = krb5_princ_component(NULL, krbPrinc, index)->length;
12038 +#endif /* HAVE_HEIMDAL_VERSION */
12041 +static inline void
12042 +krbPrincRealmToGssBuffer(krb5_principal krbPrinc, gss_buffer_t buffer)
12044 +#ifdef HAVE_HEIMDAL_VERSION
12045 + buffer->value = (void *)KRB_PRINC_REALM(krbPrinc);
12046 + buffer->length = strlen((char *)buffer->value);
12048 + krbDataToGssBuffer(KRB_PRINC_REALM(krbPrinc), buffer);
12052 +static inline void
12053 +gssBufferToKrbData(gss_buffer_t buffer, krb5_data *data)
12055 + data->data = (char *)buffer->value;
12056 + data->length = buffer->length;
12060 +struct gss_eap_status_info;
12062 +struct gss_eap_thread_local_data {
12063 + krb5_context krbContext;
12064 + struct gss_eap_status_info *statusInfo;
12067 +struct gss_eap_thread_local_data *
12068 +gssEapGetThreadLocalData(void);
12071 +gssEapDestroyStatusInfo(struct gss_eap_status_info *status);
12074 +gssEapDestroyKrbContext(krb5_context context);
12076 +#ifdef __cplusplus
12080 +#ifdef GSSEAP_ENABLE_ACCEPTOR
12081 +#include "util_json.h"
12082 +#include "util_attr.h"
12083 +#include "util_base64.h"
12084 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
12085 +#ifdef GSSEAP_ENABLE_REAUTH
12086 +#include "util_reauth.h"
12089 +#endif /* _UTIL_H_ */
12090 diff --git a/mech_eap/util_adshim.c b/mech_eap/util_adshim.c
12091 new file mode 100644
12092 index 0000000..513a1a8
12094 +++ b/mech_eap/util_adshim.c
12097 + * Copyright (c) 2011, JANET(UK)
12098 + * All rights reserved.
12100 + * Redistribution and use in source and binary forms, with or without
12101 + * modification, are permitted provided that the following conditions
12104 + * 1. Redistributions of source code must retain the above copyright
12105 + * notice, this list of conditions and the following disclaimer.
12107 + * 2. Redistributions in binary form must reproduce the above copyright
12108 + * notice, this list of conditions and the following disclaimer in the
12109 + * documentation and/or other materials provided with the distribution.
12111 + * 3. Neither the name of JANET(UK) nor the names of its contributors
12112 + * may be used to endorse or promote products derived from this software
12113 + * without specific prior written permission.
12115 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12116 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12117 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12118 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
12119 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12120 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12121 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12122 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12123 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12124 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12128 +#include "gssapiP_eap.h"
12129 +#include "authdata_plugin.h"
12132 + * This rubbish is necessary because MIT doesn't provide another way
12133 + * to access verified AD-KDCIssued elements. We can't verify them
12134 + * ourselves because they're signed in the ticket session key, which
12135 + * is destroyed immediately after the AP-REQ is processed.
12138 +struct radius_ad_context {
12139 + krb5_data avpdata;
12140 + krb5_boolean verified;
12143 +static krb5_data radius_ad_attr = {
12144 + KV5M_DATA, sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp" };
12146 +static krb5_error_code
12147 +radius_ad_init(krb5_context kcontext GSSEAP_UNUSED,
12148 + void **plugin_context)
12150 + *plugin_context = 0;
12155 +radius_ad_flags(krb5_context kcontext GSSEAP_UNUSED,
12156 + void *plugin_context GSSEAP_UNUSED,
12157 + krb5_authdatatype ad_type GSSEAP_UNUSED,
12158 + krb5_flags *flags)
12160 + *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL;
12164 +radius_ad_fini(krb5_context kcontext GSSEAP_UNUSED,
12165 + void *plugin_context GSSEAP_UNUSED)
12170 +static krb5_error_code
12171 +radius_ad_request_init(krb5_context kcontext GSSEAP_UNUSED,
12172 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12173 + void *plugin_context GSSEAP_UNUSED,
12174 + void **request_context)
12176 + struct radius_ad_context *ctx;
12178 + ctx = GSSEAP_CALLOC(1, sizeof(*ctx));
12182 + *request_context = ctx;
12187 +static krb5_error_code
12188 +radius_ad_export_authdata(krb5_context kcontext,
12189 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12190 + void *plugin_context GSSEAP_UNUSED,
12191 + void *request_context,
12192 + krb5_flags usage GSSEAP_UNUSED,
12193 + krb5_authdata ***out_authdata)
12195 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12196 + krb5_authdata *data[2];
12197 + krb5_authdata datum;
12199 + datum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
12200 + datum.length = radius_ad->avpdata.length;
12201 + datum.contents = (krb5_octet *)radius_ad->avpdata.data;
12203 + data[0] = &datum;
12206 + return krb5_copy_authdata(kcontext, data, out_authdata);
12209 +static krb5_error_code
12210 +radius_ad_import_authdata(krb5_context kcontext,
12211 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12212 + void *plugin_context GSSEAP_UNUSED,
12213 + void *request_context,
12214 + krb5_authdata **authdata,
12215 + krb5_boolean kdc_issued_flag,
12216 + krb5_const_principal issuer GSSEAP_UNUSED)
12218 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12220 + krb5_free_data_contents(kcontext, &radius_ad->avpdata);
12221 + radius_ad->verified = FALSE;
12223 + GSSEAP_ASSERT(authdata[0] != NULL);
12225 + radius_ad->avpdata.data = GSSEAP_MALLOC(authdata[0]->length);
12226 + if (radius_ad->avpdata.data == NULL)
12229 + memcpy(radius_ad->avpdata.data, authdata[0]->contents,
12230 + authdata[0]->length);
12231 + radius_ad->avpdata.length = authdata[0]->length;
12233 + radius_ad->verified = kdc_issued_flag;
12239 +radius_ad_request_fini(krb5_context kcontext,
12240 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12241 + void *plugin_context GSSEAP_UNUSED,
12242 + void *request_context)
12244 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12246 + if (radius_ad != NULL) {
12247 + krb5_free_data_contents(kcontext, &radius_ad->avpdata);
12248 + GSSEAP_FREE(radius_ad);
12252 +static krb5_error_code
12253 +radius_ad_get_attribute(krb5_context kcontext GSSEAP_UNUSED,
12254 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12255 + void *plugin_context GSSEAP_UNUSED,
12256 + void *request_context,
12257 + const krb5_data *attribute,
12258 + krb5_boolean *authenticated,
12259 + krb5_boolean *complete,
12260 + krb5_data *value,
12261 + krb5_data *display_value GSSEAP_UNUSED,
12264 + struct radius_ad_context *radius_ad = (struct radius_ad_context *)request_context;
12266 + if (attribute->length != radius_ad_attr.length ||
12267 + memcmp(attribute->data, radius_ad_attr.data,
12268 + radius_ad_attr.length) != 0)
12271 + if (radius_ad->avpdata.length == 0)
12274 + *authenticated = radius_ad->verified;
12275 + *complete = TRUE;
12278 + value->data = GSSEAP_MALLOC(radius_ad->avpdata.length);
12279 + if (value->data == NULL)
12282 + memcpy(value->data, radius_ad->avpdata.data, radius_ad->avpdata.length);
12283 + value->length = radius_ad->avpdata.length;
12288 +static krb5_error_code
12289 +radius_ad_copy(krb5_context kcontext GSSEAP_UNUSED,
12290 + struct _krb5_authdata_context *context GSSEAP_UNUSED,
12291 + void *plugin_context GSSEAP_UNUSED,
12292 + void *request_context,
12293 + void *dst_plugin_context GSSEAP_UNUSED,
12294 + void *dst_request_context)
12296 + struct radius_ad_context *radius_ad_src =
12297 + (struct radius_ad_context *)request_context;
12298 + struct radius_ad_context *radius_ad_dst =
12299 + (struct radius_ad_context *)dst_request_context;
12301 + radius_ad_dst->avpdata.data = GSSEAP_MALLOC(radius_ad_src->avpdata.length);
12302 + if (radius_ad_dst->avpdata.data == NULL)
12305 + memcpy(radius_ad_dst->avpdata.data, radius_ad_src->avpdata.data,
12306 + radius_ad_src->avpdata.length);
12307 + radius_ad_dst->avpdata.length = radius_ad_src->avpdata.length;
12308 + radius_ad_dst->verified = radius_ad_src->verified;
12313 +static krb5_authdatatype radius_ad_ad_types[] =
12314 + { KRB5_AUTHDATA_RADIUS_AVP, 0 };
12316 +krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
12318 + radius_ad_ad_types,
12322 + radius_ad_request_init,
12323 + radius_ad_request_fini,
12325 + radius_ad_get_attribute,
12328 + radius_ad_export_authdata,
12329 + radius_ad_import_authdata,
12338 diff --git a/mech_eap/util_attr.cpp b/mech_eap/util_attr.cpp
12339 new file mode 100644
12340 index 0000000..3bfe785
12342 +++ b/mech_eap/util_attr.cpp
12345 + * Copyright (c) 2011, JANET(UK)
12346 + * All rights reserved.
12348 + * Redistribution and use in source and binary forms, with or without
12349 + * modification, are permitted provided that the following conditions
12352 + * 1. Redistributions of source code must retain the above copyright
12353 + * notice, this list of conditions and the following disclaimer.
12355 + * 2. Redistributions in binary form must reproduce the above copyright
12356 + * notice, this list of conditions and the following disclaimer in the
12357 + * documentation and/or other materials provided with the distribution.
12359 + * 3. Neither the name of JANET(UK) nor the names of its contributors
12360 + * may be used to endorse or promote products derived from this software
12361 + * without specific prior written permission.
12363 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12364 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12365 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12366 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
12367 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12368 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12369 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12370 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12371 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12372 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12377 + * Attribute provider mechanism.
12380 +#include "gssapiP_eap.h"
12382 +#include <typeinfo>
12384 +#include <sstream>
12385 +#include <exception>
12388 +/* lazy initialisation */
12389 +static GSSEAP_THREAD_ONCE gssEapAttrProvidersInitOnce = GSSEAP_ONCE_INITIALIZER;
12390 +static OM_uint32 gssEapAttrProvidersInitStatus = GSS_S_UNAVAILABLE;
12392 +GSSEAP_ONCE_CALLBACK(gssEapAttrProvidersInitInternal)
12394 + OM_uint32 major, minor;
12396 + GSSEAP_ASSERT(gssEapAttrProvidersInitStatus == GSS_S_UNAVAILABLE);
12398 + json_set_alloc_funcs(GSSEAP_MALLOC, GSSEAP_FREE);
12400 + major = gssEapRadiusAttrProviderInit(&minor);
12401 + if (GSS_ERROR(major))
12404 +#ifdef HAVE_OPENSAML
12405 + major = gssEapSamlAttrProvidersInit(&minor);
12406 + if (GSS_ERROR(major))
12410 +#ifdef HAVE_SHIBRESOLVER
12411 + /* Allow Shibboleth initialization failure to be non-fatal */
12412 + gssEapLocalAttrProviderInit(&minor);
12416 +#ifdef GSSEAP_DEBUG
12417 + GSSEAP_ASSERT(major == GSS_S_COMPLETE);
12420 + gssEapAttrProvidersInitStatus = major;
12422 + GSSEAP_ONCE_LEAVE;
12426 +gssEapAttrProvidersInit(OM_uint32 *minor)
12428 + GSSEAP_ONCE(&gssEapAttrProvidersInitOnce, gssEapAttrProvidersInitInternal);
12430 + if (GSS_ERROR(gssEapAttrProvidersInitStatus))
12431 + *minor = GSSEAP_NO_ATTR_PROVIDERS;
12433 + return gssEapAttrProvidersInitStatus;
12437 +gssEapAttrProvidersFinalize(OM_uint32 *minor)
12439 + if (gssEapAttrProvidersInitStatus == GSS_S_COMPLETE) {
12440 +#ifdef HAVE_SHIBRESOLVER
12441 + gssEapLocalAttrProviderFinalize(minor);
12443 +#ifdef HAVE_OPENSAML
12444 + gssEapSamlAttrProvidersFinalize(minor);
12446 + gssEapRadiusAttrProviderFinalize(minor);
12448 + gssEapAttrProvidersInitStatus = GSS_S_UNAVAILABLE;
12451 + return GSS_S_COMPLETE;
12454 +static gss_eap_attr_create_provider gssEapAttrFactories[ATTR_TYPE_MAX + 1];
12457 + * Register a provider for a particular type and prefix
12460 +gss_eap_attr_ctx::registerProvider(unsigned int type,
12461 + gss_eap_attr_create_provider factory)
12463 + GSSEAP_ASSERT(type <= ATTR_TYPE_MAX);
12465 + GSSEAP_ASSERT(gssEapAttrFactories[type] == NULL);
12467 + gssEapAttrFactories[type] = factory;
12471 + * Unregister a provider
12474 +gss_eap_attr_ctx::unregisterProvider(unsigned int type)
12476 + GSSEAP_ASSERT(type <= ATTR_TYPE_MAX);
12478 + gssEapAttrFactories[type] = NULL;
12482 + * Create an attribute context, that manages instances of providers
12484 +gss_eap_attr_ctx::gss_eap_attr_ctx(void)
12488 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12489 + gss_eap_attr_provider *provider;
12491 + if (gssEapAttrFactories[i] != NULL) {
12492 + provider = (gssEapAttrFactories[i])();
12497 + m_providers[i] = provider;
12502 + * Convert an attribute prefix to a type
12505 +gss_eap_attr_ctx::attributePrefixToType(const gss_buffer_t prefix) const
12509 + for (i = ATTR_TYPE_MIN; i < ATTR_TYPE_MAX; i++) {
12510 + const char *pprefix;
12512 + if (!providerEnabled(i))
12515 + pprefix = m_providers[i]->prefix();
12516 + if (pprefix == NULL)
12519 + if (strlen(pprefix) == prefix->length &&
12520 + memcmp(pprefix, prefix->value, prefix->length) == 0)
12524 + return ATTR_TYPE_LOCAL;
12528 + * Convert a type to an attribute prefix
12531 +gss_eap_attr_ctx::attributeTypeToPrefix(unsigned int type) const
12533 + gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
12535 + if (type < ATTR_TYPE_MIN || type >= ATTR_TYPE_MAX)
12538 + if (!providerEnabled(type))
12541 + prefix.value = (void *)m_providers[type]->prefix();
12542 + if (prefix.value != NULL)
12543 + prefix.length = strlen((char *)prefix.value);
12549 +gss_eap_attr_ctx::providerEnabled(unsigned int type) const
12551 + if (type == ATTR_TYPE_LOCAL &&
12552 + (m_flags & ATTR_FLAG_DISABLE_LOCAL))
12555 + if (m_providers[type] == NULL)
12562 +gss_eap_attr_ctx::releaseProvider(unsigned int type)
12564 + delete m_providers[type];
12565 + m_providers[type] = NULL;
12569 + * Initialize a context from an existing context.
12572 +gss_eap_attr_ctx::initWithExistingContext(const gss_eap_attr_ctx *manager)
12576 + m_flags = manager->m_flags;
12578 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12579 + gss_eap_attr_provider *provider;
12581 + if (!providerEnabled(i)) {
12582 + releaseProvider(i);
12586 + provider = m_providers[i];
12588 + ret = provider->initWithExistingContext(this,
12589 + manager->m_providers[i]);
12590 + if (ret == false) {
12591 + releaseProvider(i);
12600 + * Initialize a context from a GSS credential and context.
12603 +gss_eap_attr_ctx::initWithGssContext(const gss_cred_id_t cred,
12604 + const gss_ctx_id_t ctx)
12608 + if (cred != GSS_C_NO_CREDENTIAL &&
12609 + (cred->flags & GSS_EAP_DISABLE_LOCAL_ATTRS_FLAG)) {
12610 + m_flags |= ATTR_FLAG_DISABLE_LOCAL;
12613 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12614 + gss_eap_attr_provider *provider;
12616 + if (!providerEnabled(i)) {
12617 + releaseProvider(i);
12621 + provider = m_providers[i];
12623 + ret = provider->initWithGssContext(this, cred, ctx);
12624 + if (ret == false) {
12625 + releaseProvider(i);
12634 +gss_eap_attr_ctx::initWithJsonObject(JSONObject &obj)
12636 + bool ret = false;
12637 + bool foundSource[ATTR_TYPE_MAX + 1];
12638 + unsigned int type;
12640 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++)
12641 + foundSource[type] = false;
12643 + if (obj["version"].integer() != 1)
12646 + m_flags = obj["flags"].integer();
12648 + JSONObject sources = obj["sources"];
12650 + /* Initialize providers from serialized state */
12651 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
12652 + gss_eap_attr_provider *provider;
12655 + if (!providerEnabled(type)) {
12656 + releaseProvider(type);
12660 + provider = m_providers[type];
12661 + key = provider->name();
12665 + JSONObject source = sources.get(key);
12666 + if (!source.isNull() &&
12667 + !provider->initWithJsonObject(this, source)) {
12668 + releaseProvider(type);
12672 + foundSource[type] = true;
12675 + /* Initialize remaining providers from initialized providers */
12676 + for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
12677 + gss_eap_attr_provider *provider;
12679 + if (foundSource[type] || !providerEnabled(type))
12682 + provider = m_providers[type];
12684 + ret = provider->initWithGssContext(this,
12685 + GSS_C_NO_CREDENTIAL,
12686 + GSS_C_NO_CONTEXT);
12687 + if (ret == false) {
12688 + releaseProvider(type);
12697 +gss_eap_attr_ctx::jsonRepresentation(void) const
12699 + JSONObject obj, sources;
12702 + obj.set("version", 1);
12703 + obj.set("flags", m_flags);
12705 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12706 + gss_eap_attr_provider *provider;
12709 + provider = m_providers[i];
12710 + if (provider == NULL)
12711 + continue; /* provider not initialised */
12713 + key = provider->name();
12715 + continue; /* provider does not have state */
12717 + JSONObject source = provider->jsonRepresentation();
12718 + sources.set(key, source);
12721 + obj.set("sources", sources);
12727 + * Initialize a context from an exported context or name token
12730 +gss_eap_attr_ctx::initWithBuffer(const gss_buffer_t buffer)
12732 + OM_uint32 major, minor;
12735 + json_error_t error;
12737 + major = bufferToString(&minor, buffer, &s);
12738 + if (GSS_ERROR(major))
12741 + JSONObject obj = JSONObject::load(s, 0, &error);
12742 + if (!obj.isNull()) {
12743 + ret = initWithJsonObject(obj);
12752 +gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
12754 + for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++)
12755 + delete m_providers[i];
12759 + * Locate provider for a given type
12761 +gss_eap_attr_provider *
12762 +gss_eap_attr_ctx::getProvider(unsigned int type) const
12764 + GSSEAP_ASSERT(type >= ATTR_TYPE_MIN && type <= ATTR_TYPE_MAX);
12765 + return m_providers[type];
12769 + * Get primary provider. Only the primary provider is serialised when
12770 + * gss_export_sec_context() or gss_export_name_composite() is called.
12772 +gss_eap_attr_provider *
12773 +gss_eap_attr_ctx::getPrimaryProvider(void) const
12775 + return m_providers[ATTR_TYPE_MIN];
12779 + * Set an attribute
12782 +gss_eap_attr_ctx::setAttribute(int complete,
12783 + const gss_buffer_t attr,
12784 + const gss_buffer_t value)
12786 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12787 + unsigned int type;
12788 + gss_eap_attr_provider *provider;
12789 + bool ret = false;
12791 + decomposeAttributeName(attr, &type, &suffix);
12793 + provider = m_providers[type];
12794 + if (provider != NULL) {
12795 + ret = provider->setAttribute(complete,
12796 + (type == ATTR_TYPE_LOCAL) ? attr : &suffix,
12804 + * Delete an attrbiute
12807 +gss_eap_attr_ctx::deleteAttribute(const gss_buffer_t attr)
12809 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12810 + unsigned int type;
12811 + gss_eap_attr_provider *provider;
12812 + bool ret = false;
12814 + decomposeAttributeName(attr, &type, &suffix);
12816 + provider = m_providers[type];
12817 + if (provider != NULL) {
12818 + ret = provider->deleteAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix);
12825 + * Enumerate attribute types with callback
12828 +gss_eap_attr_ctx::getAttributeTypes(gss_eap_attr_enumeration_cb cb, void *data) const
12830 + bool ret = false;
12833 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12834 + gss_eap_attr_provider *provider = m_providers[i];
12836 + if (provider == NULL)
12839 + ret = provider->getAttributeTypes(cb, data);
12840 + if (ret == false)
12847 +struct eap_gss_get_attr_types_args {
12848 + unsigned int type;
12849 + gss_buffer_set_t attrs;
12853 +addAttribute(const gss_eap_attr_ctx *manager,
12854 + const gss_eap_attr_provider *provider GSSEAP_UNUSED,
12855 + const gss_buffer_t attribute,
12858 + eap_gss_get_attr_types_args *args = (eap_gss_get_attr_types_args *)data;
12859 + gss_buffer_desc qualified;
12860 + OM_uint32 major, minor;
12862 + if (args->type != ATTR_TYPE_LOCAL) {
12863 + manager->composeAttributeName(args->type, attribute, &qualified);
12864 + major = gss_add_buffer_set_member(&minor, &qualified, &args->attrs);
12865 + gss_release_buffer(&minor, &qualified);
12867 + major = gss_add_buffer_set_member(&minor, attribute, &args->attrs);
12870 + return GSS_ERROR(major) == false;
12874 + * Enumerate attribute types, output is buffer set
12877 +gss_eap_attr_ctx::getAttributeTypes(gss_buffer_set_t *attrs)
12879 + eap_gss_get_attr_types_args args;
12880 + OM_uint32 major, minor;
12881 + bool ret = false;
12884 + major = gss_create_empty_buffer_set(&minor, attrs);
12885 + if (GSS_ERROR(major))
12886 + throw std::bad_alloc();
12888 + args.attrs = *attrs;
12890 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
12891 + gss_eap_attr_provider *provider = m_providers[i];
12895 + if (provider == NULL)
12898 + ret = provider->getAttributeTypes(addAttribute, (void *)&args);
12899 + if (ret == false)
12903 + if (ret == false)
12904 + gss_release_buffer_set(&minor, attrs);
12910 + * Get attribute with given name
12913 +gss_eap_attr_ctx::getAttribute(const gss_buffer_t attr,
12914 + int *authenticated,
12916 + gss_buffer_t value,
12917 + gss_buffer_t display_value,
12920 + gss_buffer_desc suffix = GSS_C_EMPTY_BUFFER;
12921 + unsigned int type;
12922 + gss_eap_attr_provider *provider;
12925 + decomposeAttributeName(attr, &type, &suffix);
12927 + provider = m_providers[type];
12928 + if (provider == NULL)
12931 + ret = provider->getAttribute(type == ATTR_TYPE_LOCAL ? attr : &suffix,
12932 + authenticated, complete,
12933 + value, display_value, more);
12939 + * Map attribute context to C++ object
12942 +gss_eap_attr_ctx::mapToAny(int authenticated,
12943 + gss_buffer_t type_id) const
12945 + unsigned int type;
12946 + gss_eap_attr_provider *provider;
12947 + gss_buffer_desc suffix;
12949 + decomposeAttributeName(type_id, &type, &suffix);
12951 + provider = m_providers[type];
12952 + if (provider == NULL)
12953 + return (gss_any_t)NULL;
12955 + return provider->mapToAny(authenticated, &suffix);
12959 + * Release mapped context
12962 +gss_eap_attr_ctx::releaseAnyNameMapping(gss_buffer_t type_id,
12963 + gss_any_t input) const
12965 + unsigned int type;
12966 + gss_eap_attr_provider *provider;
12967 + gss_buffer_desc suffix;
12969 + decomposeAttributeName(type_id, &type, &suffix);
12971 + provider = m_providers[type];
12972 + if (provider != NULL)
12973 + provider->releaseAnyNameMapping(&suffix, input);
12977 + * Export attribute context to buffer
12980 +gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
12985 + JSONObject obj = jsonRepresentation();
12988 + obj.dump(stdout);
12991 + s = obj.dump(JSON_COMPACT);
12993 + if (GSS_ERROR(makeStringBuffer(&minor, s, buffer)))
12994 + throw std::bad_alloc();
12998 + * Return soonest expiry time of providers
13001 +gss_eap_attr_ctx::getExpiryTime(void) const
13004 + time_t expiryTime = 0;
13006 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
13007 + gss_eap_attr_provider *provider = m_providers[i];
13008 + time_t providerExpiryTime;
13010 + if (provider == NULL)
13013 + providerExpiryTime = provider->getExpiryTime();
13014 + if (providerExpiryTime == 0)
13017 + if (expiryTime == 0 || providerExpiryTime < expiryTime)
13018 + expiryTime = providerExpiryTime;
13021 + return expiryTime;
13025 +gss_eap_attr_ctx::mapException(OM_uint32 *minor, std::exception &e) const
13030 + /* Errors we handle ourselves */
13031 + if (typeid(e) == typeid(std::bad_alloc)) {
13032 + major = GSS_S_FAILURE;
13035 + } else if (typeid(e) == typeid(JSONException)) {
13036 + major = GSS_S_BAD_NAME;
13037 + *minor = GSSEAP_BAD_ATTR_TOKEN;
13038 + gssEapSaveStatusInfo(*minor, "%s", e.what());
13042 + /* Errors we delegate to providers */
13043 + major = GSS_S_CONTINUE_NEEDED;
13045 + for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
13046 + gss_eap_attr_provider *provider = m_providers[i];
13048 + if (provider == NULL)
13051 + major = provider->mapException(minor, e);
13052 + if (major != GSS_S_CONTINUE_NEEDED)
13056 + if (major == GSS_S_CONTINUE_NEEDED) {
13057 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13058 + major = GSS_S_FAILURE;
13062 + GSSEAP_ASSERT(GSS_ERROR(major));
13068 + * Decompose attribute name into prefix and suffix
13071 +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
13072 + gss_buffer_t prefix,
13073 + gss_buffer_t suffix)
13078 + for (i = 0; i < attribute->length; i++) {
13079 + if (((char *)attribute->value)[i] == ' ') {
13080 + p = (char *)attribute->value + i + 1;
13085 + prefix->value = attribute->value;
13086 + prefix->length = i;
13088 + if (p != NULL && *p != '\0') {
13089 + suffix->length = attribute->length - 1 - prefix->length;
13090 + suffix->value = p;
13092 + suffix->length = 0;
13093 + suffix->value = NULL;
13098 + * Decompose attribute name into type and suffix
13101 +gss_eap_attr_ctx::decomposeAttributeName(const gss_buffer_t attribute,
13102 + unsigned int *type,
13103 + gss_buffer_t suffix) const
13105 + gss_buffer_desc prefix = GSS_C_EMPTY_BUFFER;
13107 + decomposeAttributeName(attribute, &prefix, suffix);
13108 + *type = attributePrefixToType(&prefix);
13112 + * Compose attribute name from prefix, suffix; returns C++ string
13115 +gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
13116 + const gss_buffer_t suffix)
13120 + if (prefix == GSS_C_NO_BUFFER || prefix->length == 0)
13123 + str.append((const char *)prefix->value, prefix->length);
13125 + if (suffix != GSS_C_NO_BUFFER) {
13127 + str.append((const char *)suffix->value, suffix->length);
13134 + * Compose attribute name from type, suffix; returns C++ string
13137 +gss_eap_attr_ctx::composeAttributeName(unsigned int type,
13138 + const gss_buffer_t suffix)
13140 + gss_buffer_desc prefix = attributeTypeToPrefix(type);
13142 + return composeAttributeName(&prefix, suffix);
13146 + * Compose attribute name from prefix, suffix; returns GSS buffer
13149 +gss_eap_attr_ctx::composeAttributeName(const gss_buffer_t prefix,
13150 + const gss_buffer_t suffix,
13151 + gss_buffer_t attribute)
13153 + std::string str = composeAttributeName(prefix, suffix);
13155 + if (str.length() != 0) {
13156 + return duplicateBuffer(str, attribute);
13158 + attribute->length = 0;
13159 + attribute->value = NULL;
13164 + * Compose attribute name from type, suffix; returns GSS buffer
13167 +gss_eap_attr_ctx::composeAttributeName(unsigned int type,
13168 + const gss_buffer_t suffix,
13169 + gss_buffer_t attribute) const
13171 + gss_buffer_desc prefix = attributeTypeToPrefix(type);
13173 + return composeAttributeName(&prefix, suffix, attribute);
13180 +gssEapInquireName(OM_uint32 *minor,
13183 + gss_OID *MN_mech,
13184 + gss_buffer_set_t *attrs)
13188 + if (name_is_MN != NULL)
13189 + *name_is_MN = (name->mechanismUsed != GSS_C_NULL_OID);
13191 + if (MN_mech != NULL) {
13192 + major = gssEapCanonicalizeOid(minor, name->mechanismUsed,
13193 + OID_FLAG_NULL_VALID, MN_mech);
13194 + if (GSS_ERROR(major))
13198 + if (name->attrCtx == NULL) {
13199 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13200 + return GSS_S_UNAVAILABLE;
13203 + if (GSS_ERROR(gssEapAttrProvidersInit(minor))) {
13204 + return GSS_S_UNAVAILABLE;
13208 + if (!name->attrCtx->getAttributeTypes(attrs)) {
13209 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13210 + return GSS_S_UNAVAILABLE;
13212 + } catch (std::exception &e) {
13213 + return name->attrCtx->mapException(minor, e);
13216 + return GSS_S_COMPLETE;
13220 +gssEapGetNameAttribute(OM_uint32 *minor,
13222 + gss_buffer_t attr,
13223 + int *authenticated,
13225 + gss_buffer_t value,
13226 + gss_buffer_t display_value,
13229 + if (authenticated != NULL)
13230 + *authenticated = 0;
13231 + if (complete != NULL)
13234 + if (value != NULL) {
13235 + value->length = 0;
13236 + value->value = NULL;
13239 + if (display_value != NULL) {
13240 + display_value->length = 0;
13241 + display_value->value = NULL;
13244 + if (name->attrCtx == NULL) {
13245 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13246 + return GSS_S_UNAVAILABLE;
13249 + if (GSS_ERROR(gssEapAttrProvidersInit(minor))) {
13250 + return GSS_S_UNAVAILABLE;
13254 + if (!name->attrCtx->getAttribute(attr, authenticated, complete,
13255 + value, display_value, more)) {
13256 + *minor = GSSEAP_NO_SUCH_ATTR;
13257 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13258 + (int)attr->length, (char *)attr->value);
13259 + return GSS_S_UNAVAILABLE;
13261 + } catch (std::exception &e) {
13262 + return name->attrCtx->mapException(minor, e);
13265 + return GSS_S_COMPLETE;
13269 +gssEapDeleteNameAttribute(OM_uint32 *minor,
13271 + gss_buffer_t attr)
13273 + if (name->attrCtx == NULL) {
13274 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13275 + return GSS_S_UNAVAILABLE;
13278 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13279 + return GSS_S_UNAVAILABLE;
13282 + if (!name->attrCtx->deleteAttribute(attr)) {
13283 + *minor = GSSEAP_NO_SUCH_ATTR;
13284 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13285 + (int)attr->length, (char *)attr->value);
13286 + return GSS_S_UNAVAILABLE;
13288 + } catch (std::exception &e) {
13289 + return name->attrCtx->mapException(minor, e);
13292 + return GSS_S_COMPLETE;
13296 +gssEapSetNameAttribute(OM_uint32 *minor,
13299 + gss_buffer_t attr,
13300 + gss_buffer_t value)
13302 + if (name->attrCtx == NULL) {
13303 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13304 + return GSS_S_UNAVAILABLE;
13307 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13308 + return GSS_S_UNAVAILABLE;
13311 + if (!name->attrCtx->setAttribute(complete, attr, value)) {
13312 + *minor = GSSEAP_NO_SUCH_ATTR;
13313 + gssEapSaveStatusInfo(*minor, "Unknown naming attribute %.*s",
13314 + (int)attr->length, (char *)attr->value);
13315 + return GSS_S_UNAVAILABLE;
13317 + } catch (std::exception &e) {
13318 + return name->attrCtx->mapException(minor, e);
13321 + return GSS_S_COMPLETE;
13325 +gssEapExportAttrContext(OM_uint32 *minor,
13327 + gss_buffer_t buffer)
13329 + if (name->attrCtx == NULL) {
13330 + buffer->length = 0;
13331 + buffer->value = NULL;
13333 + return GSS_S_COMPLETE;
13336 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13337 + return GSS_S_UNAVAILABLE;
13340 + name->attrCtx->exportToBuffer(buffer);
13341 + } catch (std::exception &e) {
13342 + return name->attrCtx->mapException(minor, e);
13345 + return GSS_S_COMPLETE;
13349 +gssEapImportAttrContext(OM_uint32 *minor,
13350 + gss_buffer_t buffer,
13353 + gss_eap_attr_ctx *ctx = NULL;
13354 + OM_uint32 major = GSS_S_FAILURE;
13356 + GSSEAP_ASSERT(name->attrCtx == NULL);
13358 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13359 + return GSS_S_UNAVAILABLE;
13361 + if (buffer->length == 0)
13362 + return GSS_S_COMPLETE;
13365 + ctx = new gss_eap_attr_ctx();
13367 + if (ctx->initWithBuffer(buffer)) {
13368 + name->attrCtx = ctx;
13369 + major = GSS_S_COMPLETE;
13372 + major = GSS_S_BAD_NAME;
13373 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13375 + } catch (std::exception &e) {
13377 + major = ctx->mapException(minor, e);
13380 + GSSEAP_ASSERT(major == GSS_S_COMPLETE || name->attrCtx == NULL);
13382 + if (GSS_ERROR(major))
13389 +gssEapDuplicateAttrContext(OM_uint32 *minor,
13393 + gss_eap_attr_ctx *ctx = NULL;
13394 + OM_uint32 major = GSS_S_FAILURE;
13396 + GSSEAP_ASSERT(out->attrCtx == NULL);
13398 + if (in->attrCtx == NULL) {
13400 + return GSS_S_COMPLETE;
13403 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13404 + return GSS_S_UNAVAILABLE;
13407 + ctx = new gss_eap_attr_ctx();
13409 + if (ctx->initWithExistingContext(in->attrCtx)) {
13410 + out->attrCtx = ctx;
13411 + major = GSS_S_COMPLETE;
13414 + major = GSS_S_FAILURE;
13415 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13417 + } catch (std::exception &e) {
13418 + major = in->attrCtx->mapException(minor, e);
13421 + GSSEAP_ASSERT(major == GSS_S_COMPLETE || out->attrCtx == NULL);
13423 + if (GSS_ERROR(major))
13426 + return GSS_S_COMPLETE;
13430 +gssEapMapNameToAny(OM_uint32 *minor,
13432 + int authenticated,
13433 + gss_buffer_t type_id,
13434 + gss_any_t *output)
13436 + if (name->attrCtx == NULL) {
13437 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13438 + return GSS_S_UNAVAILABLE;
13441 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13442 + return GSS_S_UNAVAILABLE;
13445 + *output = name->attrCtx->mapToAny(authenticated, type_id);
13446 + } catch (std::exception &e) {
13447 + return name->attrCtx->mapException(minor, e);
13450 + return GSS_S_COMPLETE;
13454 +gssEapReleaseAnyNameMapping(OM_uint32 *minor,
13456 + gss_buffer_t type_id,
13457 + gss_any_t *input)
13459 + if (name->attrCtx == NULL) {
13460 + *minor = GSSEAP_NO_ATTR_CONTEXT;
13461 + return GSS_S_UNAVAILABLE;
13464 + if (GSS_ERROR(gssEapAttrProvidersInit(minor)))
13465 + return GSS_S_UNAVAILABLE;
13468 + if (*input != NULL)
13469 + name->attrCtx->releaseAnyNameMapping(type_id, *input);
13471 + } catch (std::exception &e) {
13472 + return name->attrCtx->mapException(minor, e);
13475 + return GSS_S_COMPLETE;
13479 +gssEapReleaseAttrContext(OM_uint32 *minor,
13482 + if (name->attrCtx != NULL)
13483 + delete name->attrCtx;
13486 + return GSS_S_COMPLETE;
13490 + * Public accessor for initialisng a context from a GSS context. Also
13491 + * sets expiry time on GSS context as a side-effect.
13494 +gssEapCreateAttrContext(OM_uint32 *minor,
13495 + gss_cred_id_t gssCred,
13496 + gss_ctx_id_t gssCtx,
13497 + struct gss_eap_attr_ctx **pAttrContext,
13498 + time_t *pExpiryTime)
13500 + gss_eap_attr_ctx *ctx = NULL;
13503 + GSSEAP_ASSERT(gssCtx != GSS_C_NO_CONTEXT);
13505 + *pAttrContext = NULL;
13507 + major = gssEapAttrProvidersInit(minor);
13508 + if (GSS_ERROR(major))
13512 + /* Set *pAttrContext here to for reentrancy */
13513 + *pAttrContext = ctx = new gss_eap_attr_ctx();
13515 + if (ctx->initWithGssContext(gssCred, gssCtx)) {
13516 + *pExpiryTime = ctx->getExpiryTime();
13517 + major = GSS_S_COMPLETE;
13520 + major = GSS_S_FAILURE;
13521 + *minor = GSSEAP_ATTR_CONTEXT_FAILURE;
13523 + } catch (std::exception &e) {
13525 + major = ctx->mapException(minor, e);
13528 + if (GSS_ERROR(major)) {
13530 + *pAttrContext = NULL;
13535 diff --git a/mech_eap/util_attr.h b/mech_eap/util_attr.h
13536 new file mode 100644
13537 index 0000000..2af0850
13539 +++ b/mech_eap/util_attr.h
13542 + * Copyright (c) 2011, JANET(UK)
13543 + * All rights reserved.
13545 + * Redistribution and use in source and binary forms, with or without
13546 + * modification, are permitted provided that the following conditions
13549 + * 1. Redistributions of source code must retain the above copyright
13550 + * notice, this list of conditions and the following disclaimer.
13552 + * 2. Redistributions in binary form must reproduce the above copyright
13553 + * notice, this list of conditions and the following disclaimer in the
13554 + * documentation and/or other materials provided with the distribution.
13556 + * 3. Neither the name of JANET(UK) nor the names of its contributors
13557 + * may be used to endorse or promote products derived from this software
13558 + * without specific prior written permission.
13560 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13561 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13562 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13563 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
13564 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13565 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13566 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13567 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13568 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13569 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13574 + * Attribute provider interface.
13577 +#ifndef _UTIL_ATTR_H_
13578 +#define _UTIL_ATTR_H_ 1
13580 +#ifdef __cplusplus
13584 +using namespace gss_eap_util;
13586 +struct gss_eap_attr_provider;
13587 +struct gss_eap_attr_ctx;
13590 +(*gss_eap_attr_enumeration_cb)(const gss_eap_attr_ctx *ctx,
13591 + const gss_eap_attr_provider *source,
13592 + const gss_buffer_t attribute,
13595 +#define ATTR_TYPE_RADIUS 0U /* RADIUS AVPs */
13596 +#ifdef HAVE_OPENSAML
13597 +#define ATTR_TYPE_SAML_ASSERTION 1U /* SAML assertion */
13598 +#define ATTR_TYPE_SAML 2U /* SAML attributes */
13600 +#define ATTR_TYPE_LOCAL 3U /* Local attributes */
13601 +#define ATTR_TYPE_MIN ATTR_TYPE_RADIUS
13602 +#define ATTR_TYPE_MAX ATTR_TYPE_LOCAL
13604 +#define ATTR_FLAG_DISABLE_LOCAL 0x00000001
13607 + * Attribute provider: this represents a source of attributes derived
13608 + * from the security context.
13610 +struct gss_eap_attr_provider
13613 + gss_eap_attr_provider(void) {}
13614 + virtual ~gss_eap_attr_provider(void) {}
13616 + bool initWithManager(const gss_eap_attr_ctx *manager)
13618 + m_manager = manager;
13622 + virtual bool initWithExistingContext(const gss_eap_attr_ctx *manager,
13623 + const gss_eap_attr_provider *ctx GSSEAP_UNUSED)
13625 + return initWithManager(manager);
13628 + virtual bool initWithGssContext(const gss_eap_attr_ctx *manager,
13629 + const gss_cred_id_t cred GSSEAP_UNUSED,
13630 + const gss_ctx_id_t ctx GSSEAP_UNUSED)
13632 + return initWithManager(manager);
13635 + virtual bool getAttributeTypes(gss_eap_attr_enumeration_cb GSSEAP_UNUSED,
13636 + void *data GSSEAP_UNUSED) const
13641 + virtual bool setAttribute(int complete GSSEAP_UNUSED,
13642 + const gss_buffer_t attr GSSEAP_UNUSED,
13643 + const gss_buffer_t value GSSEAP_UNUSED)
13648 + virtual bool deleteAttribute(const gss_buffer_t value GSSEAP_UNUSED)
13653 + virtual bool getAttribute(const gss_buffer_t attr GSSEAP_UNUSED,
13654 + int *authenticated GSSEAP_UNUSED,
13655 + int *complete GSSEAP_UNUSED,
13656 + gss_buffer_t value GSSEAP_UNUSED,
13657 + gss_buffer_t display_value GSSEAP_UNUSED,
13658 + int *more GSSEAP_UNUSED) const
13663 + virtual gss_any_t mapToAny(int authenticated GSSEAP_UNUSED,
13664 + gss_buffer_t type_id GSSEAP_UNUSED) const
13669 + virtual void releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
13670 + gss_any_t input GSSEAP_UNUSED) const
13674 + /* prefix to be prepended to attributes emitted by gss_get_name_attribute */
13675 + virtual const char *prefix(void) const
13680 + /* optional key for storing JSON dictionary */
13681 + virtual const char *name(void) const
13686 + virtual bool initWithJsonObject(const gss_eap_attr_ctx *manager,
13687 + JSONObject &object GSSEAP_UNUSED)
13689 + return initWithManager(manager);
13693 + virtual JSONObject jsonRepresentation(void) const
13695 + return JSONObject::null();
13698 + virtual time_t getExpiryTime(void) const { return 0; }
13700 + virtual OM_uint32 mapException(OM_uint32 *minor GSSEAP_UNUSED,
13701 + std::exception &e GSSEAP_UNUSED) const
13703 + return GSS_S_CONTINUE_NEEDED;
13706 + static bool init(void) { return true; }
13707 + static void finalize(void) {}
13709 + static gss_eap_attr_provider *createAttrContext(void) { return NULL; }
13712 + const gss_eap_attr_ctx *m_manager;
13715 + /* make non-copyable */
13716 + gss_eap_attr_provider(const gss_eap_attr_provider&);
13717 + gss_eap_attr_provider& operator=(const gss_eap_attr_provider&);
13720 +typedef gss_eap_attr_provider *(*gss_eap_attr_create_provider)(void);
13723 + * Attribute context: this manages a set of providers for a given
13724 + * security context.
13726 +struct gss_eap_attr_ctx
13729 + gss_eap_attr_ctx(void);
13730 + ~gss_eap_attr_ctx(void);
13732 + bool initWithExistingContext(const gss_eap_attr_ctx *manager);
13733 + bool initWithGssContext(const gss_cred_id_t cred,
13734 + const gss_ctx_id_t ctx);
13736 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
13737 + bool getAttributeTypes(gss_buffer_set_t *attrs);
13739 + bool setAttribute(int complete,
13740 + const gss_buffer_t attr,
13741 + const gss_buffer_t value);
13742 + bool deleteAttribute(const gss_buffer_t value);
13743 + bool getAttribute(const gss_buffer_t attr,
13744 + int *authenticated,
13746 + gss_buffer_t value,
13747 + gss_buffer_t display_value,
13748 + int *more) const;
13749 + gss_any_t mapToAny(int authenticated,
13750 + gss_buffer_t type_id) const;
13751 + void releaseAnyNameMapping(gss_buffer_t type_id,
13752 + gss_any_t input) const;
13754 + void exportToBuffer(gss_buffer_t buffer) const;
13755 + bool initWithBuffer(const gss_buffer_t buffer);
13757 + static std::string
13758 + composeAttributeName(const gss_buffer_t prefix,
13759 + const gss_buffer_t suffix);
13761 + decomposeAttributeName(const gss_buffer_t attribute,
13762 + gss_buffer_t prefix,
13763 + gss_buffer_t suffix);
13765 + composeAttributeName(const gss_buffer_t prefix,
13766 + const gss_buffer_t suffix,
13767 + gss_buffer_t attribute);
13770 + composeAttributeName(unsigned int type,
13771 + const gss_buffer_t suffix);
13773 + decomposeAttributeName(const gss_buffer_t attribute,
13774 + unsigned int *type,
13775 + gss_buffer_t suffix) const;
13777 + composeAttributeName(unsigned int type,
13778 + const gss_buffer_t suffix,
13779 + gss_buffer_t attribute) const;
13781 + gss_eap_attr_provider *getProvider(unsigned int type) const;
13784 + registerProvider(unsigned int type,
13785 + gss_eap_attr_create_provider factory);
13787 + unregisterProvider(unsigned int type);
13789 + time_t getExpiryTime(void) const;
13790 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
13793 + bool providerEnabled(unsigned int type) const;
13794 + void releaseProvider(unsigned int type);
13796 + unsigned int attributePrefixToType(const gss_buffer_t prefix) const;
13797 + gss_buffer_desc attributeTypeToPrefix(unsigned int type) const;
13799 + bool initWithJsonObject(JSONObject &object);
13800 + JSONObject jsonRepresentation(void) const;
13802 + gss_eap_attr_provider *getPrimaryProvider(void) const;
13804 + /* make non-copyable */
13805 + gss_eap_attr_ctx(const gss_eap_attr_ctx&);
13806 + gss_eap_attr_ctx& operator=(const gss_eap_attr_ctx&);
13808 + uint32_t m_flags;
13809 + gss_eap_attr_provider *m_providers[ATTR_TYPE_MAX + 1];
13812 +#endif /* __cplusplus */
13814 +#include "util_radius.h"
13815 +#include "util_saml.h"
13816 +#include "util_shib.h"
13818 +#ifdef __cplusplus
13820 +static inline void
13821 +duplicateBuffer(gss_buffer_desc &src, gss_buffer_t dst)
13825 + if (GSS_ERROR(duplicateBuffer(&minor, &src, dst)))
13826 + throw std::bad_alloc();
13829 +static inline void
13830 +duplicateBuffer(std::string &str, gss_buffer_t buffer)
13832 + gss_buffer_desc tmp;
13834 + tmp.length = str.length();
13835 + tmp.value = (char *)str.c_str();
13837 + duplicateBuffer(tmp, buffer);
13841 +struct gss_eap_attr_ctx;
13844 +#ifdef __cplusplus
13849 + * C wrappers for attribute context functions. These match their
13850 + * GSS naming extension equivalents. The caller is required to
13851 + * obtain the name mutex.
13855 +gssEapCreateAttrContext(OM_uint32 *minor,
13856 + gss_cred_id_t acceptorCred,
13857 + gss_ctx_id_t acceptorCtx,
13858 + struct gss_eap_attr_ctx **pAttrCtx,
13859 + time_t *pExpiryTime);
13862 +gssEapInquireName(OM_uint32 *minor,
13865 + gss_OID *MN_mech,
13866 + gss_buffer_set_t *attrs);
13869 +gssEapGetNameAttribute(OM_uint32 *minor,
13871 + gss_buffer_t attr,
13872 + int *authenticated,
13874 + gss_buffer_t value,
13875 + gss_buffer_t display_value,
13879 +gssEapDeleteNameAttribute(OM_uint32 *minor,
13881 + gss_buffer_t attr);
13884 +gssEapSetNameAttribute(OM_uint32 *minor,
13887 + gss_buffer_t attr,
13888 + gss_buffer_t value);
13891 +gssEapExportAttrContext(OM_uint32 *minor,
13893 + gss_buffer_t buffer);
13896 +gssEapImportAttrContext(OM_uint32 *minor,
13897 + gss_buffer_t buffer,
13898 + gss_name_t name);
13901 +gssEapDuplicateAttrContext(OM_uint32 *minor,
13906 +gssEapMapNameToAny(OM_uint32 *minor,
13908 + int authenticated,
13909 + gss_buffer_t type_id,
13910 + gss_any_t *output);
13913 +gssEapReleaseAnyNameMapping(OM_uint32 *minor,
13915 + gss_buffer_t type_id,
13916 + gss_any_t *input);
13919 +gssEapReleaseAttrContext(OM_uint32 *minor,
13920 + gss_name_t name);
13923 +gssEapAttrProvidersFinalize(OM_uint32 *minor);
13925 +#ifdef __cplusplus
13929 +#endif /* _UTIL_ATTR_H_ */
13930 diff --git a/mech_eap/util_base64.c b/mech_eap/util_base64.c
13931 new file mode 100644
13932 index 0000000..aaa1ea8
13934 +++ b/mech_eap/util_base64.c
13937 + * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
13938 + * (Royal Institute of Technology, Stockholm, Sweden).
13939 + * All rights reserved.
13941 + * Redistribution and use in source and binary forms, with or without
13942 + * modification, are permitted provided that the following conditions
13945 + * 1. Redistributions of source code must retain the above copyright
13946 + * notice, this list of conditions and the following disclaimer.
13948 + * 2. Redistributions in binary form must reproduce the above copyright
13949 + * notice, this list of conditions and the following disclaimer in the
13950 + * documentation and/or other materials provided with the distribution.
13952 + * 3. Neither the name of the Institute nor the names of its contributors
13953 + * may be used to endorse or promote products derived from this software
13954 + * without specific prior written permission.
13956 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
13957 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13958 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13959 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
13960 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13961 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13962 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13963 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13964 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13965 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13969 +#include "gssapiP_eap.h"
13971 +static const char base64_chars[] =
13972 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13978 + for (p = base64_chars; *p; p++)
13980 + return p - base64_chars;
13985 +base64Encode(const void *data, int size, char **str)
13990 + const unsigned char *q;
13992 + if (size > INT_MAX/4 || size < 0) {
13997 + p = s = (char *)GSSEAP_MALLOC(BASE64_EXPAND(size));
14002 + q = (const unsigned char *) data;
14004 + for (i = 0; i < size;) {
14014 + p[0] = base64_chars[(c & 0x00fc0000) >> 18];
14015 + p[1] = base64_chars[(c & 0x0003f000) >> 12];
14016 + p[2] = base64_chars[(c & 0x00000fc0) >> 6];
14017 + p[3] = base64_chars[(c & 0x0000003f) >> 0];
14020 + if (i > size + 1)
14026 + return strlen(s);
14029 +#define DECODE_ERROR 0xffffffff
14031 +static unsigned int
14032 +token_decode(const char *token)
14035 + unsigned int val = 0;
14037 + if (strlen(token) < 4)
14038 + return DECODE_ERROR;
14039 + for (i = 0; i < 4; i++) {
14041 + if (token[i] == '=')
14043 + else if (marker > 0)
14044 + return DECODE_ERROR;
14046 + val += pos(token[i]);
14049 + return DECODE_ERROR;
14050 + return (marker << 24) | val;
14054 +base64Decode(const char *str, void *data)
14057 + unsigned char *q;
14062 + while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
14063 + unsigned int val = token_decode(p);
14064 + unsigned int marker = (val >> 24) & 0xff;
14065 + if (val == DECODE_ERROR)
14067 + *q++ = (val >> 16) & 0xff;
14069 + *q++ = (val >> 8) & 0xff;
14071 + *q++ = val & 0xff;
14076 + return q - (unsigned char *) data;
14080 +base64Valid(const char *str)
14082 + const char *p = str;
14085 + while (*p && *p && (*p == '=' || strchr(base64_chars, *p))) {
14086 + unsigned int val = token_decode(p);
14087 + if (val == DECODE_ERROR) {
14097 diff --git a/mech_eap/util_base64.h b/mech_eap/util_base64.h
14098 new file mode 100644
14099 index 0000000..d015efe
14101 +++ b/mech_eap/util_base64.h
14104 + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
14105 + * (Royal Institute of Technology, Stockholm, Sweden).
14106 + * All rights reserved.
14108 + * Redistribution and use in source and binary forms, with or without
14109 + * modification, are permitted provided that the following conditions
14112 + * 1. Redistributions of source code must retain the above copyright
14113 + * notice, this list of conditions and the following disclaimer.
14115 + * 2. Redistributions in binary form must reproduce the above copyright
14116 + * notice, this list of conditions and the following disclaimer in the
14117 + * documentation and/or other materials provided with the distribution.
14119 + * 3. Neither the name of the Institute nor the names of its contributors
14120 + * may be used to endorse or promote products derived from this software
14121 + * without specific prior written permission.
14123 + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
14124 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14125 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14126 + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
14127 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14128 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14129 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14130 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14131 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14132 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14138 +#ifndef _UTIL_BASE64_H_
14139 +#define _UTIL_BASE64_H_
14141 +#ifdef __cplusplus
14146 +base64Encode(const void *, int, char **);
14149 +base64Decode(const char *, void *);
14152 +base64Valid(const char *str);
14154 +#define BASE64_EXPAND(n) (n * 4 / 3 + 4)
14156 +#ifdef __cplusplus
14161 diff --git a/mech_eap/util_buffer.c b/mech_eap/util_buffer.c
14162 new file mode 100644
14163 index 0000000..e135db9
14165 +++ b/mech_eap/util_buffer.c
14168 + * Copyright (c) 2011, JANET(UK)
14169 + * All rights reserved.
14171 + * Redistribution and use in source and binary forms, with or without
14172 + * modification, are permitted provided that the following conditions
14175 + * 1. Redistributions of source code must retain the above copyright
14176 + * notice, this list of conditions and the following disclaimer.
14178 + * 2. Redistributions in binary form must reproduce the above copyright
14179 + * notice, this list of conditions and the following disclaimer in the
14180 + * documentation and/or other materials provided with the distribution.
14182 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14183 + * may be used to endorse or promote products derived from this software
14184 + * without specific prior written permission.
14186 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14187 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14188 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14189 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14190 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14191 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14192 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14193 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14194 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14195 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14200 + * Buffer handling helpers.
14203 +#include "gssapiP_eap.h"
14206 +makeStringBuffer(OM_uint32 *minor,
14207 + const char *string,
14208 + gss_buffer_t buffer)
14210 + size_t len = strlen(string);
14212 + buffer->value = GSSEAP_MALLOC(len + 1);
14213 + if (buffer->value == NULL) {
14215 + return GSS_S_FAILURE;
14217 + memcpy(buffer->value, string, len + 1);
14218 + buffer->length = len;
14221 + return GSS_S_COMPLETE;
14225 +bufferToString(OM_uint32 *minor,
14226 + const gss_buffer_t buffer,
14231 + s = GSSEAP_MALLOC(buffer->length + 1);
14234 + return GSS_S_FAILURE;
14236 + memcpy(s, buffer->value, buffer->length);
14237 + s[buffer->length] = '\0';
14242 + return GSS_S_COMPLETE;
14246 +duplicateBuffer(OM_uint32 *minor,
14247 + const gss_buffer_t src,
14248 + gss_buffer_t dst)
14251 + dst->value = NULL;
14253 + if (src == GSS_C_NO_BUFFER)
14254 + return GSS_S_COMPLETE;
14256 + dst->value = GSSEAP_MALLOC(src->length + 1);
14257 + if (dst->value == NULL) {
14259 + return GSS_S_FAILURE;
14262 + dst->length = src->length;
14263 + memcpy(dst->value, src->value, dst->length);
14265 + ((unsigned char *)dst->value)[dst->length] = '\0';
14268 + return GSS_S_COMPLETE;
14270 diff --git a/mech_eap/util_cksum.c b/mech_eap/util_cksum.c
14271 new file mode 100644
14272 index 0000000..aedc93e
14274 +++ b/mech_eap/util_cksum.c
14277 + * Copyright (c) 2011, JANET(UK)
14278 + * All rights reserved.
14280 + * Redistribution and use in source and binary forms, with or without
14281 + * modification, are permitted provided that the following conditions
14284 + * 1. Redistributions of source code must retain the above copyright
14285 + * notice, this list of conditions and the following disclaimer.
14287 + * 2. Redistributions in binary form must reproduce the above copyright
14288 + * notice, this list of conditions and the following disclaimer in the
14289 + * documentation and/or other materials provided with the distribution.
14291 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14292 + * may be used to endorse or promote products derived from this software
14293 + * without specific prior written permission.
14295 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14296 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14297 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14298 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14299 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14300 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14301 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14302 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14303 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14304 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14308 + * Copyright 1993 by OpenVision Technologies, Inc.
14310 + * Permission to use, copy, modify, distribute, and sell this software
14311 + * and its documentation for any purpose is hereby granted without fee,
14312 + * provided that the above copyright notice appears in all copies and
14313 + * that both that copyright notice and this permission notice appear in
14314 + * supporting documentation, and that the name of OpenVision not be used
14315 + * in advertising or publicity pertaining to distribution of the software
14316 + * without specific, written prior permission. OpenVision makes no
14317 + * representations about the suitability of this software for any
14318 + * purpose. It is provided "as is" without express or implied warranty.
14320 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
14321 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
14322 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
14323 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
14324 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14325 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14326 + * PERFORMANCE OF THIS SOFTWARE.
14330 + * Message protection services: checksum helpers.
14333 +#include "gssapiP_eap.h"
14336 +gssEapChecksum(krb5_context context,
14337 + krb5_cksumtype type,
14339 +#ifdef HAVE_HEIMDAL_VERSION
14340 + krb5_crypto crypto,
14342 + krb5_keyblock *crypto,
14344 + krb5_keyusage sign_usage,
14345 + gss_iov_buffer_desc *iov,
14350 + krb5_error_code code;
14351 + gss_iov_buffer_desc *header;
14352 + gss_iov_buffer_desc *trailer;
14353 + krb5_crypto_iov *kiov;
14354 + size_t kiov_count;
14356 + size_t k5_checksumlen;
14361 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen);
14365 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
14366 + GSSEAP_ASSERT(header != NULL);
14368 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
14369 + GSSEAP_ASSERT(rrc != 0 || trailer != NULL);
14371 + if (trailer == NULL) {
14372 + if (rrc != k5_checksumlen)
14373 + return KRB5_BAD_MSIZE;
14374 + if (header->buffer.length != 16 + k5_checksumlen)
14375 + return KRB5_BAD_MSIZE;
14376 + } else if (trailer->buffer.length != k5_checksumlen)
14377 + return KRB5_BAD_MSIZE;
14379 + kiov_count = 2 + iov_count;
14380 + kiov = (krb5_crypto_iov *)GSSEAP_MALLOC(kiov_count * sizeof(krb5_crypto_iov));
14381 + if (kiov == NULL)
14384 + /* Checksum over ( Data | Header ) */
14387 + for (j = 0; j < iov_count; j++) {
14388 + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
14389 + kiov[i].data.length = iov[j].buffer.length;
14390 + kiov[i].data.data = (char *)iov[j].buffer.value;
14395 + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
14396 + kiov[i].data.length = 16;
14397 + kiov[i].data.data = (char *)header->buffer.value;
14401 + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
14402 + if (trailer == NULL) {
14403 + kiov[i].data.length = header->buffer.length - 16;
14404 + kiov[i].data.data = (char *)header->buffer.value + 16;
14406 + kiov[i].data.length = trailer->buffer.length;
14407 + kiov[i].data.data = (char *)trailer->buffer.value;
14411 +#ifdef HAVE_HEIMDAL_VERSION
14413 + code = krb5_verify_checksum_iov(context, crypto, sign_usage,
14414 + kiov, kiov_count, &type);
14415 + *valid = (code == 0);
14417 + code = krb5_create_checksum_iov(context, crypto, sign_usage,
14418 + kiov, kiov_count, &type);
14422 + krb5_boolean kvalid = FALSE;
14424 + code = krb5_c_verify_checksum_iov(context, type, crypto,
14425 + sign_usage, kiov, kiov_count, &kvalid);
14429 + code = krb5_c_make_checksum_iov(context, type, crypto,
14430 + sign_usage, kiov, kiov_count);
14432 +#endif /* HAVE_HEIMDAL_VERSION */
14434 + GSSEAP_FREE(kiov);
14440 +gssEapSign(krb5_context context,
14441 + krb5_cksumtype type,
14443 +#ifdef HAVE_HEIMDAL_VERSION
14444 + krb5_crypto crypto,
14446 + krb5_keyblock *crypto,
14448 + krb5_keyusage sign_usage,
14449 + gss_iov_buffer_desc *iov,
14452 + return gssEapChecksum(context, type, rrc, crypto,
14453 + sign_usage, iov, iov_count, 0, NULL);
14457 +gssEapVerify(krb5_context context,
14458 + krb5_cksumtype type,
14460 +#ifdef HAVE_HEIMDAL_VERSION
14461 + krb5_crypto crypto,
14463 + krb5_keyblock *crypto,
14465 + krb5_keyusage sign_usage,
14466 + gss_iov_buffer_desc *iov,
14470 + return gssEapChecksum(context, type, rrc, crypto,
14471 + sign_usage, iov, iov_count, 1, valid);
14476 +gssEapEncodeGssChannelBindings(OM_uint32 *minor,
14477 + gss_channel_bindings_t chanBindings,
14478 + gss_buffer_t encodedBindings)
14480 + OM_uint32 major, tmpMinor;
14482 + unsigned char *p;
14484 + if (chanBindings != GSS_C_NO_CHANNEL_BINDINGS) {
14486 + length += chanBindings->initiator_address.length;
14487 + length += chanBindings->acceptor_address.length;
14488 + length += chanBindings->application_data.length;
14490 + encodedBindings->value = GSSEAP_MALLOC(length);
14491 + if (encodedBindings->value == NULL) {
14493 + return GSS_S_FAILURE;
14496 + encodedBindings->length = length;
14497 + p = (unsigned char *)encodedBindings->value;
14499 + store_uint32_be(chanBindings->initiator_addrtype, p);
14500 + store_buffer(&chanBindings->initiator_address, p + 4, 0);
14501 + p += 4 + chanBindings->initiator_address.length;
14503 + store_uint32_be(chanBindings->acceptor_addrtype, p);
14504 + store_buffer(&chanBindings->acceptor_address, p + 4, 0);
14505 + p += 4 + chanBindings->acceptor_address.length;
14507 + store_buffer(&chanBindings->application_data, p, 1);
14508 + p += chanBindings->application_data.length;
14510 + encodedBindings->length = 0;
14511 + encodedBindings->value = NULL;
14515 + return GSS_S_COMPLETE;
14518 diff --git a/mech_eap/util_context.c b/mech_eap/util_context.c
14519 new file mode 100644
14520 index 0000000..e18edc5
14522 +++ b/mech_eap/util_context.c
14525 + * Copyright (c) 2011, JANET(UK)
14526 + * All rights reserved.
14528 + * Redistribution and use in source and binary forms, with or without
14529 + * modification, are permitted provided that the following conditions
14532 + * 1. Redistributions of source code must retain the above copyright
14533 + * notice, this list of conditions and the following disclaimer.
14535 + * 2. Redistributions in binary form must reproduce the above copyright
14536 + * notice, this list of conditions and the following disclaimer in the
14537 + * documentation and/or other materials provided with the distribution.
14539 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14540 + * may be used to endorse or promote products derived from this software
14541 + * without specific prior written permission.
14543 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14544 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14545 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14546 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14547 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14548 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14549 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14550 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14551 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14552 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14557 + * Utility routines for context handles.
14560 +#include "gssapiP_eap.h"
14563 +gssEapAllocContext(OM_uint32 *minor,
14564 + gss_ctx_id_t *pCtx)
14566 + OM_uint32 tmpMinor;
14567 + gss_ctx_id_t ctx;
14569 + GSSEAP_ASSERT(*pCtx == GSS_C_NO_CONTEXT);
14571 + ctx = (gss_ctx_id_t)GSSEAP_CALLOC(1, sizeof(*ctx));
14572 + if (ctx == NULL) {
14574 + return GSS_S_FAILURE;
14577 + if (GSSEAP_MUTEX_INIT(&ctx->mutex) != 0) {
14578 + *minor = GSSEAP_GET_LAST_ERROR();
14579 + gssEapReleaseContext(&tmpMinor, &ctx);
14580 + return GSS_S_FAILURE;
14583 + ctx->state = GSSEAP_STATE_INITIAL;
14584 + ctx->mechanismUsed = GSS_C_NO_OID;
14587 + * Integrity, confidentiality, sequencing and replay detection are
14588 + * always available. Regardless of what flags are requested in
14589 + * GSS_Init_sec_context, implementations MUST set the flag corresponding
14590 + * to these services in the output of GSS_Init_sec_context and
14591 + * GSS_Accept_sec_context.
14593 + ctx->gssFlags = GSS_C_TRANS_FLAG | /* exporting contexts */
14594 + GSS_C_INTEG_FLAG | /* integrity */
14595 + GSS_C_CONF_FLAG | /* confidentiality */
14596 + GSS_C_SEQUENCE_FLAG | /* sequencing */
14597 + GSS_C_REPLAY_FLAG; /* replay detection */
14601 + return GSS_S_COMPLETE;
14605 +releaseInitiatorContext(struct gss_eap_initiator_ctx *ctx)
14607 + eap_peer_sm_deinit(ctx->eap);
14610 +#ifdef GSSEAP_ENABLE_ACCEPTOR
14612 +releaseAcceptorContext(struct gss_eap_acceptor_ctx *ctx)
14614 + OM_uint32 tmpMinor;
14616 + if (ctx->radConn != NULL)
14617 + rs_conn_destroy(ctx->radConn);
14618 + if (ctx->radContext != NULL)
14619 + rs_context_destroy(ctx->radContext);
14620 + if (ctx->radServer != NULL)
14621 + GSSEAP_FREE(ctx->radServer);
14622 + gss_release_buffer(&tmpMinor, &ctx->state);
14623 + if (ctx->vps != NULL)
14624 + gssEapRadiusFreeAvps(&tmpMinor, &ctx->vps);
14626 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
14629 +gssEapReleaseContext(OM_uint32 *minor,
14630 + gss_ctx_id_t *pCtx)
14632 + OM_uint32 tmpMinor;
14633 + gss_ctx_id_t ctx = *pCtx;
14634 + krb5_context krbContext = NULL;
14636 + if (ctx == GSS_C_NO_CONTEXT) {
14637 + return GSS_S_COMPLETE;
14640 + gssEapKerberosInit(&tmpMinor, &krbContext);
14642 +#ifdef GSSEAP_ENABLE_REAUTH
14643 + if (ctx->flags & CTX_FLAG_KRB_REAUTH) {
14644 + gssDeleteSecContext(&tmpMinor, &ctx->reauthCtx, GSS_C_NO_BUFFER);
14646 +#endif /* GSSEAP_ENABLE_REAUTH */
14647 + if (CTX_IS_INITIATOR(ctx)) {
14648 + releaseInitiatorContext(&ctx->initiatorCtx);
14650 +#ifdef GSSEAP_ENABLE_ACCEPTOR
14652 + releaseAcceptorContext(&ctx->acceptorCtx);
14654 +#endif /* GSSEAP_ENABLE_ACCEPTOR */
14656 + krb5_free_keyblock_contents(krbContext, &ctx->rfc3961Key);
14657 + gssEapReleaseName(&tmpMinor, &ctx->initiatorName);
14658 + gssEapReleaseName(&tmpMinor, &ctx->acceptorName);
14659 + gssEapReleaseOid(&tmpMinor, &ctx->mechanismUsed);
14660 + sequenceFree(&tmpMinor, &ctx->seqState);
14661 + gssEapReleaseCred(&tmpMinor, &ctx->cred);
14663 + GSSEAP_MUTEX_DESTROY(&ctx->mutex);
14665 + memset(ctx, 0, sizeof(*ctx));
14666 + GSSEAP_FREE(ctx);
14667 + *pCtx = GSS_C_NO_CONTEXT;
14670 + return GSS_S_COMPLETE;
14674 +gssEapMakeToken(OM_uint32 *minor,
14675 + gss_ctx_id_t ctx,
14676 + const gss_buffer_t innerToken,
14677 + enum gss_eap_token_type tokenType,
14678 + gss_buffer_t outputToken)
14680 + unsigned char *p;
14682 + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID);
14684 + outputToken->length = tokenSize(ctx->mechanismUsed, innerToken->length);
14685 + outputToken->value = GSSEAP_MALLOC(outputToken->length);
14686 + if (outputToken->value == NULL) {
14688 + return GSS_S_FAILURE;
14691 + p = (unsigned char *)outputToken->value;
14692 + makeTokenHeader(ctx->mechanismUsed, innerToken->length, &p, tokenType);
14693 + memcpy(p, innerToken->value, innerToken->length);
14696 + return GSS_S_COMPLETE;
14700 +gssEapVerifyToken(OM_uint32 *minor,
14701 + gss_ctx_id_t ctx,
14702 + const gss_buffer_t inputToken,
14703 + enum gss_eap_token_type *actualToken,
14704 + gss_buffer_t innerInputToken)
14708 + unsigned char *p = (unsigned char *)inputToken->value;
14709 + gss_OID_desc oidBuf;
14712 + if (ctx->mechanismUsed != GSS_C_NO_OID) {
14713 + oid = ctx->mechanismUsed;
14715 + oidBuf.elements = NULL;
14716 + oidBuf.length = 0;
14720 + major = verifyTokenHeader(minor, oid, &bodySize, &p,
14721 + inputToken->length, actualToken);
14722 + if (GSS_ERROR(major))
14725 + if (ctx->mechanismUsed == GSS_C_NO_OID) {
14726 + major = gssEapCanonicalizeOid(minor, oid, 0, &ctx->mechanismUsed);
14727 + if (GSS_ERROR(major))
14731 + innerInputToken->length = bodySize;
14732 + innerInputToken->value = p;
14735 + return GSS_S_COMPLETE;
14739 +gssEapContextTime(OM_uint32 *minor,
14740 + gss_ctx_id_t context_handle,
14741 + OM_uint32 *time_rec)
14745 + if (context_handle->expiryTime == 0) {
14746 + *time_rec = GSS_C_INDEFINITE;
14748 + time_t now, lifetime;
14751 + lifetime = context_handle->expiryTime - now;
14752 + if (lifetime <= 0) {
14754 + return GSS_S_CONTEXT_EXPIRED;
14756 + *time_rec = lifetime;
14759 + return GSS_S_COMPLETE;
14763 +gssEapMakeOrVerifyTokenMIC(OM_uint32 *minor,
14764 + gss_ctx_id_t ctx,
14765 + gss_buffer_t tokenMIC,
14769 + gss_iov_buffer_desc *iov = NULL;
14771 + enum gss_eap_token_type tokType;
14772 + OM_uint32 micTokType;
14773 + unsigned char wireTokType[2];
14774 + unsigned char *innerTokTypes = NULL, *innerTokLengths = NULL;
14775 + const struct gss_eap_token_buffer_set *tokens;
14777 + tokens = verifyMIC ? ctx->inputTokens : ctx->outputTokens;
14779 + GSSEAP_ASSERT(tokens != NULL);
14781 + iov = GSSEAP_CALLOC(2 + (3 * tokens->buffers.count) + 1, sizeof(*iov));
14782 + if (iov == NULL) {
14783 + major = GSS_S_FAILURE;
14788 + innerTokTypes = GSSEAP_MALLOC(4 * tokens->buffers.count);
14789 + if (innerTokTypes == NULL) {
14791 + major = GSS_S_FAILURE;
14795 + innerTokLengths = GSSEAP_MALLOC(4 * tokens->buffers.count);
14796 + if (innerTokLengths == NULL) {
14797 + major = GSS_S_FAILURE;
14802 + /* Mechanism OID */
14803 + GSSEAP_ASSERT(ctx->mechanismUsed != GSS_C_NO_OID);
14804 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14805 + iov[i].buffer.length = ctx->mechanismUsed->length;
14806 + iov[i].buffer.value = ctx->mechanismUsed->elements;
14810 + if (CTX_IS_INITIATOR(ctx) ^ verifyMIC) {
14811 + tokType = TOK_TYPE_INITIATOR_CONTEXT;
14812 + micTokType = ITOK_TYPE_INITIATOR_MIC;
14814 + tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
14815 + micTokType = ITOK_TYPE_ACCEPTOR_MIC;
14817 + store_uint16_be(tokType, wireTokType);
14819 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14820 + iov[i].buffer.length = sizeof(wireTokType);
14821 + iov[i].buffer.value = wireTokType;
14824 + for (j = 0; j < tokens->buffers.count; j++) {
14826 + (tokens->types[j] & ITOK_TYPE_MASK) == micTokType)
14827 + continue; /* will use this slot for trailer */
14829 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14830 + iov[i].buffer.length = 4;
14831 + iov[i].buffer.value = &innerTokTypes[j * 4];
14832 + store_uint32_be(tokens->types[j] & ~(ITOK_FLAG_VERIFIED),
14833 + iov[i].buffer.value);
14836 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14837 + iov[i].buffer.length = 4;
14838 + iov[i].buffer.value = &innerTokLengths[j * 4];
14839 + store_uint32_be(tokens->buffers.elements[j].length,
14840 + iov[i].buffer.value);
14843 + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA;
14844 + iov[i].buffer = tokens->buffers.elements[j];
14849 + GSSEAP_ASSERT(tokenMIC->length >= 16);
14851 + GSSEAP_ASSERT(i < 2 + (3 * tokens->buffers.count));
14853 + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER;
14854 + iov[i].buffer = *tokenMIC;
14857 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, NULL, NULL,
14858 + iov, i, TOK_TYPE_MIC);
14860 + iov[i++].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
14861 + major = gssEapWrapOrGetMIC(minor, ctx, FALSE, NULL,
14862 + iov, i, TOK_TYPE_MIC);
14863 + if (!GSS_ERROR(major))
14864 + *tokenMIC = iov[i - 1].buffer;
14869 + gssEapReleaseIov(iov, tokens->buffers.count);
14870 + if (innerTokTypes != NULL)
14871 + GSSEAP_FREE(innerTokTypes);
14872 + if (innerTokLengths != NULL)
14873 + GSSEAP_FREE(innerTokLengths);
14879 +gssEapMakeTokenMIC(OM_uint32 *minor,
14880 + gss_ctx_id_t ctx,
14881 + gss_buffer_t tokenMIC)
14883 + tokenMIC->length = 0;
14884 + tokenMIC->value = NULL;
14886 + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, FALSE);
14890 +gssEapVerifyTokenMIC(OM_uint32 *minor,
14891 + gss_ctx_id_t ctx,
14892 + const gss_buffer_t tokenMIC)
14894 + if (tokenMIC->length < 16) {
14895 + *minor = GSSEAP_TOK_TRUNC;
14896 + return GSS_S_BAD_SIG;
14899 + return gssEapMakeOrVerifyTokenMIC(minor, ctx, tokenMIC, TRUE);
14901 diff --git a/mech_eap/util_cred.c b/mech_eap/util_cred.c
14902 new file mode 100644
14903 index 0000000..746bd61
14905 +++ b/mech_eap/util_cred.c
14908 + * Copyright (c) 2011, JANET(UK)
14909 + * All rights reserved.
14911 + * Redistribution and use in source and binary forms, with or without
14912 + * modification, are permitted provided that the following conditions
14915 + * 1. Redistributions of source code must retain the above copyright
14916 + * notice, this list of conditions and the following disclaimer.
14918 + * 2. Redistributions in binary form must reproduce the above copyright
14919 + * notice, this list of conditions and the following disclaimer in the
14920 + * documentation and/or other materials provided with the distribution.
14922 + * 3. Neither the name of JANET(UK) nor the names of its contributors
14923 + * may be used to endorse or promote products derived from this software
14924 + * without specific prior written permission.
14926 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14927 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14928 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14929 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
14930 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14931 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14932 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14933 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14934 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14935 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14940 + * Utility routines for credential handles.
14943 +#include "gssapiP_eap.h"
14946 +# include <shlobj.h> /* may need to use ShFolder.h instead */
14947 +# include <stdio.h>
14953 +gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred)
14955 + OM_uint32 tmpMinor;
14956 + gss_cred_id_t cred;
14958 + *pCred = GSS_C_NO_CREDENTIAL;
14960 + cred = (gss_cred_id_t)GSSEAP_CALLOC(1, sizeof(*cred));
14961 + if (cred == NULL) {
14963 + return GSS_S_FAILURE;
14966 + if (GSSEAP_MUTEX_INIT(&cred->mutex) != 0) {
14967 + *minor = GSSEAP_GET_LAST_ERROR();
14968 + gssEapReleaseCred(&tmpMinor, &cred);
14969 + return GSS_S_FAILURE;
14975 + return GSS_S_COMPLETE;
14979 +zeroAndReleasePassword(gss_buffer_t password)
14981 + if (password->value != NULL) {
14982 + memset(password->value, 0, password->length);
14983 + GSSEAP_FREE(password->value);
14986 + password->value = NULL;
14987 + password->length = 0;
14991 +gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred)
14993 + OM_uint32 tmpMinor;
14994 + gss_cred_id_t cred = *pCred;
14995 + krb5_context krbContext = NULL;
14997 + if (cred == GSS_C_NO_CREDENTIAL) {
14998 + return GSS_S_COMPLETE;
15001 + GSSEAP_KRB_INIT(&krbContext);
15003 + gssEapReleaseName(&tmpMinor, &cred->name);
15004 + gssEapReleaseName(&tmpMinor, &cred->target);
15006 + zeroAndReleasePassword(&cred->password);
15008 + gss_release_buffer(&tmpMinor, &cred->radiusConfigFile);
15009 + gss_release_buffer(&tmpMinor, &cred->radiusConfigStanza);
15010 + gss_release_buffer(&tmpMinor, &cred->caCertificate);
15011 + gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
15012 + gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
15014 +#ifdef GSSEAP_ENABLE_REAUTH
15015 + if (cred->krbCredCache != NULL) {
15016 + if (cred->flags & CRED_FLAG_DEFAULT_CCACHE)
15017 + krb5_cc_close(krbContext, cred->krbCredCache);
15019 + krb5_cc_destroy(krbContext, cred->krbCredCache);
15021 + if (cred->reauthCred != GSS_C_NO_CREDENTIAL)
15022 + gssReleaseCred(&tmpMinor, &cred->reauthCred);
15025 + GSSEAP_MUTEX_DESTROY(&cred->mutex);
15026 + memset(cred, 0, sizeof(*cred));
15027 + GSSEAP_FREE(cred);
15031 + return GSS_S_COMPLETE;
15035 +readStaticIdentityFile(OM_uint32 *minor,
15036 + gss_buffer_t defaultIdentity,
15037 + gss_buffer_t defaultPassword)
15039 + OM_uint32 major, tmpMinor;
15041 + char buf[BUFSIZ];
15042 + char *ccacheName;
15045 + struct passwd *pw = NULL, pwd;
15046 + char pwbuf[BUFSIZ];
15049 + defaultIdentity->length = 0;
15050 + defaultIdentity->value = NULL;
15052 + if (defaultPassword != GSS_C_NO_BUFFER) {
15053 + defaultPassword->length = 0;
15054 + defaultPassword->value = NULL;
15057 + ccacheName = getenv("GSSEAP_IDENTITY");
15058 + if (ccacheName == NULL) {
15060 + TCHAR szPath[MAX_PATH];
15062 + if (!SUCCEEDED(SHGetFolderPath(NULL,
15063 + CSIDL_APPDATA, /* |CSIDL_FLAG_CREATE */
15064 + NULL, /* User access token */
15065 + 0, /* SHGFP_TYPE_CURRENT */
15067 + major = GSS_S_CRED_UNAVAIL;
15068 + *minor = GSSEAP_GET_LAST_ERROR(); /* XXX */
15072 + snprintf(buf, sizeof(buf), "%s/.gss_eap_id", szPath);
15074 + if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 ||
15075 + pw == NULL || pw->pw_dir == NULL) {
15076 + major = GSS_S_CRED_UNAVAIL;
15077 + *minor = GSSEAP_GET_LAST_ERROR();
15081 + snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir);
15082 +#endif /* WIN32 */
15083 + ccacheName = buf;
15086 + fp = fopen(ccacheName, "r");
15087 + if (fp == NULL) {
15088 + major = GSS_S_CRED_UNAVAIL;
15089 + *minor = GSSEAP_NO_DEFAULT_CRED;
15093 + while (fgets(buf, sizeof(buf), fp) != NULL) {
15094 + gss_buffer_desc src, *dst;
15096 + src.length = strlen(buf);
15099 + if (src.length == 0)
15102 + if (buf[src.length - 1] == '\n') {
15103 + buf[src.length - 1] = '\0';
15104 + if (--src.length == 0)
15109 + dst = defaultIdentity;
15111 + dst = defaultPassword;
15115 + if (dst != GSS_C_NO_BUFFER) {
15116 + major = duplicateBuffer(minor, &src, dst);
15117 + if (GSS_ERROR(major))
15124 + if (defaultIdentity->length == 0) {
15125 + major = GSS_S_CRED_UNAVAIL;
15126 + *minor = GSSEAP_NO_DEFAULT_CRED;
15130 + major = GSS_S_COMPLETE;
15137 + if (GSS_ERROR(major)) {
15138 + gss_release_buffer(&tmpMinor, defaultIdentity);
15139 + zeroAndReleasePassword(defaultPassword);
15142 + memset(buf, 0, sizeof(buf));
15148 +gssEapPrimaryMechForCred(gss_cred_id_t cred)
15150 + gss_OID nameMech = GSS_C_NO_OID;
15152 + if (cred->mechanisms != GSS_C_NO_OID_SET &&
15153 + cred->mechanisms->count == 1)
15154 + nameMech = &cred->mechanisms->elements[0];
15160 +gssEapAcquireCred(OM_uint32 *minor,
15161 + const gss_name_t desiredName,
15162 + OM_uint32 timeReq GSSEAP_UNUSED,
15163 + const gss_OID_set desiredMechs,
15165 + gss_cred_id_t *pCred,
15166 + gss_OID_set *pActualMechs,
15167 + OM_uint32 *timeRec)
15169 + OM_uint32 major, tmpMinor;
15170 + gss_cred_id_t cred;
15172 + /* XXX TODO validate with changed set_cred_option API */
15173 + *pCred = GSS_C_NO_CREDENTIAL;
15175 + major = gssEapAllocCred(minor, &cred);
15176 + if (GSS_ERROR(major))
15179 + switch (credUsage) {
15181 + cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT;
15183 + case GSS_C_INITIATE:
15184 + cred->flags |= CRED_FLAG_INITIATE;
15186 + case GSS_C_ACCEPT:
15187 + cred->flags |= CRED_FLAG_ACCEPT;
15190 + major = GSS_S_FAILURE;
15191 + *minor = GSSEAP_BAD_USAGE;
15196 + major = gssEapValidateMechs(minor, desiredMechs);
15197 + if (GSS_ERROR(major))
15200 + major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms);
15201 + if (GSS_ERROR(major))
15204 + if (desiredName != GSS_C_NO_NAME) {
15205 + GSSEAP_MUTEX_LOCK(&desiredName->mutex);
15207 + major = gssEapDuplicateName(minor, desiredName, &cred->name);
15208 + if (GSS_ERROR(major)) {
15209 + GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
15213 + GSSEAP_MUTEX_UNLOCK(&desiredName->mutex);
15216 +#ifdef GSSEAP_ENABLE_ACCEPTOR
15217 + if (cred->flags & CRED_FLAG_ACCEPT) {
15218 + struct rs_context *radContext;
15220 + major = gssEapCreateRadiusContext(minor, cred, &radContext);
15221 + if (GSS_ERROR(major))
15224 + rs_context_destroy(radContext);
15228 + if (pActualMechs != NULL) {
15229 + major = duplicateOidSet(minor, cred->mechanisms, pActualMechs);
15230 + if (GSS_ERROR(major))
15234 + if (timeRec != NULL)
15235 + *timeRec = GSS_C_INDEFINITE;
15239 + major = GSS_S_COMPLETE;
15243 + if (GSS_ERROR(major))
15244 + gssEapReleaseCred(&tmpMinor, &cred);
15250 + * Return TRUE if cred available for mechanism. Caller need no acquire
15251 + * lock because mechanisms list is immutable.
15254 +gssEapCredAvailable(gss_cred_id_t cred, gss_OID mech)
15259 + GSSEAP_ASSERT(mech != GSS_C_NO_OID);
15261 + if (cred == GSS_C_NO_CREDENTIAL || cred->mechanisms == GSS_C_NO_OID_SET)
15264 + gss_test_oid_set_member(&minor, mech, cred->mechanisms, &present);
15270 +staticIdentityFileResolveDefaultIdentity(OM_uint32 *minor,
15271 + const gss_cred_id_t cred,
15272 + gss_name_t *pName)
15274 + OM_uint32 major, tmpMinor;
15275 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
15276 + gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
15278 + *pName = GSS_C_NO_NAME;
15280 + major = readStaticIdentityFile(minor, &defaultIdentity, GSS_C_NO_BUFFER);
15281 + if (major == GSS_S_COMPLETE) {
15282 + major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
15283 + nameMech, pName);
15286 + gss_release_buffer(&tmpMinor, &defaultIdentity);
15292 +gssEapResolveCredIdentity(OM_uint32 *minor,
15293 + gss_cred_id_t cred)
15296 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
15298 + if (cred->name != GSS_C_NO_NAME) {
15300 + return GSS_S_COMPLETE;
15303 + if (cred->flags & CRED_FLAG_ACCEPT) {
15304 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
15305 + char serviceName[5 + MAXHOSTNAMELEN];
15307 + /* default host-based service is host@localhost */
15308 + memcpy(serviceName, "host@", 5);
15309 + if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) {
15310 + *minor = GSSEAP_NO_HOSTNAME;
15311 + return GSS_S_FAILURE;
15314 + nameBuf.value = serviceName;
15315 + nameBuf.length = strlen((char *)nameBuf.value);
15317 + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE,
15318 + nameMech, &cred->name);
15319 + if (GSS_ERROR(major))
15321 + } else if (cred->flags & CRED_FLAG_INITIATE) {
15322 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
15323 + major = libMoonshotResolveDefaultIdentity(minor, cred, &cred->name);
15324 + if (major == GSS_S_CRED_UNAVAIL)
15326 + major = staticIdentityFileResolveDefaultIdentity(minor, cred, &cred->name);
15327 + if (major != GSS_S_CRED_UNAVAIL)
15332 + return GSS_S_COMPLETE;
15336 +gssEapInquireCred(OM_uint32 *minor,
15337 + gss_cred_id_t cred,
15338 + gss_name_t *name,
15339 + OM_uint32 *pLifetime,
15340 + gss_cred_usage_t *cred_usage,
15341 + gss_OID_set *mechanisms)
15344 + time_t now, lifetime;
15346 + if (name != NULL) {
15347 + major = gssEapResolveCredIdentity(minor, cred);
15348 + if (GSS_ERROR(major))
15351 + if (cred->name != GSS_C_NO_NAME) {
15352 + major = gssEapDuplicateName(minor, cred->name, name);
15353 + if (GSS_ERROR(major))
15356 + *name = GSS_C_NO_NAME;
15359 + if (cred_usage != NULL) {
15360 + OM_uint32 flags = (cred->flags & (CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT));
15363 + case CRED_FLAG_INITIATE:
15364 + *cred_usage = GSS_C_INITIATE;
15366 + case CRED_FLAG_ACCEPT:
15367 + *cred_usage = GSS_C_ACCEPT;
15370 + *cred_usage = GSS_C_BOTH;
15375 + if (mechanisms != NULL) {
15376 + if (cred->mechanisms != GSS_C_NO_OID_SET)
15377 + major = duplicateOidSet(minor, cred->mechanisms, mechanisms);
15379 + major = gssEapIndicateMechs(minor, mechanisms);
15380 + if (GSS_ERROR(major))
15384 + if (cred->expiryTime == 0) {
15385 + lifetime = GSS_C_INDEFINITE;
15387 + now = time(NULL);
15388 + lifetime = now - cred->expiryTime;
15389 + if (lifetime < 0)
15393 + if (pLifetime != NULL) {
15394 + *pLifetime = lifetime;
15397 + if (lifetime == 0) {
15398 + major = GSS_S_CREDENTIALS_EXPIRED;
15399 + *minor = GSSEAP_CRED_EXPIRED;
15403 + major = GSS_S_COMPLETE;
15411 +gssEapSetCredPassword(OM_uint32 *minor,
15412 + gss_cred_id_t cred,
15413 + const gss_buffer_t password)
15415 + OM_uint32 major, tmpMinor;
15416 + gss_buffer_desc newPassword = GSS_C_EMPTY_BUFFER;
15418 + if (cred->flags & CRED_FLAG_RESOLVED) {
15419 + major = GSS_S_FAILURE;
15420 + *minor = GSSEAP_CRED_RESOLVED;
15424 + if (password != GSS_C_NO_BUFFER) {
15425 + major = duplicateBuffer(minor, password, &newPassword);
15426 + if (GSS_ERROR(major))
15429 + cred->flags |= CRED_FLAG_PASSWORD;
15431 + cred->flags &= ~(CRED_FLAG_PASSWORD);
15434 + gss_release_buffer(&tmpMinor, &cred->password);
15435 + cred->password = newPassword;
15437 + major = GSS_S_COMPLETE;
15445 +gssEapSetCredService(OM_uint32 *minor,
15446 + gss_cred_id_t cred,
15447 + const gss_name_t target)
15449 + OM_uint32 major, tmpMinor;
15450 + gss_name_t newTarget = GSS_C_NO_NAME;
15452 + if (cred->flags & CRED_FLAG_RESOLVED) {
15453 + major = GSS_S_FAILURE;
15454 + *minor = GSSEAP_CRED_RESOLVED;
15458 + if (target != GSS_C_NO_NAME) {
15459 + major = gssEapDuplicateName(minor, target, &newTarget);
15460 + if (GSS_ERROR(major))
15463 + cred->flags |= CRED_FLAG_TARGET;
15465 + cred->flags &= ~(CRED_FLAG_TARGET);
15468 + gssEapReleaseName(&tmpMinor, &cred->target);
15469 + cred->target = newTarget;
15471 + major = GSS_S_COMPLETE;
15479 +gssEapDuplicateCred(OM_uint32 *minor,
15480 + const gss_cred_id_t src,
15481 + gss_cred_id_t *pDst)
15483 + OM_uint32 major, tmpMinor;
15484 + gss_cred_id_t dst = GSS_C_NO_CREDENTIAL;
15486 + *pDst = GSS_C_NO_CREDENTIAL;
15488 + major = gssEapAllocCred(minor, &dst);
15489 + if (GSS_ERROR(major))
15492 + dst->flags = src->flags;
15494 + if (src->name != GSS_C_NO_NAME) {
15495 + major = gssEapDuplicateName(minor, src->name, &dst->name);
15496 + if (GSS_ERROR(major))
15500 + if (src->target != GSS_C_NO_NAME) {
15501 + major = gssEapDuplicateName(minor, src->target, &dst->target);
15502 + if (GSS_ERROR(major))
15506 + if (src->password.value != NULL) {
15507 + major = duplicateBuffer(minor, &src->password, &dst->password);
15508 + if (GSS_ERROR(major))
15512 + major = duplicateOidSet(minor, src->mechanisms, &dst->mechanisms);
15513 + if (GSS_ERROR(major))
15516 + dst->expiryTime = src->expiryTime;
15518 + if (src->radiusConfigFile.value != NULL)
15519 + duplicateBufferOrCleanup(&src->radiusConfigFile, &dst->radiusConfigFile);
15520 + if (src->radiusConfigStanza.value != NULL)
15521 + duplicateBufferOrCleanup(&src->radiusConfigStanza, &dst->radiusConfigStanza);
15522 + if (src->caCertificate.value != NULL)
15523 + duplicateBufferOrCleanup(&src->caCertificate, &dst->caCertificate);
15524 + if (src->subjectNameConstraint.value != NULL)
15525 + duplicateBufferOrCleanup(&src->subjectNameConstraint, &dst->subjectNameConstraint);
15526 + if (src->subjectAltNameConstraint.value != NULL)
15527 + duplicateBufferOrCleanup(&src->subjectAltNameConstraint, &dst->subjectAltNameConstraint);
15529 +#ifdef GSSEAP_ENABLE_REAUTH
15530 + /* XXX krbCredCache, reauthCred */
15534 + dst = GSS_C_NO_CREDENTIAL;
15536 + major = GSS_S_COMPLETE;
15540 + gssEapReleaseCred(&tmpMinor, &dst);
15546 +staticIdentityFileResolveInitiatorCred(OM_uint32 *minor, gss_cred_id_t cred)
15548 + OM_uint32 major, tmpMinor;
15549 + gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER;
15550 + gss_name_t defaultIdentityName = GSS_C_NO_NAME;
15551 + gss_buffer_desc defaultPassword = GSS_C_EMPTY_BUFFER;
15552 + int isDefaultIdentity = FALSE;
15554 + major = readStaticIdentityFile(minor, &defaultIdentity, &defaultPassword);
15555 + if (GSS_ERROR(major))
15558 + major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME,
15559 + gssEapPrimaryMechForCred(cred), &defaultIdentityName);
15560 + if (GSS_ERROR(major))
15563 + if (defaultIdentityName == GSS_C_NO_NAME) {
15564 + if (cred->name == GSS_C_NO_NAME) {
15565 + major = GSS_S_CRED_UNAVAIL;
15566 + *minor = GSSEAP_NO_DEFAULT_IDENTITY;
15570 + if (cred->name == GSS_C_NO_NAME) {
15571 + cred->name = defaultIdentityName;
15572 + defaultIdentityName = GSS_C_NO_NAME;
15573 + isDefaultIdentity = TRUE;
15575 + major = gssEapCompareName(minor, cred->name,
15576 + defaultIdentityName, &isDefaultIdentity);
15577 + if (GSS_ERROR(major))
15582 + if (isDefaultIdentity &&
15583 + (cred->flags & CRED_FLAG_PASSWORD) == 0) {
15584 + major = gssEapSetCredPassword(minor, cred, &defaultPassword);
15585 + if (GSS_ERROR(major))
15590 + gssEapReleaseName(&tmpMinor, &defaultIdentityName);
15591 + zeroAndReleasePassword(&defaultPassword);
15592 + gss_release_buffer(&tmpMinor, &defaultIdentity);
15598 +gssEapResolveInitiatorCred(OM_uint32 *minor,
15599 + const gss_cred_id_t cred,
15600 + const gss_name_t targetName
15601 +#ifndef HAVE_MOONSHOT_GET_IDENTITY
15605 + gss_cred_id_t *pResolvedCred)
15607 + OM_uint32 major, tmpMinor;
15608 + gss_cred_id_t resolvedCred = GSS_C_NO_CREDENTIAL;
15610 + if (cred == GSS_C_NO_CREDENTIAL) {
15611 + major = gssEapAcquireCred(minor,
15613 + GSS_C_INDEFINITE,
15614 + GSS_C_NO_OID_SET,
15619 + if (GSS_ERROR(major))
15622 + if ((cred->flags & CRED_FLAG_INITIATE) == 0) {
15623 + major = GSS_S_NO_CRED;
15624 + *minor = GSSEAP_CRED_USAGE_MISMATCH;
15628 + major = gssEapDuplicateCred(minor, cred, &resolvedCred);
15629 + if (GSS_ERROR(major))
15633 + if ((resolvedCred->flags & CRED_FLAG_RESOLVED) == 0) {
15634 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
15635 + major = libMoonshotResolveInitiatorCred(minor, resolvedCred, targetName);
15636 + if (major == GSS_S_CRED_UNAVAIL)
15638 + major = staticIdentityFileResolveInitiatorCred(minor, resolvedCred);
15639 + if (GSS_ERROR(major) && major != GSS_S_CRED_UNAVAIL)
15642 + /* If we have a caller-supplied password, the credential is resolved. */
15643 + if ((resolvedCred->flags & CRED_FLAG_PASSWORD) == 0) {
15644 + major = GSS_S_CRED_UNAVAIL;
15645 + *minor = GSSEAP_NO_DEFAULT_CRED;
15649 + resolvedCred->flags |= CRED_FLAG_RESOLVED;
15652 + *pResolvedCred = resolvedCred;
15653 + resolvedCred = GSS_C_NO_CREDENTIAL;
15655 + major = GSS_S_COMPLETE;
15659 + gssEapReleaseCred(&tmpMinor, &resolvedCred);
15663 diff --git a/mech_eap/util_crypt.c b/mech_eap/util_crypt.c
15664 new file mode 100644
15665 index 0000000..b6e203e
15667 +++ b/mech_eap/util_crypt.c
15670 + * Copyright (c) 2011, JANET(UK)
15671 + * All rights reserved.
15673 + * Redistribution and use in source and binary forms, with or without
15674 + * modification, are permitted provided that the following conditions
15677 + * 1. Redistributions of source code must retain the above copyright
15678 + * notice, this list of conditions and the following disclaimer.
15680 + * 2. Redistributions in binary form must reproduce the above copyright
15681 + * notice, this list of conditions and the following disclaimer in the
15682 + * documentation and/or other materials provided with the distribution.
15684 + * 3. Neither the name of JANET(UK) nor the names of its contributors
15685 + * may be used to endorse or promote products derived from this software
15686 + * without specific prior written permission.
15688 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15689 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15690 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15691 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
15692 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15693 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
15694 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15695 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
15696 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
15697 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
15701 + * Copyright 2001, 2008 by the Massachusetts Institute of Technology.
15702 + * Copyright 1993 by OpenVision Technologies, Inc.
15704 + * Permission to use, copy, modify, distribute, and sell this software
15705 + * and its documentation for any purpose is hereby granted without fee,
15706 + * provided that the above copyright notice appears in all copies and
15707 + * that both that copyright notice and this permission notice appear in
15708 + * supporting documentation, and that the name of OpenVision not be used
15709 + * in advertising or publicity pertaining to distribution of the software
15710 + * without specific, written prior permission. OpenVision makes no
15711 + * representations about the suitability of this software for any
15712 + * purpose. It is provided "as is" without express or implied warranty.
15714 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15715 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
15716 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
15717 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
15718 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15719 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15720 + * PERFORMANCE OF THIS SOFTWARE.
15723 + * Copyright (C) 1998 by the FundsXpress, INC.
15725 + * All rights reserved.
15727 + * Export of this software from the United States of America may require
15728 + * a specific license from the United States Government. It is the
15729 + * responsibility of any person or organization contemplating export to
15730 + * obtain such a license before exporting.
15732 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
15733 + * distribute this software and its documentation for any purpose and
15734 + * without fee is hereby granted, provided that the above copyright
15735 + * notice appear in all copies and that both that copyright notice and
15736 + * this permission notice appear in supporting documentation, and that
15737 + * the name of FundsXpress. not be used in advertising or publicity pertaining
15738 + * to distribution of the software without specific, written prior
15739 + * permission. FundsXpress makes no representations about the suitability of
15740 + * this software for any purpose. It is provided "as is" without express
15741 + * or implied warranty.
15743 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15744 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15745 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15749 + * Message protection services: cryptography helpers.
15752 +#include "gssapiP_eap.h"
15755 + * DCE_STYLE indicates actual RRC is EC + RRC
15756 + * EC is extra rotate count for DCE_STYLE, pad length otherwise
15757 + * RRC is rotate count.
15759 +static krb5_error_code
15760 +mapIov(krb5_context context, int dce_style, size_t ec, size_t rrc,
15761 +#ifdef HAVE_HEIMDAL_VERSION
15762 + krb5_crypto crypto,
15764 + krb5_keyblock *crypto,
15766 + gss_iov_buffer_desc *iov,
15767 + int iov_count, krb5_crypto_iov **pkiov,
15768 + size_t *pkiov_count)
15770 + gss_iov_buffer_t header;
15771 + gss_iov_buffer_t trailer;
15773 + size_t kiov_count;
15774 + krb5_crypto_iov *kiov;
15775 + size_t k5_headerlen = 0, k5_trailerlen = 0;
15776 + size_t gss_headerlen, gss_trailerlen;
15777 + krb5_error_code code;
15780 + *pkiov_count = 0;
15782 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
15783 + GSSEAP_ASSERT(header != NULL);
15785 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
15786 + GSSEAP_ASSERT(trailer == NULL || rrc == 0);
15788 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen);
15792 + code = krbCryptoLength(context, crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen);
15796 + /* Check header and trailer sizes */
15797 + gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */
15798 + gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */
15800 + /* If we're caller without a trailer, we must rotate by trailer length */
15801 + if (trailer == NULL) {
15802 + size_t actual_rrc = rrc;
15805 + actual_rrc += ec; /* compensate for Windows bug */
15807 + if (actual_rrc != gss_trailerlen)
15808 + return KRB5_BAD_MSIZE;
15810 + gss_headerlen += gss_trailerlen;
15811 + gss_trailerlen = 0;
15813 + if (trailer->buffer.length != gss_trailerlen)
15814 + return KRB5_BAD_MSIZE;
15817 + if (header->buffer.length != gss_headerlen)
15818 + return KRB5_BAD_MSIZE;
15820 + kiov_count = 3 + iov_count;
15821 + kiov = (krb5_crypto_iov *)GSSEAP_MALLOC(kiov_count * sizeof(krb5_crypto_iov));
15822 + if (kiov == NULL)
15826 + * The krb5 header is located at the end of the GSS header.
15828 + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER;
15829 + kiov[i].data.length = k5_headerlen;
15830 + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen;
15833 + for (j = 0; j < iov_count; j++) {
15834 + kiov[i].flags = gssEapMapCryptoFlag(iov[j].type);
15835 + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY)
15838 + kiov[i].data.length = iov[j].buffer.length;
15839 + kiov[i].data.data = (char *)iov[j].buffer.value;
15844 + * The EC and encrypted GSS header are placed in the trailer, which may
15845 + * be rotated directly after the plaintext header if no trailer buffer
15848 + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA;
15849 + kiov[i].data.length = ec + 16; /* E(Header) */
15850 + if (trailer == NULL)
15851 + kiov[i].data.data = (char *)header->buffer.value + 16;
15853 + kiov[i].data.data = (char *)trailer->buffer.value;
15857 + * The krb5 trailer is placed after the encrypted copy of the
15858 + * krb5 header (which may be in the GSS header or trailer).
15860 + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
15861 + kiov[i].data.length = k5_trailerlen;
15862 + kiov[i].data.data = (char *)kiov[i - 1].data.data + ec + 16; /* E(Header) */
15866 + *pkiov_count = i;
15872 +gssEapEncrypt(krb5_context context,
15876 +#ifdef HAVE_HEIMDAL_VERSION
15877 + krb5_crypto crypto,
15879 + krb5_keyblock *crypto,
15882 + gss_iov_buffer_desc *iov,
15885 + krb5_error_code code;
15886 + size_t kiov_count;
15887 + krb5_crypto_iov *kiov = NULL;
15889 + code = mapIov(context, dce_style, ec, rrc, crypto,
15890 + iov, iov_count, &kiov, &kiov_count);
15894 +#ifdef HAVE_HEIMDAL_VERSION
15895 + code = krb5_encrypt_iov_ivec(context, crypto, usage, kiov, kiov_count, NULL);
15897 + code = krb5_c_encrypt_iov(context, crypto, usage, NULL, kiov, kiov_count);
15903 + if (kiov != NULL)
15904 + GSSEAP_FREE(kiov);
15910 +gssEapDecrypt(krb5_context context,
15914 +#ifdef HAVE_HEIMDAL_VERSION
15915 + krb5_crypto crypto,
15917 + krb5_keyblock *crypto,
15920 + gss_iov_buffer_desc *iov,
15923 + krb5_error_code code;
15924 + size_t kiov_count;
15925 + krb5_crypto_iov *kiov;
15927 + code = mapIov(context, dce_style, ec, rrc, crypto,
15928 + iov, iov_count, &kiov, &kiov_count);
15932 +#ifdef HAVE_HEIMDAL_VERSION
15933 + code = krb5_decrypt_iov_ivec(context, crypto, usage, kiov, kiov_count, NULL);
15935 + code = krb5_c_decrypt_iov(context, crypto, usage, NULL, kiov, kiov_count);
15939 + if (kiov != NULL)
15940 + GSSEAP_FREE(kiov);
15946 +gssEapMapCryptoFlag(OM_uint32 type)
15950 + switch (GSS_IOV_BUFFER_TYPE(type)) {
15951 + case GSS_IOV_BUFFER_TYPE_DATA:
15952 + case GSS_IOV_BUFFER_TYPE_PADDING:
15953 + ktype = KRB5_CRYPTO_TYPE_DATA;
15955 + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
15956 + ktype = KRB5_CRYPTO_TYPE_SIGN_ONLY;
15959 + ktype = KRB5_CRYPTO_TYPE_EMPTY;
15967 +gssEapLocateIov(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)
15970 + gss_iov_buffer_t p = GSS_C_NO_IOV_BUFFER;
15972 + if (iov == GSS_C_NO_IOV_BUFFER)
15973 + return GSS_C_NO_IOV_BUFFER;
15975 + for (i = iov_count - 1; i >= 0; i--) {
15976 + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == type) {
15977 + if (p == GSS_C_NO_IOV_BUFFER)
15980 + return GSS_C_NO_IOV_BUFFER;
15988 +gssEapIovMessageLength(gss_iov_buffer_desc *iov,
15990 + size_t *data_length_p,
15991 + size_t *assoc_data_length_p)
15994 + size_t data_length = 0, assoc_data_length = 0;
15996 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
15998 + *data_length_p = *assoc_data_length_p = 0;
16000 + for (i = 0; i < iov_count; i++) {
16001 + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[i].type);
16003 + if (type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
16004 + assoc_data_length += iov[i].buffer.length;
16006 + if (type == GSS_IOV_BUFFER_TYPE_DATA ||
16007 + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
16008 + data_length += iov[i].buffer.length;
16011 + *data_length_p = data_length;
16012 + *assoc_data_length_p = assoc_data_length;
16016 +gssEapReleaseIov(gss_iov_buffer_desc *iov, int iov_count)
16019 + OM_uint32 min_stat;
16021 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16023 + for (i = 0; i < iov_count; i++) {
16024 + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) {
16025 + gss_release_buffer(&min_stat, &iov[i].buffer);
16026 + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED);
16032 +gssEapIsIntegrityOnly(gss_iov_buffer_desc *iov, int iov_count)
16035 + krb5_boolean has_conf_data = FALSE;
16037 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16039 + for (i = 0; i < iov_count; i++) {
16040 + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) {
16041 + has_conf_data = TRUE;
16046 + return (has_conf_data == FALSE);
16050 +gssEapAllocIov(gss_iov_buffer_t iov, size_t size)
16052 + GSSEAP_ASSERT(iov != GSS_C_NO_IOV_BUFFER);
16053 + GSSEAP_ASSERT(iov->type & GSS_IOV_BUFFER_FLAG_ALLOCATE);
16055 + iov->buffer.length = size;
16056 + iov->buffer.value = GSSEAP_MALLOC(size);
16057 + if (iov->buffer.value == NULL) {
16058 + iov->buffer.length = 0;
16062 + iov->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED;
16066 diff --git a/mech_eap/util_json.cpp b/mech_eap/util_json.cpp
16067 new file mode 100644
16068 index 0000000..97eb1ed
16070 +++ b/mech_eap/util_json.cpp
16073 + * Copyright (c) 2011, JANET(UK)
16074 + * All rights reserved.
16076 + * Redistribution and use in source and binary forms, with or without
16077 + * modification, are permitted provided that the following conditions
16080 + * 1. Redistributions of source code must retain the above copyright
16081 + * notice, this list of conditions and the following disclaimer.
16083 + * 2. Redistributions in binary form must reproduce the above copyright
16084 + * notice, this list of conditions and the following disclaimer in the
16085 + * documentation and/or other materials provided with the distribution.
16087 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16088 + * may be used to endorse or promote products derived from this software
16089 + * without specific prior written permission.
16091 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16092 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16093 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16094 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16095 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16096 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16097 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16098 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16099 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16100 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16105 + * JSONObject utilities.
16108 +#include "gssapiP_eap.h"
16110 +#include <typeinfo>
16112 +#include <sstream>
16113 +#include <exception>
16116 +#define JSON_INIT(obj) do { \
16117 + if ((obj) == NULL) \
16118 + throw std::bad_alloc(); \
16122 +#define JSON_CHECK_CONTAINER() do { \
16123 + if (!json_is_object(m_obj) && !json_is_array(m_obj)) { \
16124 + std::string s("JSONObject is not a container"); \
16125 + throw JSONException(m_obj); \
16129 +#define JSON_CHECK_OBJECT() do { \
16130 + if (!json_is_object(m_obj)) { \
16131 + std::string s("JSONObject is not a dictionary"); \
16132 + throw JSONException(m_obj, JSON_OBJECT); \
16136 +#define JSON_CHECK_ARRAY() do { \
16137 + if (!json_is_array(m_obj)) { \
16138 + throw JSONException(m_obj, JSON_ARRAY); \
16142 +#define JSON_CHECK(s) do { \
16144 + throw JSONException(); \
16148 +JSONObject::load(const char *input, size_t flags, json_error_t *error)
16152 + obj = json_loads(input, flags, error);
16154 + return JSONObject(obj, false);
16158 +JSONObject::load(FILE *fp, size_t flags, json_error_t *error)
16162 + obj = json_loadf(fp, flags, error);
16164 + return JSONObject(obj, false);
16168 +JSONObject::dump(size_t flags) const
16170 + char *s = json_dumps(m_obj, flags);
16173 + throw std::bad_alloc();
16179 +JSONObject::dump(FILE *fp, size_t flags) const
16181 + int r = json_dumpf(m_obj, fp, flags);
16184 + throw std::bad_alloc();
16188 +JSONObject::size(void) const
16190 + if (json_is_object(m_obj))
16191 + return json_object_size(m_obj);
16192 + else if (json_is_array(m_obj))
16193 + return json_array_size(m_obj);
16198 +JSONObject::JSONObject(json_t *obj, bool retain)
16201 + json_incref(obj);
16205 +JSONObject::JSONObject(const char *value)
16207 + json_t *obj = json_string(value);
16212 +JSONObject::JSONObject(json_int_t value)
16214 + json_t *obj = json_integer(value);
16219 +JSONObject::JSONObject(double value)
16221 + json_t *obj = json_real(value);
16226 +JSONObject::JSONObject(bool value)
16228 + json_t *obj = value ? json_true() : json_false();
16233 +JSONObject::JSONObject(void)
16235 + json_t *obj = json_object();
16241 +JSONObject::object(void)
16243 + return JSONObject();
16247 +JSONObject::null(void)
16249 + return JSONObject(json_null(), false);
16253 +JSONObject::array(void)
16255 + return JSONObject(json_array(), false);
16259 +JSONObject::set(const char *key, JSONObject &value)
16261 + JSON_CHECK_OBJECT();
16262 + JSON_CHECK(json_object_set_new(m_obj, key, value.get()));
16266 +JSONObject::set(const char *key, const char *value)
16268 + JSONObject jobj(value);
16273 +JSONObject::set(const char *key, json_int_t value)
16275 + JSONObject jobj(value);
16280 +JSONObject::del(const char *key)
16282 + json_object_del(m_obj, key);
16286 +JSONObject::get(const char *key) const
16290 + obj = json_object_get(m_obj, key);
16292 + return JSONObject::null();
16294 + return JSONObject(obj, true);
16298 +JSONObject::get(size_t index) const
16302 + obj = json_array_get(m_obj, index);
16304 + return JSONObject::null();
16306 + return JSONObject(obj, true);
16310 +JSONObject::update(JSONObject &value)
16312 + JSON_CHECK_OBJECT();
16313 + json_t *other = value.get();
16314 + JSON_CHECK(json_object_update(m_obj, other));
16315 + json_decref(other);
16319 +JSONObject::operator[](size_t index) const
16321 + return get(index);
16325 +JSONObject::operator[](const char *key) const
16331 +JSONObject::append(JSONObject &value)
16333 + JSON_CHECK_ARRAY();
16334 + JSON_CHECK(json_array_append_new(m_obj, value.get()));
16338 +JSONObject::insert(size_t index, JSONObject &value)
16340 + JSON_CHECK_ARRAY();
16341 + JSON_CHECK(json_array_insert_new(m_obj, index, value.get()));
16345 +JSONObject::remove(size_t index)
16347 + JSON_CHECK_ARRAY();
16348 + JSON_CHECK(json_array_remove(m_obj, index));
16352 +JSONObject::clear(void)
16354 + JSON_CHECK_CONTAINER();
16356 + if (json_is_object(m_obj)) {
16357 + JSON_CHECK(json_object_clear(m_obj));
16358 + } else if (json_is_array(m_obj)) {
16359 + JSON_CHECK(json_array_clear(m_obj));
16364 +JSONObject::extend(JSONObject &value)
16366 + JSON_CHECK_ARRAY();
16367 + json_t *other = value.get();
16368 + JSON_CHECK(json_array_extend(m_obj, other));
16369 + json_decref(other);
16373 +JSONObject::string(void) const
16375 + return json_string_value(m_obj);
16379 +JSONObject::integer(void) const
16381 + return json_integer_value(m_obj);
16385 +JSONObject::real(void) const
16387 + return json_real_value(m_obj);
16391 +JSONObject::number(void) const
16393 + return json_number_value(m_obj);
16396 +#ifdef HAVE_SHIBRESOLVER
16398 +JSONObject::ddf(DDF &ddf)
16400 + if (ddf.isstruct()) {
16401 + DDF elem = ddf.first();
16402 + JSONObject jobj = JSONObject::object();
16404 + while (!elem.isnull()) {
16405 + JSONObject jtmp = JSONObject::ddf(elem);
16406 + jobj.set(elem.name(), jtmp);
16407 + elem = ddf.next();
16411 + } else if (ddf.islist()) {
16412 + DDF elem = ddf.first();
16413 + JSONObject jobj = JSONObject::array();
16415 + while (!elem.isnull()) {
16416 + JSONObject jtmp = JSONObject::ddf(elem);
16417 + jobj.append(jtmp);
16418 + elem = ddf.next();
16422 + } else if (ddf.isstring()) {
16423 + return JSONObject(ddf.string());
16424 + } else if (ddf.isint()) {
16425 + return JSONObject((json_int_t)ddf.integer());
16426 + } else if (ddf.isfloat()) {
16427 + return JSONObject(ddf.floating());
16428 + } else if (ddf.isempty() || ddf.ispointer()) {
16429 + return JSONObject::object();
16430 + } else if (ddf.isnull()) {
16431 + return JSONObject::null();
16434 + std::string s("Unbridgeable DDF object");
16435 + throw JSONException();
16439 +JSONObject::ddf(void) const
16443 + switch (type()) {
16444 + case JSON_OBJECT: {
16445 + JSONIterator iter = iterator();
16448 + const char *key = iter.key();
16449 + DDF value = iter.value().ddf();
16450 + ddf.addmember(key).swap(value);
16451 + } while (iter.next());
16454 + case JSON_ARRAY: {
16455 + size_t i, nelems = size();
16457 + for (i = 0; i < nelems; i++) {
16458 + DDF value = get(i).ddf();
16463 + case JSON_STRING:
16464 + ddf.string(string());
16466 + case JSON_INTEGER:
16467 + ddf.integer(integer());
16470 + ddf.floating(real());
16484 +#endif /* HAVE_SHIBRESOLVER */
16486 +bool JSONObject::isObject(void) const
16488 + return json_is_object(m_obj);
16491 +bool JSONObject::isArray(void) const
16493 + return json_is_array(m_obj);
16496 +bool JSONObject::isString(void) const
16498 + return json_is_string(m_obj);
16501 +bool JSONObject::isInteger(void) const
16503 + return json_is_integer(m_obj);
16506 +bool JSONObject::isNumber(void) const
16508 + return json_is_number(m_obj);
16511 +bool JSONObject::isBoolean(void) const
16513 + return json_is_boolean(m_obj);
16516 +bool JSONObject::isNull(void) const
16518 + return json_is_null(m_obj);
16521 +JSONIterator::JSONIterator(const JSONObject &obj)
16523 + m_obj = obj.get();
16524 + m_iter = json_object_iter(m_obj);
16527 +JSONIterator::~JSONIterator(void)
16529 + json_decref(m_obj);
16533 +JSONIterator::key(void) const
16535 + return json_object_iter_key(m_iter);
16539 +JSONIterator::value(void) const
16541 + return JSONObject(json_object_iter_value(m_iter));
16545 +JSONIterator::next(void)
16547 + m_iter = json_object_iter_next(m_obj, m_iter);
16548 + return m_iter != NULL;
16551 +JSONException::JSONException(json_t *obj, json_type type)
16556 + m_obj = json_incref(obj);
16560 + s = json_dumps(m_obj, 0);
16563 + case JSON_OBJECT: t = "OBJECT"; break;
16564 + case JSON_ARRAY: t = "ARRAY"; break;
16565 + case JSON_STRING: t = "STRING"; break;
16566 + case JSON_INTEGER: t = "INTEGER"; break;
16567 + case JSON_REAL: t = "REAL"; break;
16568 + case JSON_TRUE: t = "TRUE"; break;
16569 + case JSON_FALSE: t = "FALSE"; break;
16570 + case JSON_NULL: t = "NULL"; break;
16571 + default: t = "UNKNOWN"; break;
16574 + if (obj != NULL) {
16575 + m_reason = "Invalid JSON object: " + std::string(s);
16576 + if (type != JSON_NULL)
16577 + m_reason += " (excepted type " + std::string(t) + ")";
16579 + m_reason = "Internal JSON error";
16585 diff --git a/mech_eap/util_json.h b/mech_eap/util_json.h
16586 new file mode 100644
16587 index 0000000..4ffecc8
16589 +++ b/mech_eap/util_json.h
16592 + * Copyright (c) 2011, JANET(UK)
16593 + * All rights reserved.
16595 + * Redistribution and use in source and binary forms, with or without
16596 + * modification, are permitted provided that the following conditions
16599 + * 1. Redistributions of source code must retain the above copyright
16600 + * notice, this list of conditions and the following disclaimer.
16602 + * 2. Redistributions in binary form must reproduce the above copyright
16603 + * notice, this list of conditions and the following disclaimer in the
16604 + * documentation and/or other materials provided with the distribution.
16606 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16607 + * may be used to endorse or promote products derived from this software
16608 + * without specific prior written permission.
16610 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16611 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16612 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16613 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16614 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16615 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16616 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16617 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16618 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16619 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16624 + * JSON object wrapper with not-entirely-toll-free DDF bridging.
16627 +#ifndef _UTIL_JSON_H_
16628 +#define _UTIL_JSON_H_ 1
16630 +#ifdef __cplusplus
16634 +#include <jansson.h>
16636 +#ifdef HAVE_SHIBRESOLVER
16637 +#include <shibsp/remoting/ddf.h>
16638 +using namespace shibsp;
16641 +namespace gss_eap_util {
16642 + class JSONObject;
16644 + class JSONException : public std::exception {
16646 + JSONException(json_t *obj = NULL, json_type type = JSON_NULL);
16648 + ~JSONException(void) throw() {
16649 + json_decref(m_obj);
16652 + virtual const char *what(void) const throw() {
16653 + return m_reason.c_str();
16658 + json_type m_type;
16659 + std::string m_reason;
16662 + class JSONIterator {
16664 + JSONIterator(const JSONObject &obj);
16665 + ~JSONIterator(void);
16666 + const char *key(void) const;
16667 + JSONObject value(void) const;
16675 + class JSONObject {
16677 + static JSONObject load(const char *input, size_t flags, json_error_t *error);
16678 + static JSONObject load(FILE *, size_t flags, json_error_t *error);
16680 + static JSONObject object(void);
16681 + static JSONObject array(void);
16682 + static JSONObject null(void);
16683 +#ifdef HAVE_SHIBRESOLVER
16684 + static JSONObject ddf(DDF &value);
16687 + char *dump(size_t flags = 0) const;
16688 + void dump(FILE *fp, size_t flags = JSON_INDENT(4)) const;
16690 + json_type type(void) const { return json_typeof(m_obj); }
16691 + size_t size(void) const;
16693 + JSONObject(void);
16694 + JSONObject(const char *value);
16695 + JSONObject(json_int_t value);
16696 + JSONObject(double value);
16697 + JSONObject(bool value);
16699 + void set(const char *key, JSONObject &value);
16700 + void set(const char *key, const char *value);
16701 + void set(const char *key, json_int_t value);
16702 + void del(const char *key);
16703 + void update(JSONObject &value);
16704 + JSONIterator iterator(void) const { return JSONIterator(*this); }
16705 + JSONObject get(const char *key) const;
16706 + JSONObject operator[](const char *key) const;
16708 + JSONObject get(size_t index) const;
16709 + JSONObject operator[](size_t index) const;
16710 + void append(JSONObject &value);
16711 + void insert(size_t index, JSONObject &value);
16712 + void remove(size_t index);
16713 + void clear(void);
16714 + void extend(JSONObject &value);
16716 + const char *string(void) const;
16717 + json_int_t integer(void) const;
16718 + double real(void) const;
16719 + double number(void) const;
16720 +#ifdef HAVE_SHIBRESOLVER
16721 + DDF ddf(void) const;
16724 + bool isObject(void) const;
16725 + bool isArray(void) const;
16726 + bool isString(void) const;
16727 + bool isInteger(void) const;
16728 + bool isNumber(void) const;
16729 + bool isBoolean(void) const;
16730 + bool isNull(void) const;
16732 + ~JSONObject(void)
16734 + if (m_obj != NULL)
16735 + json_decref(m_obj);
16738 + JSONObject(const JSONObject &obj)
16740 + m_obj = json_incref(obj.m_obj);
16743 + JSONObject& operator=(const JSONObject &obj)
16745 + if (this != &obj)
16751 + friend class JSONIterator;
16753 + json_t *get(void) const {
16754 + return json_incref(m_obj);
16757 + void set(json_t *obj) {
16758 + if (m_obj != obj) {
16759 + json_decref(m_obj);
16760 + m_obj = json_incref(m_obj);
16764 + JSONObject(json_t *obj, bool retain = true);
16770 +#endif /* __cplusplus */
16772 +#endif /* _UTIL_JSON_H_ */
16773 diff --git a/mech_eap/util_krb.c b/mech_eap/util_krb.c
16774 new file mode 100644
16775 index 0000000..5eaa31e
16777 +++ b/mech_eap/util_krb.c
16780 + * Copyright (c) 2011, JANET(UK)
16781 + * All rights reserved.
16783 + * Redistribution and use in source and binary forms, with or without
16784 + * modification, are permitted provided that the following conditions
16787 + * 1. Redistributions of source code must retain the above copyright
16788 + * notice, this list of conditions and the following disclaimer.
16790 + * 2. Redistributions in binary form must reproduce the above copyright
16791 + * notice, this list of conditions and the following disclaimer in the
16792 + * documentation and/or other materials provided with the distribution.
16794 + * 3. Neither the name of JANET(UK) nor the names of its contributors
16795 + * may be used to endorse or promote products derived from this software
16796 + * without specific prior written permission.
16798 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16799 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16800 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16801 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16802 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
16803 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16804 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
16805 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16806 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16807 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
16812 + * Kerberos 5 helpers.
16815 +#include "gssapiP_eap.h"
16818 +gssEapDestroyKrbContext(krb5_context context)
16820 + if (context != NULL)
16821 + krb5_free_context(context);
16824 +static krb5_error_code
16825 +initKrbContext(krb5_context *pKrbContext)
16827 + krb5_context krbContext;
16828 + krb5_error_code code;
16829 + char *defaultRealm = NULL;
16831 + *pKrbContext = NULL;
16833 + code = krb5_init_context(&krbContext);
16837 + krb5_appdefault_string(krbContext, "eap_gss",
16838 + NULL, "default_realm", "", &defaultRealm);
16840 + if (defaultRealm != NULL && defaultRealm[0] != '\0') {
16841 + code = krb5_set_default_realm(krbContext, defaultRealm);
16846 + *pKrbContext = krbContext;
16849 + krb5_free_default_realm(krbContext, defaultRealm);
16851 + if (code != 0 && krbContext != NULL)
16852 + krb5_free_context(krbContext);
16858 +gssEapKerberosInit(OM_uint32 *minor, krb5_context *context)
16860 + struct gss_eap_thread_local_data *tld;
16865 + tld = gssEapGetThreadLocalData();
16866 + if (tld != NULL) {
16867 + if (tld->krbContext == NULL) {
16868 + *minor = initKrbContext(&tld->krbContext);
16870 + tld->krbContext = NULL;
16872 + *context = tld->krbContext;
16874 + *minor = GSSEAP_GET_LAST_ERROR();
16877 + GSSEAP_ASSERT(*context != NULL || *minor != 0);
16879 + return (*minor == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
16883 + * Derive a key K for RFC 4121 use by using the following
16884 + * derivation function (based on RFC 4402);
16886 + * KMSK = random-to-key(MSK)
16887 + * Tn = pseudo-random(KMSK, n || "rfc4121-gss-eap")
16888 + * L = output key size
16889 + * K = truncate(L, T1 || T2 || .. || Tn)
16891 + * The output must be freed by krb5_free_keyblock_contents(),
16892 + * not GSSEAP_FREE().
16895 +gssEapDeriveRfc3961Key(OM_uint32 *minor,
16896 + const unsigned char *inputKey,
16897 + size_t inputKeyLength,
16898 + krb5_enctype encryptionType,
16899 + krb5_keyblock *pKey)
16901 + krb5_context krbContext;
16902 +#ifndef HAVE_HEIMDAL_VERSION
16905 + krb5_data ns, t, derivedKeyData;
16906 + krb5_keyblock kd;
16907 + krb5_error_code code;
16908 + size_t randomLength, keyLength, prfLength;
16909 + unsigned char constant[4 + sizeof("rfc4121-gss-eap") - 1], *p;
16910 + ssize_t i, remain;
16912 + GSSEAP_KRB_INIT(&krbContext);
16913 + GSSEAP_ASSERT(encryptionType != ENCTYPE_NULL);
16915 + KRB_KEY_INIT(pKey);
16916 + KRB_KEY_INIT(&kd);
16917 + KRB_KEY_TYPE(&kd) = encryptionType;
16919 + KRB_DATA_INIT(&ns);
16920 + KRB_DATA_INIT(&t);
16921 + KRB_DATA_INIT(&derivedKeyData);
16923 + code = krb5_c_keylengths(krbContext, encryptionType,
16924 + &randomLength, &keyLength);
16928 + /* Convert EAP MSK into a Kerberos key */
16930 +#ifdef HAVE_HEIMDAL_VERSION
16931 + code = krb5_random_to_key(krbContext, encryptionType, inputKey,
16932 + MIN(inputKeyLength, randomLength), &kd);
16934 + data.length = MIN(inputKeyLength, randomLength);
16935 + data.data = (char *)inputKey;
16937 + KRB_KEY_DATA(&kd) = KRB_MALLOC(keyLength);
16938 + if (KRB_KEY_DATA(&kd) == NULL) {
16942 + KRB_KEY_LENGTH(&kd) = keyLength;
16944 + code = krb5_c_random_to_key(krbContext, encryptionType, &data, &kd);
16945 +#endif /* HAVE_HEIMDAL_VERSION */
16949 + memset(&constant[0], 0, 4);
16950 + memcpy(&constant[4], "rfc4121-gss-eap", sizeof("rfc4121-gss-eap") - 1);
16952 + ns.length = sizeof(constant);
16953 + ns.data = (char *)constant;
16955 + /* Plug derivation constant and key into PRF */
16956 + code = krb5_c_prf_length(krbContext, encryptionType, &prfLength);
16960 +#ifndef HAVE_HEIMDAL_VERSION
16961 + /* Same API, but different allocation rules, unfortunately. */
16962 + t.length = prfLength;
16963 + t.data = GSSEAP_MALLOC(t.length);
16964 + if (t.data == NULL) {
16970 + derivedKeyData.length = randomLength;
16971 + derivedKeyData.data = GSSEAP_MALLOC(derivedKeyData.length);
16972 + if (derivedKeyData.data == NULL) {
16977 + for (i = 0, p = (unsigned char *)derivedKeyData.data, remain = randomLength;
16979 + p += t.length, remain -= t.length, i++)
16981 + store_uint32_be(i, ns.data);
16983 + code = krb5_c_prf(krbContext, &kd, &ns, &t);
16987 + memcpy(p, t.data, MIN(t.length, remain));
16990 + /* Finally, convert PRF output into a new key which we will return */
16991 +#ifdef HAVE_HEIMDAL_VERSION
16992 + krb5_free_keyblock_contents(krbContext, &kd);
16993 + KRB_KEY_INIT(&kd);
16995 + code = krb5_random_to_key(krbContext, encryptionType,
16996 + derivedKeyData.data, derivedKeyData.length, &kd);
16998 + code = krb5_c_random_to_key(krbContext, encryptionType,
16999 + &derivedKeyData, &kd);
17008 + krb5_free_keyblock_contents(krbContext, &kd);
17009 +#ifdef HAVE_HEIMDAL_VERSION
17010 + krb5_free_data_contents(krbContext, &t);
17012 + if (t.data != NULL) {
17013 + memset(t.data, 0, t.length);
17014 + GSSEAP_FREE(t.data);
17017 + if (derivedKeyData.data != NULL) {
17018 + memset(derivedKeyData.data, 0, derivedKeyData.length);
17019 + GSSEAP_FREE(derivedKeyData.data);
17024 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
17027 +#ifdef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17028 +extern krb5_error_code
17029 +krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
17033 +rfc3961ChecksumTypeForKey(OM_uint32 *minor,
17034 + krb5_keyblock *key,
17035 + krb5_cksumtype *cksumtype)
17037 + krb5_context krbContext;
17038 +#ifndef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17040 + krb5_checksum cksum;
17043 + GSSEAP_KRB_INIT(&krbContext);
17045 +#ifdef HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE
17046 + *minor = krb5int_c_mandatory_cksumtype(krbContext, KRB_KEY_TYPE(key),
17049 + return GSS_S_FAILURE;
17051 + KRB_DATA_INIT(&data);
17053 + memset(&cksum, 0, sizeof(cksum));
17056 + * This is a complete hack but it's the only way to work with
17057 + * MIT Kerberos pre-1.9 without using private API, as it does
17058 + * not support passing in zero as the checksum type.
17060 + *minor = krb5_c_make_checksum(krbContext, 0, key, 0, &data, &cksum);
17062 + return GSS_S_FAILURE;
17064 +#ifdef HAVE_HEIMDAL_VERSION
17065 + *cksumtype = cksum.cksumtype;
17067 + *cksumtype = cksum.checksum_type;
17070 + krb5_free_checksum_contents(krbContext, &cksum);
17071 +#endif /* HAVE_KRB5INT_C_MANDATORY_CKSUMTYPE */
17073 + if (!krb5_c_is_keyed_cksum(*cksumtype)) {
17074 + *minor = (OM_uint32)KRB5KRB_AP_ERR_INAPP_CKSUM;
17075 + return GSS_S_FAILURE;
17078 + return GSS_S_COMPLETE;
17082 +krbCryptoLength(krb5_context krbContext,
17083 +#ifdef HAVE_HEIMDAL_VERSION
17084 + krb5_crypto krbCrypto,
17086 + krb5_keyblock *key,
17091 +#ifdef HAVE_HEIMDAL_VERSION
17092 + return krb5_crypto_length(krbContext, krbCrypto, type, length);
17094 + unsigned int len;
17095 + krb5_error_code code;
17097 + code = krb5_c_crypto_length(krbContext, KRB_KEY_TYPE(key), type, &len);
17099 + *length = (size_t)len;
17106 +krbPaddingLength(krb5_context krbContext,
17107 +#ifdef HAVE_HEIMDAL_VERSION
17108 + krb5_crypto krbCrypto,
17110 + krb5_keyblock *key,
17112 + size_t dataLength,
17113 + size_t *padLength)
17115 + krb5_error_code code;
17116 +#ifdef HAVE_HEIMDAL_VERSION
17117 + size_t headerLength, paddingLength;
17119 + code = krbCryptoLength(krbContext, krbCrypto,
17120 + KRB5_CRYPTO_TYPE_HEADER, &headerLength);
17124 + dataLength += headerLength;
17126 + code = krb5_crypto_length(krbContext, krbCrypto,
17127 + KRB5_CRYPTO_TYPE_PADDING, &paddingLength);
17131 + if (paddingLength != 0 && (dataLength % paddingLength) != 0)
17132 + *padLength = paddingLength - (dataLength % paddingLength);
17138 + unsigned int pad;
17140 + code = krb5_c_padding_length(krbContext, KRB_KEY_TYPE(key), dataLength, &pad);
17142 + *padLength = (size_t)pad;
17145 +#endif /* HAVE_HEIMDAL_VERSION */
17149 +krbBlockSize(krb5_context krbContext,
17150 +#ifdef HAVE_HEIMDAL_VERSION
17151 + krb5_crypto krbCrypto,
17153 + krb5_keyblock *key,
17155 + size_t *blockSize)
17157 +#ifdef HAVE_HEIMDAL_VERSION
17158 + return krb5_crypto_getblocksize(krbContext, krbCrypto, blockSize);
17160 + return krb5_c_block_size(krbContext, KRB_KEY_TYPE(key), blockSize);
17165 +krbEnctypeToString(
17166 +#ifdef HAVE_HEIMDAL_VERSION
17167 + krb5_context krbContext,
17169 + krb5_context krbContext GSSEAP_UNUSED,
17171 + krb5_enctype enctype,
17172 + const char *prefix,
17173 + gss_buffer_t string)
17175 + krb5_error_code code;
17176 +#ifdef HAVE_HEIMDAL_VERSION
17177 + char *enctypeBuf = NULL;
17179 + char enctypeBuf[128];
17181 + size_t prefixLength, enctypeLength;
17183 +#ifdef HAVE_HEIMDAL_VERSION
17184 + code = krb5_enctype_to_string(krbContext, enctype, &enctypeBuf);
17186 + code = krb5_enctype_to_name(enctype, 0, enctypeBuf, sizeof(enctypeBuf));
17191 + prefixLength = (prefix != NULL) ? strlen(prefix) : 0;
17192 + enctypeLength = strlen(enctypeBuf);
17194 + string->value = GSSEAP_MALLOC(prefixLength + enctypeLength + 1);
17195 + if (string->value == NULL) {
17196 +#ifdef HAVE_HEIMDAL_VERSION
17197 + krb5_xfree(enctypeBuf);
17202 + if (prefixLength != 0)
17203 + memcpy(string->value, prefix, prefixLength);
17204 + memcpy((char *)string->value + prefixLength, enctypeBuf, enctypeLength);
17206 + string->length = prefixLength + enctypeLength;
17207 + ((char *)string->value)[string->length] = '\0';
17209 +#ifdef HAVE_HEIMDAL_VERSION
17210 + krb5_xfree(enctypeBuf);
17217 +krbMakeAuthDataKdcIssued(krb5_context context,
17218 + const krb5_keyblock *key,
17219 + krb5_const_principal issuer,
17220 +#ifdef HAVE_HEIMDAL_VERSION
17221 + const AuthorizationData *authdata,
17222 + AuthorizationData *adKdcIssued
17224 + krb5_authdata *const *authdata,
17225 + krb5_authdata ***adKdcIssued
17229 +#ifdef HAVE_HEIMDAL_VERSION
17230 + krb5_error_code code;
17231 + AD_KDCIssued kdcIssued;
17232 + AuthorizationDataElement adDatum;
17233 + unsigned char *buf;
17234 + size_t buf_size, len;
17235 + krb5_crypto crypto = NULL;
17237 + memset(&kdcIssued, 0, sizeof(kdcIssued));
17238 + memset(adKdcIssued, 0, sizeof(*adKdcIssued));
17240 + kdcIssued.i_realm = issuer->realm != NULL ? (Realm *)&issuer->realm : NULL;
17241 + kdcIssued.i_sname = (PrincipalName *)&issuer->name;
17242 + kdcIssued.elements = *authdata;
17244 + ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata, &len, code);
17248 + code = krb5_crypto_init(context, key, 0, &crypto);
17252 + code = krb5_create_checksum(context, crypto, KRB5_KU_AD_KDC_ISSUED,
17253 + 0, buf, buf_size, &kdcIssued.ad_checksum);
17257 + free(buf); /* match ASN1_MALLOC_ENCODE */
17260 + ASN1_MALLOC_ENCODE(AD_KDCIssued, buf, buf_size, &kdcIssued, &len, code);
17264 + adDatum.ad_type = KRB5_AUTHDATA_KDC_ISSUED;
17265 + adDatum.ad_data.length = buf_size;
17266 + adDatum.ad_data.data = buf;
17268 + code = add_AuthorizationData(adKdcIssued, &adDatum);
17274 + free(buf); /* match ASN1_MALLOC_ENCODE */
17275 + if (crypto != NULL)
17276 + krb5_crypto_destroy(context, crypto);
17277 + free_Checksum(&kdcIssued.ad_checksum);
17281 + return krb5_make_authdata_kdc_issued(context, key, issuer, authdata,
17283 +#endif /* HAVE_HEIMDAL_VERSION */
17287 +krbMakeCred(krb5_context krbContext,
17288 + krb5_auth_context authContext,
17289 + krb5_creds *creds,
17292 + krb5_error_code code;
17293 +#ifdef HAVE_HEIMDAL_VERSION
17294 + KRB_CRED krbCred;
17295 + KrbCredInfo krbCredInfo;
17296 + EncKrbCredPart encKrbCredPart;
17297 + krb5_keyblock *key;
17298 + krb5_crypto krbCrypto = NULL;
17299 + krb5_data encKrbCredPartData;
17300 + krb5_replay_data rdata;
17303 + krb5_data *d = NULL;
17306 + memset(data, 0, sizeof(*data));
17307 +#ifdef HAVE_HEIMDAL_VERSION
17308 + memset(&krbCred, 0, sizeof(krbCred));
17309 + memset(&krbCredInfo, 0, sizeof(krbCredInfo));
17310 + memset(&encKrbCredPart, 0, sizeof(encKrbCredPart));
17311 + memset(&rdata, 0, sizeof(rdata));
17313 + if (authContext->local_subkey)
17314 + key = authContext->local_subkey;
17315 + else if (authContext->remote_subkey)
17316 + key = authContext->remote_subkey;
17318 + key = authContext->keyblock;
17320 + krbCred.pvno = 5;
17321 + krbCred.msg_type = krb_cred;
17322 + krbCred.tickets.val = (Ticket *)GSSEAP_CALLOC(1, sizeof(Ticket));
17323 + if (krbCred.tickets.val == NULL) {
17327 + krbCred.tickets.len = 1;
17329 + code = decode_Ticket(creds->ticket.data,
17330 + creds->ticket.length,
17331 + krbCred.tickets.val, &len);
17335 + krbCredInfo.key = creds->session;
17336 + krbCredInfo.prealm = &creds->client->realm;
17337 + krbCredInfo.pname = &creds->client->name;
17338 + krbCredInfo.flags = &creds->flags.b;
17339 + krbCredInfo.authtime = &creds->times.authtime;
17340 + krbCredInfo.starttime = &creds->times.starttime;
17341 + krbCredInfo.endtime = &creds->times.endtime;
17342 + krbCredInfo.renew_till = &creds->times.renew_till;
17343 + krbCredInfo.srealm = &creds->server->realm;
17344 + krbCredInfo.sname = &creds->server->name;
17345 + krbCredInfo.caddr = creds->addresses.len ? &creds->addresses : NULL;
17347 + encKrbCredPart.ticket_info.len = 1;
17348 + encKrbCredPart.ticket_info.val = &krbCredInfo;
17349 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
17350 + rdata.seq = authContext->local_seqnumber;
17351 + encKrbCredPart.nonce = (int32_t *)&rdata.seq;
17353 + encKrbCredPart.nonce = NULL;
17355 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
17356 + krb5_us_timeofday(krbContext, &rdata.timestamp, &rdata.usec);
17357 + encKrbCredPart.timestamp = &rdata.timestamp;
17358 + encKrbCredPart.usec = &rdata.usec;
17360 + encKrbCredPart.timestamp = NULL;
17361 + encKrbCredPart.usec = NULL;
17363 + encKrbCredPart.s_address = authContext->local_address;
17364 + encKrbCredPart.r_address = authContext->remote_address;
17366 + ASN1_MALLOC_ENCODE(EncKrbCredPart, encKrbCredPartData.data,
17367 + encKrbCredPartData.length, &encKrbCredPart,
17372 + code = krb5_crypto_init(krbContext, key, 0, &krbCrypto);
17376 + code = krb5_encrypt_EncryptedData(krbContext,
17378 + KRB5_KU_KRB_CRED,
17379 + encKrbCredPartData.data,
17380 + encKrbCredPartData.length,
17382 + &krbCred.enc_part);
17386 + ASN1_MALLOC_ENCODE(KRB_CRED, data->data, data->length,
17387 + &krbCred, &len, code);
17391 + if (authContext->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
17392 + authContext->local_seqnumber++;
17395 + if (krbCrypto != NULL)
17396 + krb5_crypto_destroy(krbContext, krbCrypto);
17397 + free_KRB_CRED(&krbCred);
17398 + krb5_data_free(&encKrbCredPartData);
17402 + code = krb5_mk_1cred(krbContext, authContext, creds, &d, NULL);
17409 +#endif /* HAVE_HEIMDAL_VERSION */
17411 diff --git a/mech_eap/util_lucid.c b/mech_eap/util_lucid.c
17412 new file mode 100644
17413 index 0000000..f9e9941
17415 +++ b/mech_eap/util_lucid.c
17418 + * Copyright (c) 2011, JANET(UK)
17419 + * All rights reserved.
17421 + * Redistribution and use in source and binary forms, with or without
17422 + * modification, are permitted provided that the following conditions
17425 + * 1. Redistributions of source code must retain the above copyright
17426 + * notice, this list of conditions and the following disclaimer.
17428 + * 2. Redistributions in binary form must reproduce the above copyright
17429 + * notice, this list of conditions and the following disclaimer in the
17430 + * documentation and/or other materials provided with the distribution.
17432 + * 3. Neither the name of JANET(UK) nor the names of its contributors
17433 + * may be used to endorse or promote products derived from this software
17434 + * without specific prior written permission.
17436 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17437 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17438 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17439 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17440 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17441 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17442 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17443 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17444 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17445 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17450 + * "Lucid" security context export routine (called by MIT Kerberos mechanism).
17453 +#include "gssapiP_eap.h"
17456 +gssEapExportLucidSecContext(OM_uint32 *minor,
17457 + gss_ctx_id_t ctx,
17458 + const gss_OID desiredObject GSSEAP_UNUSED,
17459 + gss_buffer_set_t *data_set)
17461 + OM_uint32 major = GSS_S_COMPLETE;
17462 + int haveAcceptorSubkey =
17463 + ((rfc4121Flags(ctx, 0) & TOK_FLAG_ACCEPTOR_SUBKEY) != 0);
17464 + gss_buffer_desc rep;
17465 +#ifdef HAVE_HEIMDAL_VERSION
17466 + krb5_error_code code;
17467 + krb5_storage *sp;
17468 + krb5_data data = { 0 };
17470 + sp = krb5_storage_emem();
17471 + if (sp == NULL) {
17476 + code = krb5_store_int32(sp, 1); /* version */
17480 + code = krb5_store_int32(sp, CTX_IS_INITIATOR(ctx));
17484 + code = krb5_store_int32(sp, ctx->expiryTime);
17488 + code = krb5_store_int32(sp, 0);
17492 + code = krb5_store_int32(sp, ctx->sendSeq);
17496 + code = krb5_store_int32(sp, 0);
17500 + code = krb5_store_int32(sp, ctx->recvSeq);
17504 + code = krb5_store_int32(sp, 1); /* is_cfx */
17508 + code = krb5_store_int32(sp, haveAcceptorSubkey);
17512 + code = krb5_store_keyblock(sp, ctx->rfc3961Key);
17516 + if (haveAcceptorSubkey) {
17517 + code = krb5_store_keyblock(sp, ctx->rfc3961Key);
17522 + code = krb5_storage_to_data(sp, &data);
17526 + rep.length = data.length;
17527 + rep.value = data.data;
17529 + major = gss_add_buffer_set_member(minor, &rep, data_set);
17530 + if (GSS_ERROR(major))
17534 + krb5_data_free(&data);
17536 + if (major == GSS_S_COMPLETE) {
17538 + major = (code != 0) ? GSS_S_FAILURE : GSS_S_COMPLETE;
17543 + gss_krb5_lucid_context_v1_t *lctx;
17544 + gss_krb5_lucid_key_t *lkey = NULL;
17546 + lctx = (gss_krb5_lucid_context_v1_t *)GSSEAP_CALLOC(1, sizeof(*lctx));
17547 + if (lctx == NULL) {
17548 + major = GSS_S_FAILURE;
17553 + lctx->version = 1;
17554 + lctx->initiate = CTX_IS_INITIATOR(ctx);
17555 + if (ctx->expiryTime == 0)
17556 + lctx->endtime = KRB_TIME_FOREVER;
17558 + lctx->endtime = ctx->expiryTime;
17559 + lctx->send_seq = ctx->sendSeq;
17560 + lctx->recv_seq = ctx->recvSeq;
17561 + lctx->protocol = 1;
17563 + lctx->cfx_kd.have_acceptor_subkey = haveAcceptorSubkey;
17565 + lkey = haveAcceptorSubkey
17566 + ? &lctx->cfx_kd.acceptor_subkey
17567 + : &lctx->cfx_kd.ctx_key;
17569 + lkey->type = KRB_KEY_TYPE(&ctx->rfc3961Key);
17570 + lkey->data = GSSEAP_MALLOC(KRB_KEY_LENGTH(&ctx->rfc3961Key));
17571 + if (lkey->data == NULL) {
17572 + major = GSS_S_FAILURE;
17576 + lkey->length = KRB_KEY_LENGTH(&ctx->rfc3961Key);
17577 + memcpy(lkey->data, KRB_KEY_DATA(&ctx->rfc3961Key), lkey->length);
17579 + rep.value = &lctx;
17580 + rep.length = sizeof(void *);
17582 + major = gss_add_buffer_set_member(minor, &rep, data_set);
17583 + if (GSS_ERROR(major))
17587 + if (GSS_ERROR(major)) {
17588 + if (lctx != NULL) {
17589 + if (lkey != NULL && lkey->data != NULL) {
17590 + memset(lkey->data, 0, lkey->length);
17591 + GSSEAP_FREE(lkey->data);
17593 + GSSEAP_FREE(lctx);
17598 +#endif /* HAVE_HEIMDAL_VERSION */
17600 diff --git a/mech_eap/util_mech.c b/mech_eap/util_mech.c
17601 new file mode 100644
17602 index 0000000..958e43d
17604 +++ b/mech_eap/util_mech.c
17607 + * Copyright (c) 2011, JANET(UK)
17608 + * All rights reserved.
17610 + * Redistribution and use in source and binary forms, with or without
17611 + * modification, are permitted provided that the following conditions
17614 + * 1. Redistributions of source code must retain the above copyright
17615 + * notice, this list of conditions and the following disclaimer.
17617 + * 2. Redistributions in binary form must reproduce the above copyright
17618 + * notice, this list of conditions and the following disclaimer in the
17619 + * documentation and/or other materials provided with the distribution.
17621 + * 3. Neither the name of JANET(UK) nor the names of its contributors
17622 + * may be used to endorse or promote products derived from this software
17623 + * without specific prior written permission.
17625 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17626 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17627 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17628 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17629 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17630 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
17631 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
17632 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
17633 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17634 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17639 + * General mechanism utility routines.
17642 +#include "gssapiP_eap.h"
17645 + * 1.3.6.1.4.1.5322(padl)
17648 + * eap-aes128-cts-hmac-sha1-96(17)
17649 + * eap-aes256-cts-hmac-sha1-96(18)
17651 + * apiExtensions(3)
17652 + * inquireSecContextByOid(1)
17653 + * inquireCredByOid(2)
17654 + * setSecContextOption(3)
17655 + * setCredOption(4)
17660 + * Note: the enctype-less OID is used as the mechanism OID in non-
17661 + * canonicalized exported names.
17663 +static gss_OID_desc gssEapMechOids[] = {
17664 + /* 1.3.6.1.4.1.5322.22.1 */
17665 + { 9, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01" },
17666 + /* 1.3.6.1.4.1.5322.22.1.17 */
17667 + { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x11" },
17668 + /* 1.3.6.1.4.1.5322.22.1.18 */
17669 + { 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x01\x12" }
17672 +gss_OID GSS_EAP_MECHANISM = &gssEapMechOids[0];
17673 +gss_OID GSS_EAP_AES128_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[1];
17674 +gss_OID GSS_EAP_AES256_CTS_HMAC_SHA1_96_MECHANISM = &gssEapMechOids[2];
17677 +internalizeOid(const gss_OID oid,
17678 + gss_OID *const pInternalizedOid);
17681 + * Returns TRUE is the OID is a concrete mechanism OID, that is, one
17682 + * with a Kerberos enctype as the last element.
17685 +gssEapIsConcreteMechanismOid(const gss_OID oid)
17687 + return oid->length > GSS_EAP_MECHANISM->length &&
17688 + memcmp(oid->elements, GSS_EAP_MECHANISM->elements,
17689 + GSS_EAP_MECHANISM->length) == 0;
17693 +gssEapIsMechanismOid(const gss_OID oid)
17695 + return oid == GSS_C_NO_OID ||
17696 + oidEqual(oid, GSS_EAP_MECHANISM) ||
17697 + gssEapIsConcreteMechanismOid(oid);
17701 + * Validate that all elements are concrete mechanism OIDs.
17704 +gssEapValidateMechs(OM_uint32 *minor,
17705 + const gss_OID_set mechs)
17711 + if (mechs == GSS_C_NO_OID_SET) {
17712 + return GSS_S_COMPLETE;
17715 + for (i = 0; i < mechs->count; i++) {
17716 + gss_OID oid = &mechs->elements[i];
17718 + if (!gssEapIsConcreteMechanismOid(oid)) {
17719 + *minor = GSSEAP_WRONG_MECH;
17720 + return GSS_S_BAD_MECH;
17724 + return GSS_S_COMPLETE;
17728 +gssEapOidToEnctype(OM_uint32 *minor,
17729 + const gss_OID oid,
17730 + krb5_enctype *enctype)
17735 + major = decomposeOid(minor,
17736 + GSS_EAP_MECHANISM->elements,
17737 + GSS_EAP_MECHANISM->length,
17740 + if (major == GSS_S_COMPLETE)
17741 + *enctype = suffix;
17747 +gssEapEnctypeToOid(OM_uint32 *minor,
17748 + krb5_enctype enctype,
17756 + oid = (gss_OID)GSSEAP_MALLOC(sizeof(*oid));
17757 + if (oid == NULL) {
17759 + return GSS_S_FAILURE;
17762 + oid->length = GSS_EAP_MECHANISM->length + 1;
17763 + oid->elements = GSSEAP_MALLOC(oid->length);
17764 + if (oid->elements == NULL) {
17766 + GSSEAP_FREE(oid);
17767 + return GSS_S_FAILURE;
17770 + major = composeOid(minor,
17771 + GSS_EAP_MECHANISM->elements,
17772 + GSS_EAP_MECHANISM->length,
17775 + if (major == GSS_S_COMPLETE) {
17776 + internalizeOid(oid, pOid);
17779 + GSSEAP_FREE(oid->elements);
17780 + GSSEAP_FREE(oid);
17787 +gssEapIndicateMechs(OM_uint32 *minor,
17788 + gss_OID_set *mechs)
17790 + krb5_context krbContext;
17792 + krb5_enctype *etypes;
17795 + GSSEAP_KRB_INIT(&krbContext);
17797 + *minor = krb5_get_permitted_enctypes(krbContext, &etypes);
17798 + if (*minor != 0) {
17799 + return GSS_S_FAILURE;
17802 + major = gss_create_empty_oid_set(minor, mechs);
17803 + if (GSS_ERROR(major)) {
17804 + GSSEAP_FREE(etypes);
17808 + for (i = 0; etypes[i] != ENCTYPE_NULL; i++) {
17810 +#ifndef HAVE_HEIMDAL_VERSION
17811 + OM_uint32 tmpMinor;
17814 + /* XXX currently we aren't equipped to encode these enctypes */
17815 + if (etypes[i] < 0 || etypes[i] > 127)
17818 + major = gssEapEnctypeToOid(minor, etypes[i], &mechOid);
17819 + if (GSS_ERROR(major))
17822 + major = gss_add_oid_set_member(minor, mechOid, mechs);
17823 + if (GSS_ERROR(major))
17826 +#ifndef HAVE_HEIMDAL_VERSION
17827 + gss_release_oid(&tmpMinor, &mechOid);
17831 + GSSEAP_FREE(etypes);
17838 +gssEapDefaultMech(OM_uint32 *minor,
17841 + gss_OID_set mechs;
17842 + OM_uint32 major, tmpMinor;
17844 + major = gssEapIndicateMechs(minor, &mechs);
17845 + if (GSS_ERROR(major)) {
17849 + if (mechs->count == 0) {
17850 + gss_release_oid_set(&tmpMinor, &mechs);
17851 + return GSS_S_BAD_MECH;
17854 + if (!internalizeOid(&mechs->elements[0], oid)) {
17855 + /* don't double-free if we didn't internalize it */
17856 + mechs->elements[0].length = 0;
17857 + mechs->elements[0].elements = NULL;
17860 + gss_release_oid_set(&tmpMinor, &mechs);
17863 + return GSS_S_COMPLETE;
17867 +internalizeOid(const gss_OID oid,
17868 + gss_OID *const pInternalizedOid)
17872 + *pInternalizedOid = GSS_C_NO_OID;
17875 + i < sizeof(gssEapMechOids) / sizeof(gssEapMechOids[0]);
17877 + if (oidEqual(oid, &gssEapMechOids[i])) {
17878 + *pInternalizedOid = (const gss_OID)&gssEapMechOids[i];
17883 + if (*pInternalizedOid == GSS_C_NO_OID) {
17884 + if (oidEqual(oid, GSS_EAP_NT_EAP_NAME))
17885 + *pInternalizedOid = (const gss_OID)GSS_EAP_NT_EAP_NAME;
17888 + if (*pInternalizedOid == GSS_C_NO_OID) {
17889 + *pInternalizedOid = oid;
17897 +gssEapReleaseOid(OM_uint32 *minor, gss_OID *oid)
17899 + gss_OID internalizedOid = GSS_C_NO_OID;
17903 + if (internalizeOid(*oid, &internalizedOid)) {
17904 + /* OID was internalized, so we can mark it as "freed" */
17905 + *oid = GSS_C_NO_OID;
17906 + return GSS_S_COMPLETE;
17909 + /* we don't know about this OID */
17910 + return GSS_S_CONTINUE_NEEDED;
17914 +gssEapCanonicalizeOid(OM_uint32 *minor,
17915 + const gss_OID oid,
17920 + int mapToNull = 0;
17922 + major = GSS_S_COMPLETE;
17924 + *pOid = GSS_C_NULL_OID;
17926 + if (oid == GSS_C_NULL_OID) {
17927 + if ((flags & OID_FLAG_NULL_VALID) == 0) {
17928 + *minor = GSSEAP_WRONG_MECH;
17929 + return GSS_S_BAD_MECH;
17930 + } else if (flags & OID_FLAG_MAP_NULL_TO_DEFAULT_MECH) {
17931 + return gssEapDefaultMech(minor, pOid);
17935 + } else if (oidEqual(oid, GSS_EAP_MECHANISM)) {
17936 + if ((flags & OID_FLAG_FAMILY_MECH_VALID) == 0) {
17937 + *minor = GSSEAP_WRONG_MECH;
17938 + return GSS_S_BAD_MECH;
17939 + } else if (flags & OID_FLAG_MAP_FAMILY_MECH_TO_NULL) {
17942 + } else if (!gssEapIsConcreteMechanismOid(oid)) {
17943 + *minor = GSSEAP_WRONG_MECH;
17944 + return GSS_S_BAD_MECH;
17947 + if (!mapToNull) {
17948 + if (!internalizeOid(oid, pOid))
17949 + major = duplicateOid(minor, oid, pOid);
17955 +static gss_buffer_desc gssEapSaslMechs[] = {
17956 + { sizeof("EAP") - 1, "EAP", }, /* not used */
17957 + { sizeof("EAP-AES128") - 1, "EAP-AES128" },
17958 + { sizeof("EAP-AES256") - 1, "EAP-AES256" },
17962 +gssEapOidToSaslName(const gss_OID oid)
17966 + for (i = 1; i < sizeof(gssEapMechOids)/sizeof(gssEapMechOids[0]); i++) {
17967 + if (oidEqual(&gssEapMechOids[i], oid))
17968 + return &gssEapSaslMechs[i];
17971 + return GSS_C_NO_BUFFER;
17975 +gssEapSaslNameToOid(const gss_buffer_t name)
17979 + for (i = 1; i < sizeof(gssEapSaslMechs)/sizeof(gssEapSaslMechs[0]); i++) {
17980 + if (bufferEqual(&gssEapSaslMechs[i], name))
17981 + return &gssEapMechOids[i];
17984 + return GSS_C_NO_OID;
17986 diff --git a/mech_eap/util_moonshot.c b/mech_eap/util_moonshot.c
17987 new file mode 100644
17988 index 0000000..dc0c35e
17990 +++ b/mech_eap/util_moonshot.c
17993 + * Copyright (c) 2011, JANET(UK)
17994 + * All rights reserved.
17996 + * Redistribution and use in source and binary forms, with or without
17997 + * modification, are permitted provided that the following conditions
18000 + * 1. Redistributions of source code must retain the above copyright
18001 + * notice, this list of conditions and the following disclaimer.
18003 + * 2. Redistributions in binary form must reproduce the above copyright
18004 + * notice, this list of conditions and the following disclaimer in the
18005 + * documentation and/or other materials provided with the distribution.
18007 + * 3. Neither the name of JANET(UK) nor the names of its contributors
18008 + * may be used to endorse or promote products derived from this software
18009 + * without specific prior written permission.
18011 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18012 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18013 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18014 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18015 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18016 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18017 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18018 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18019 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18020 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18024 +#include "gssapiP_eap.h"
18026 +#ifdef HAVE_MOONSHOT_GET_IDENTITY
18027 +#include <libmoonshot.h>
18030 +libMoonshotMapError(OM_uint32 *minor,
18031 + MoonshotError **pError)
18033 + MoonshotError *error = *pError;
18035 + GSSEAP_ASSERT(error != NULL);
18037 + switch (error->code) {
18038 + case MOONSHOT_ERROR_UNABLE_TO_START_SERVICE:
18039 + *minor = GSSEAP_UNABLE_TO_START_IDENTITY_SERVICE;
18041 + case MOONSHOT_ERROR_NO_IDENTITY_SELECTED:
18042 + *minor = GSSEAP_NO_IDENTITY_SELECTED;
18044 + case MOONSHOT_ERROR_INSTALLATION_ERROR:
18045 + *minor = GSSEAP_IDENTITY_SERVICE_INSTALL_ERROR;
18047 + case MOONSHOT_ERROR_OS_ERROR:
18048 + *minor = GSSEAP_IDENTITY_SERVICE_OS_ERROR;
18050 + case MOONSHOT_ERROR_IPC_ERROR:
18051 + *minor = GSSEAP_IDENTITY_SERVICE_IPC_ERROR;
18054 + *minor = GSSEAP_IDENTITY_SERVICE_UNKNOWN_ERROR;
18058 + gssEapSaveStatusInfo(*minor, error->message);
18059 + moonshot_error_free(error);
18062 + return GSS_S_CRED_UNAVAIL;
18066 +libMoonshotResolveDefaultIdentity(OM_uint32 *minor,
18067 + const gss_cred_id_t cred,
18068 + gss_name_t *pName)
18070 + OM_uint32 major, tmpMinor;
18071 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
18072 + gss_name_t name = GSS_C_NO_NAME;
18073 + gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
18074 + char *nai = NULL;
18075 + char *password = NULL;
18076 + char *serverCertificateHash = NULL;
18077 + char *caCertificate = NULL;
18078 + char *subjectNameConstraint = NULL;
18079 + char *subjectAltNameConstraint = NULL;
18080 + MoonshotError *error = NULL;
18082 + *pName = GSS_C_NO_NAME;
18084 + if (!moonshot_get_default_identity(&nai,
18086 + &serverCertificateHash,
18088 + &subjectNameConstraint,
18089 + &subjectAltNameConstraint,
18091 + if (error->code == MOONSHOT_ERROR_NO_IDENTITY_SELECTED) {
18092 + major = GSS_S_CRED_UNAVAIL;
18093 + *minor = GSSEAP_NO_DEFAULT_IDENTITY;
18094 + moonshot_error_free(error);
18096 + major = libMoonshotMapError(minor, &error);
18100 + tmpBuffer.value = nai;
18101 + tmpBuffer.length = strlen(nai);
18103 + major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME, nameMech, &name);
18104 + if (GSS_ERROR(major))
18108 + name = GSS_C_NO_NAME;
18111 + moonshot_free(nai);
18112 + moonshot_free(password);
18113 + moonshot_free(serverCertificateHash);
18114 + moonshot_free(caCertificate);
18115 + moonshot_free(subjectNameConstraint);
18116 + moonshot_free(subjectAltNameConstraint);
18118 + gssEapReleaseName(&tmpMinor, &name);
18124 +libMoonshotResolveInitiatorCred(OM_uint32 *minor,
18125 + gss_cred_id_t cred,
18126 + const gss_name_t targetName)
18128 + OM_uint32 major, tmpMinor;
18129 + gss_OID nameMech = gssEapPrimaryMechForCred(cred);
18130 + gss_buffer_desc initiator = GSS_C_EMPTY_BUFFER;
18131 + gss_buffer_desc target = GSS_C_EMPTY_BUFFER;
18132 + gss_buffer_desc tmpBuffer = GSS_C_EMPTY_BUFFER;
18133 + char *nai = NULL;
18134 + char *password = NULL;
18135 + char *serverCertificateHash = NULL;
18136 + char *caCertificate = NULL;
18137 + char *subjectNameConstraint = NULL;
18138 + char *subjectAltNameConstraint = NULL;
18139 + MoonshotError *error = NULL;
18141 + if (cred->name != GSS_C_NO_NAME) {
18142 + major = gssEapExportName(minor, cred->name, &initiator);
18143 + if (GSS_ERROR(major))
18147 + if (targetName != GSS_C_NO_NAME) {
18148 + major = gssEapExportName(minor, targetName, &target);
18149 + if (GSS_ERROR(major))
18153 + if (!moonshot_get_identity((const char *)initiator.value,
18154 + (const char *)cred->password.value,
18155 + (const char *)target.value,
18158 + &serverCertificateHash,
18160 + &subjectNameConstraint,
18161 + &subjectAltNameConstraint,
18163 + major = libMoonshotMapError(minor, &error);
18167 + gssEapReleaseName(&tmpMinor, &cred->name);
18169 + tmpBuffer.value = nai;
18170 + tmpBuffer.length = strlen(nai);
18172 + major = gssEapImportName(minor, &tmpBuffer, GSS_C_NT_USER_NAME,
18173 + nameMech, &cred->name);
18174 + if (GSS_ERROR(major))
18177 + tmpBuffer.value = password;
18178 + tmpBuffer.length = strlen(password);
18180 + major = gssEapSetCredPassword(minor, cred, &tmpBuffer);
18181 + if (GSS_ERROR(major))
18184 + gss_release_buffer(&tmpMinor, &cred->caCertificate);
18185 + gss_release_buffer(&tmpMinor, &cred->subjectNameConstraint);
18186 + gss_release_buffer(&tmpMinor, &cred->subjectAltNameConstraint);
18188 + if (serverCertificateHash != NULL) {
18189 + size_t len = strlen(serverCertificateHash);
18191 + #define HASH_PREFIX "hash://server/sha256/"
18192 + #define HASH_PREFIX_LEN (sizeof(HASH_PREFIX) - 1)
18194 + cred->caCertificate.value = GSSEAP_MALLOC(HASH_PREFIX_LEN + len + 1);
18195 + if (cred->caCertificate.value == NULL) {
18196 + major = GSS_S_FAILURE;
18201 + memcpy(cred->caCertificate.value, HASH_PREFIX, HASH_PREFIX_LEN);
18202 + memcpy((char *)cred->caCertificate.value + HASH_PREFIX_LEN, serverCertificateHash, len);
18204 + ((char *)cred->caCertificate.value)[HASH_PREFIX_LEN + len] = '\0';
18206 + cred->caCertificate.length = HASH_PREFIX_LEN + len;
18207 + } else if (caCertificate != NULL) {
18208 + makeStringBufferOrCleanup(caCertificate, &cred->caCertificate);
18211 + if (subjectNameConstraint != NULL)
18212 + makeStringBufferOrCleanup(subjectNameConstraint, &cred->subjectNameConstraint);
18213 + if (subjectAltNameConstraint != NULL)
18214 + makeStringBufferOrCleanup(subjectAltNameConstraint, &cred->subjectAltNameConstraint);
18217 + moonshot_free(nai);
18218 + moonshot_free(password);
18219 + moonshot_free(serverCertificateHash);
18220 + moonshot_free(caCertificate);
18221 + moonshot_free(subjectNameConstraint);
18222 + moonshot_free(subjectAltNameConstraint);
18224 + gss_release_buffer(&tmpMinor, &initiator);
18225 + gss_release_buffer(&tmpMinor, &target);
18229 +#endif /* HAVE_MOONSHOT_GET_IDENTITY */
18230 diff --git a/mech_eap/util_name.c b/mech_eap/util_name.c
18231 new file mode 100644
18232 index 0000000..6045724
18234 +++ b/mech_eap/util_name.c
18237 + * Copyright (c) 2011, JANET(UK)
18238 + * All rights reserved.
18240 + * Redistribution and use in source and binary forms, with or without
18241 + * modification, are permitted provided that the following conditions
18244 + * 1. Redistributions of source code must retain the above copyright
18245 + * notice, this list of conditions and the following disclaimer.
18247 + * 2. Redistributions in binary form must reproduce the above copyright
18248 + * notice, this list of conditions and the following disclaimer in the
18249 + * documentation and/or other materials provided with the distribution.
18251 + * 3. Neither the name of JANET(UK) nor the names of its contributors
18252 + * may be used to endorse or promote products derived from this software
18253 + * without specific prior written permission.
18255 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18256 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18257 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18258 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18259 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18260 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18261 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18262 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18263 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
18264 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18268 + * Portions Copyright 2009 by the Massachusetts Institute of Technology.
18269 + * All Rights Reserved.
18271 + * Export of this software from the United States of America may
18272 + * require a specific license from the United States Government.
18273 + * It is the responsibility of any person or organization contemplating
18274 + * export to obtain such a license before exporting.
18276 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18277 + * distribute this software and its documentation for any purpose and
18278 + * without fee is hereby granted, provided that the above copyright
18279 + * notice appear in all copies and that both that copyright notice and
18280 + * this permission notice appear in supporting documentation, and that
18281 + * the name of M.I.T. not be used in advertising or publicity pertaining
18282 + * to distribution of the software without specific, written prior
18283 + * permission. Furthermore if you modify this software you must label
18284 + * your software as modified software and not distribute it in such a
18285 + * fashion that it might be confused with the original M.I.T. software.
18286 + * M.I.T. makes no representations about the suitability of
18287 + * this software for any purpose. It is provided "as is" without express
18288 + * or implied warranty.
18292 + * Name utility routines.
18295 +#include "gssapiP_eap.h"
18297 +static gss_OID_desc gssEapNtEapName = {
18298 + /* 1.3.6.1.4.1.5322.22.2.1 */
18299 + 10, "\x2B\x06\x01\x04\x01\xA9\x4A\x16\x02\x01"
18302 +gss_OID GSS_EAP_NT_EAP_NAME = &gssEapNtEapName;
18305 +gssEapAllocName(OM_uint32 *minor, gss_name_t *pName)
18307 + OM_uint32 tmpMinor;
18310 + *pName = GSS_C_NO_NAME;
18312 + name = (gss_name_t)GSSEAP_CALLOC(1, sizeof(*name));
18313 + if (name == NULL) {
18315 + return GSS_S_FAILURE;
18318 + if (GSSEAP_MUTEX_INIT(&name->mutex) != 0) {
18319 + *minor = GSSEAP_GET_LAST_ERROR();
18320 + gssEapReleaseName(&tmpMinor, &name);
18321 + return GSS_S_FAILURE;
18326 + return GSS_S_COMPLETE;
18330 +gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName)
18333 + krb5_context krbContext = NULL;
18334 + OM_uint32 tmpMinor;
18338 + if (pName == NULL) {
18339 + return GSS_S_COMPLETE;
18343 + if (name == GSS_C_NO_NAME) {
18344 + return GSS_S_COMPLETE;
18347 + GSSEAP_KRB_INIT(&krbContext);
18348 + krb5_free_principal(krbContext, name->krbPrincipal);
18349 + gssEapReleaseOid(&tmpMinor, &name->mechanismUsed);
18350 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18351 + gssEapReleaseAttrContext(&tmpMinor, name);
18354 + GSSEAP_MUTEX_DESTROY(&name->mutex);
18355 + GSSEAP_FREE(name);
18358 + return GSS_S_COMPLETE;
18362 +krbPrincipalToName(OM_uint32 *minor,
18363 + krb5_principal *principal,
18364 + gss_name_t *pName)
18369 + major = gssEapAllocName(minor, &name);
18370 + if (GSS_ERROR(major))
18373 + name->krbPrincipal = *principal;
18374 + *principal = NULL;
18376 + if (KRB_PRINC_LENGTH(name->krbPrincipal) > 1) {
18377 + name->flags |= NAME_FLAG_SERVICE;
18379 + name->flags |= NAME_FLAG_NAI;
18385 + return GSS_S_COMPLETE;
18389 +gssEapGetDefaultRealm(krb5_context krbContext)
18391 + char *defaultRealm = NULL;
18393 + krb5_appdefault_string(krbContext, "eap_gss",
18394 + NULL, "default_realm", "", &defaultRealm);
18396 + return defaultRealm;
18400 +importServiceName(OM_uint32 *minor,
18401 + const gss_buffer_t nameBuffer,
18402 + gss_name_t *pName)
18405 + krb5_error_code code;
18406 + krb5_context krbContext;
18407 + krb5_principal krbPrinc;
18408 + char *service, *host, *realm = NULL;
18410 + GSSEAP_KRB_INIT(&krbContext);
18412 + major = bufferToString(minor, nameBuffer, &service);
18413 + if (GSS_ERROR(major))
18416 + host = strchr(service, '@');
18417 + if (host != NULL) {
18422 + realm = gssEapGetDefaultRealm(krbContext);
18424 + code = krb5_build_principal(krbContext,
18426 + realm != NULL ? strlen(realm) : 0,
18427 + realm != NULL ? realm : "",
18433 + KRB_PRINC_TYPE(krbPrinc) = KRB5_NT_SRV_HST;
18435 + major = krbPrincipalToName(minor, &krbPrinc, pName);
18436 + if (GSS_ERROR(major))
18437 + krb5_free_principal(krbContext, krbPrinc);
18439 + major = GSS_S_FAILURE;
18440 + *minor = GSSEAP_BAD_SERVICE_NAME;
18443 + if (realm != NULL)
18444 + krb5_free_default_realm(krbContext, realm);
18445 + GSSEAP_FREE(service);
18450 +#define IMPORT_FLAG_DEFAULT_REALM 0x1
18453 + * Import an EAP name, possibly appending the default GSS EAP realm,
18456 +importEapNameFlags(OM_uint32 *minor,
18457 + const gss_buffer_t nameBuffer,
18458 + OM_uint32 importFlags,
18459 + gss_name_t *pName)
18462 + krb5_context krbContext;
18463 + krb5_principal krbPrinc = NULL;
18464 + krb5_error_code code;
18465 + char *nameString;
18467 + GSSEAP_KRB_INIT(&krbContext);
18469 + if (nameBuffer == GSS_C_NO_BUFFER) {
18471 + code = KRB5_PARSE_MALFORMED;
18473 + major = bufferToString(minor, nameBuffer, &nameString);
18474 + if (GSS_ERROR(major))
18478 + * First, attempt to parse the name on the assumption that it includes
18479 + * a qualifying realm. This allows us to avoid accidentally appending
18480 + * the default Kerberos realm to an unqualified name. (A bug in MIT
18481 + * Kerberos prevents the default realm being set to an empty value.)
18483 + code = krb5_parse_name_flags(krbContext, nameString,
18484 + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &krbPrinc);
18487 + if (code == KRB5_PARSE_MALFORMED) {
18488 + char *defaultRealm = NULL;
18489 + int parseFlags = 0;
18491 + /* Possibly append the default EAP realm if required */
18492 + if (importFlags & IMPORT_FLAG_DEFAULT_REALM)
18493 + defaultRealm = gssEapGetDefaultRealm(krbContext);
18495 + /* If no default realm, leave the realm empty in the parsed name */
18496 + if (defaultRealm == NULL || defaultRealm[0] == '\0')
18497 + parseFlags |= KRB5_PRINCIPAL_PARSE_NO_REALM;
18499 + code = krb5_parse_name_flags(krbContext, nameString, parseFlags, &krbPrinc);
18501 +#ifdef HAVE_HEIMDAL_VERSION
18502 + if (code == 0 && KRB_PRINC_REALM(krbPrinc) == NULL) {
18503 + KRB_PRINC_REALM(krbPrinc) = KRB_CALLOC(1, sizeof(char));
18504 + if (KRB_PRINC_REALM(krbPrinc) == NULL)
18509 + if (defaultRealm != NULL)
18510 + krb5_free_default_realm(krbContext, defaultRealm);
18513 + if (nameBuffer != GSS_C_NO_BUFFER)
18514 + GSSEAP_FREE(nameString);
18518 + return GSS_S_FAILURE;
18521 + GSSEAP_ASSERT(krbPrinc != NULL);
18523 + major = krbPrincipalToName(minor, &krbPrinc, pName);
18524 + if (GSS_ERROR(major))
18525 + krb5_free_principal(krbContext, krbPrinc);
18531 +importEapName(OM_uint32 *minor,
18532 + const gss_buffer_t nameBuffer,
18533 + gss_name_t *pName)
18535 + return importEapNameFlags(minor, nameBuffer, 0, pName);
18539 +importUserName(OM_uint32 *minor,
18540 + const gss_buffer_t nameBuffer,
18541 + gss_name_t *pName)
18543 + return importEapNameFlags(minor, nameBuffer, IMPORT_FLAG_DEFAULT_REALM, pName);
18547 +importAnonymousName(OM_uint32 *minor,
18548 + const gss_buffer_t nameBuffer GSSEAP_UNUSED,
18549 + gss_name_t *pName)
18551 + return importEapNameFlags(minor, GSS_C_NO_BUFFER, 0, pName);
18554 +#define UPDATE_REMAIN(n) do { \
18559 +#define CHECK_REMAIN(n) do { \
18560 + if (remain < (n)) { \
18561 + major = GSS_S_BAD_NAME; \
18562 + *minor = GSSEAP_TOK_TRUNC; \
18568 +gssEapImportNameInternal(OM_uint32 *minor,
18569 + const gss_buffer_t nameBuffer,
18570 + gss_name_t *pName,
18573 + OM_uint32 major, tmpMinor;
18574 + krb5_context krbContext;
18575 + unsigned char *p;
18576 + size_t len, remain;
18577 + gss_buffer_desc buf;
18578 + gss_name_t name = GSS_C_NO_NAME;
18579 + gss_OID mechanismUsed = GSS_C_NO_OID;
18581 + GSSEAP_KRB_INIT(&krbContext);
18583 + p = (unsigned char *)nameBuffer->value;
18584 + remain = nameBuffer->length;
18586 + if (flags & EXPORT_NAME_FLAG_OID) {
18587 + gss_OID_desc mech;
18588 + enum gss_eap_token_type tokType;
18589 + uint16_t wireTokType;
18591 + /* TOK_ID || MECH_OID_LEN || MECH_OID */
18592 + if (remain < 6) {
18593 + *minor = GSSEAP_BAD_NAME_TOKEN;
18594 + return GSS_S_BAD_NAME;
18597 + if (flags & EXPORT_NAME_FLAG_COMPOSITE)
18598 + tokType = TOK_TYPE_EXPORT_NAME_COMPOSITE;
18600 + tokType = TOK_TYPE_EXPORT_NAME;
18603 + wireTokType = load_uint16_be(p);
18605 + if ((flags & EXPORT_NAME_FLAG_ALLOW_COMPOSITE) &&
18606 + wireTokType == TOK_TYPE_EXPORT_NAME_COMPOSITE) {
18607 + tokType = TOK_TYPE_EXPORT_NAME_COMPOSITE;
18608 + flags |= EXPORT_NAME_FLAG_COMPOSITE;
18611 + if (wireTokType != tokType) {
18612 + *minor = GSSEAP_WRONG_TOK_ID;
18613 + return GSS_S_BAD_NAME;
18615 + UPDATE_REMAIN(2);
18617 + /* MECH_OID_LEN */
18618 + len = load_uint16_be(p);
18620 + *minor = GSSEAP_BAD_NAME_TOKEN;
18621 + return GSS_S_BAD_NAME;
18623 + UPDATE_REMAIN(2);
18626 + if (p[0] != 0x06) {
18627 + *minor = GSSEAP_BAD_NAME_TOKEN;
18628 + return GSS_S_BAD_NAME;
18631 + mech.length = p[1];
18632 + mech.elements = &p[2];
18634 + CHECK_REMAIN(mech.length);
18636 + major = gssEapCanonicalizeOid(minor,
18638 + OID_FLAG_FAMILY_MECH_VALID |
18639 + OID_FLAG_MAP_FAMILY_MECH_TO_NULL,
18641 + if (GSS_ERROR(major))
18644 + UPDATE_REMAIN(2 + mech.length);
18649 + len = load_uint32_be(p);
18650 + UPDATE_REMAIN(4);
18653 + CHECK_REMAIN(len);
18654 + buf.length = len;
18656 + UPDATE_REMAIN(len);
18658 + major = importEapNameFlags(minor, &buf, 0, &name);
18659 + if (GSS_ERROR(major))
18662 + name->mechanismUsed = mechanismUsed;
18663 + mechanismUsed = GSS_C_NO_OID;
18665 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18666 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18667 + gss_buffer_desc buf;
18669 + buf.length = remain;
18672 + major = gssEapImportAttrContext(minor, &buf, name);
18673 + if (GSS_ERROR(major))
18678 + major = GSS_S_COMPLETE;
18682 + if (GSS_ERROR(major)) {
18683 + gssEapReleaseOid(&tmpMinor, &mechanismUsed);
18684 + gssEapReleaseName(&tmpMinor, &name);
18693 +importExportName(OM_uint32 *minor,
18694 + const gss_buffer_t nameBuffer,
18695 + gss_name_t *name)
18697 + return gssEapImportNameInternal(minor, nameBuffer, name,
18698 + EXPORT_NAME_FLAG_OID |
18699 + EXPORT_NAME_FLAG_ALLOW_COMPOSITE);
18702 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
18704 +importCompositeExportName(OM_uint32 *minor,
18705 + const gss_buffer_t nameBuffer,
18706 + gss_name_t *name)
18708 + return gssEapImportNameInternal(minor, nameBuffer, name,
18709 + EXPORT_NAME_FLAG_OID |
18710 + EXPORT_NAME_FLAG_COMPOSITE);
18714 +struct gss_eap_name_import_provider {
18715 + gss_const_OID oid;
18716 + OM_uint32 (*import)(OM_uint32 *, const gss_buffer_t, gss_name_t *);
18720 +gssEapImportName(OM_uint32 *minor,
18721 + const gss_buffer_t nameBuffer,
18722 + const gss_OID nameType,
18723 + const gss_OID mechType,
18724 + gss_name_t *pName)
18726 + struct gss_eap_name_import_provider nameTypes[] = {
18727 + { GSS_EAP_NT_EAP_NAME, importEapName },
18728 + { GSS_C_NT_USER_NAME, importUserName },
18729 + { GSS_C_NT_HOSTBASED_SERVICE, importServiceName },
18730 + { GSS_C_NT_HOSTBASED_SERVICE_X, importServiceName },
18731 + { GSS_C_NT_ANONYMOUS, importAnonymousName },
18732 + { GSS_C_NT_EXPORT_NAME, importExportName },
18733 + { GSS_KRB5_NT_PRINCIPAL_NAME, importUserName },
18734 +#ifdef HAVE_GSS_C_NT_COMPOSITE_EXPORT
18735 + { GSS_C_NT_COMPOSITE_EXPORT, importCompositeExportName },
18739 + OM_uint32 major = GSS_S_BAD_NAMETYPE;
18740 + OM_uint32 tmpMinor;
18741 + gss_name_t name = GSS_C_NO_NAME;
18743 + for (i = 0; i < sizeof(nameTypes) / sizeof(nameTypes[0]); i++) {
18744 + if (oidEqual(nameTypes[i].oid,
18745 + nameType == GSS_C_NO_OID ? GSS_EAP_NT_EAP_NAME : nameType)) {
18746 + major = nameTypes[i].import(minor, nameBuffer, &name);
18751 + if (major == GSS_S_COMPLETE &&
18752 + mechType != GSS_C_NO_OID) {
18753 + GSSEAP_ASSERT(gssEapIsConcreteMechanismOid(mechType));
18754 + GSSEAP_ASSERT(name->mechanismUsed == GSS_C_NO_OID);
18756 + major = gssEapCanonicalizeOid(minor, mechType, 0, &name->mechanismUsed);
18759 + if (GSS_ERROR(major))
18760 + gssEapReleaseName(&tmpMinor, &name);
18768 +gssEapExportName(OM_uint32 *minor,
18769 + const gss_name_t name,
18770 + gss_buffer_t exportedName)
18772 + return gssEapExportNameInternal(minor, name, exportedName,
18773 + EXPORT_NAME_FLAG_OID);
18777 +gssEapExportNameInternal(OM_uint32 *minor,
18778 + const gss_name_t name,
18779 + gss_buffer_t exportedName,
18782 + OM_uint32 major = GSS_S_FAILURE, tmpMinor;
18783 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
18784 + size_t exportedNameLen;
18785 + unsigned char *p;
18786 + gss_buffer_desc attrs = GSS_C_EMPTY_BUFFER;
18789 + exportedName->length = 0;
18790 + exportedName->value = NULL;
18792 + if (name->mechanismUsed != GSS_C_NO_OID)
18793 + mech = name->mechanismUsed;
18795 + mech = GSS_EAP_MECHANISM;
18797 + major = gssEapDisplayName(minor, name, &nameBuf, NULL);
18798 + if (GSS_ERROR(major))
18801 + exportedNameLen = 0;
18802 + if (flags & EXPORT_NAME_FLAG_OID) {
18803 + exportedNameLen += 6 + mech->length;
18805 + exportedNameLen += 4 + nameBuf.length;
18806 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18807 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18808 + major = gssEapExportAttrContext(minor, name, &attrs);
18809 + if (GSS_ERROR(major))
18811 + exportedNameLen += attrs.length;
18815 + exportedName->value = GSSEAP_MALLOC(exportedNameLen);
18816 + if (exportedName->value == NULL) {
18817 + major = GSS_S_FAILURE;
18821 + exportedName->length = exportedNameLen;
18823 + p = (unsigned char *)exportedName->value;
18825 + if (flags & EXPORT_NAME_FLAG_OID) {
18826 + /* TOK | MECH_OID_LEN */
18827 + store_uint16_be((flags & EXPORT_NAME_FLAG_COMPOSITE)
18828 + ? TOK_TYPE_EXPORT_NAME_COMPOSITE
18829 + : TOK_TYPE_EXPORT_NAME,
18832 + store_uint16_be(mech->length + 2, p);
18837 + *p++ = mech->length & 0xff;
18838 + memcpy(p, mech->elements, mech->length);
18839 + p += mech->length;
18843 + store_uint32_be(nameBuf.length, p);
18847 + memcpy(p, nameBuf.value, nameBuf.length);
18848 + p += nameBuf.length;
18850 + if (flags & EXPORT_NAME_FLAG_COMPOSITE) {
18851 + memcpy(p, attrs.value, attrs.length);
18852 + p += attrs.length;
18855 + GSSEAP_ASSERT(p == (unsigned char *)exportedName->value + exportedNameLen);
18857 + major = GSS_S_COMPLETE;
18861 + gss_release_buffer(&tmpMinor, &attrs);
18862 + gss_release_buffer(&tmpMinor, &nameBuf);
18863 + if (GSS_ERROR(major))
18864 + gss_release_buffer(&tmpMinor, exportedName);
18870 +gssEapCanonicalizeName(OM_uint32 *minor,
18871 + const gss_name_t input_name,
18872 + const gss_OID mech_type,
18873 + gss_name_t *dest_name)
18875 + OM_uint32 major, tmpMinor;
18876 + krb5_context krbContext;
18878 + gss_OID mech_used;
18880 + if (input_name == GSS_C_NO_NAME) {
18882 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
18885 + GSSEAP_KRB_INIT(&krbContext);
18887 + major = gssEapAllocName(minor, &name);
18888 + if (GSS_ERROR(major)) {
18892 + if (mech_type != GSS_C_NO_OID)
18893 + mech_used = mech_type;
18895 + mech_used = input_name->mechanismUsed;
18897 + major = gssEapCanonicalizeOid(minor,
18899 + OID_FLAG_NULL_VALID,
18900 + &name->mechanismUsed);
18901 + if (GSS_ERROR(major))
18904 + name->flags = input_name->flags;
18906 + *minor = krb5_copy_principal(krbContext, input_name->krbPrincipal,
18907 + &name->krbPrincipal);
18908 + if (*minor != 0) {
18909 + major = GSS_S_FAILURE;
18913 +#ifdef GSSEAP_ENABLE_ACCEPTOR
18914 + if (input_name->attrCtx != NULL) {
18915 + major = gssEapDuplicateAttrContext(minor, input_name, name);
18916 + if (GSS_ERROR(major))
18921 + *dest_name = name;
18924 + if (GSS_ERROR(major)) {
18925 + gssEapReleaseName(&tmpMinor, &name);
18932 +gssEapDuplicateName(OM_uint32 *minor,
18933 + const gss_name_t input_name,
18934 + gss_name_t *dest_name)
18936 + return gssEapCanonicalizeName(minor, input_name,
18937 + GSS_C_NO_OID, dest_name);
18941 +gssEapDisplayName(OM_uint32 *minor,
18943 + gss_buffer_t output_name_buffer,
18944 + gss_OID *output_name_type)
18947 + krb5_context krbContext;
18949 + gss_OID name_type;
18952 + GSSEAP_KRB_INIT(&krbContext);
18954 + output_name_buffer->length = 0;
18955 + output_name_buffer->value = NULL;
18957 + if (name == GSS_C_NO_NAME) {
18959 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME;
18963 + * According to draft-ietf-abfab-gss-eap-01, when the realm is
18964 + * absent the trailing '@' is not included.
18966 +#ifdef HAVE_HEIMDAL_VERSION
18967 + if (KRB_PRINC_REALM(name->krbPrincipal) == NULL ||
18968 + KRB_PRINC_REALM(name->krbPrincipal)[0] == '\0')
18970 + if (KRB_PRINC_REALM(name->krbPrincipal)->length == 0)
18972 + flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
18974 + *minor = krb5_unparse_name_flags(krbContext, name->krbPrincipal,
18975 + flags, &krbName);
18976 + if (*minor != 0) {
18977 + return GSS_S_FAILURE;
18980 + major = makeStringBuffer(minor, krbName, output_name_buffer);
18981 + if (GSS_ERROR(major)) {
18982 + krb5_free_unparsed_name(krbContext, krbName);
18986 + krb5_free_unparsed_name(krbContext, krbName);
18988 + if (output_name_buffer->length == 0) {
18989 + name_type = GSS_C_NT_ANONYMOUS;
18990 + } else if (name->flags & NAME_FLAG_NAI) {
18991 + name_type = GSS_C_NT_USER_NAME;
18993 + name_type = GSS_EAP_NT_EAP_NAME;
18996 + if (output_name_type != NULL)
18997 + *output_name_type = name_type;
18999 + return GSS_S_COMPLETE;
19003 +gssEapCompareName(OM_uint32 *minor,
19004 + gss_name_t name1,
19005 + gss_name_t name2,
19008 + krb5_context krbContext;
19012 + if (name1 == GSS_C_NO_NAME && name2 == GSS_C_NO_NAME) {
19014 + } else if (name1 != GSS_C_NO_NAME && name2 != GSS_C_NO_NAME) {
19015 + GSSEAP_KRB_INIT(&krbContext);
19017 + /* krbPrincipal is immutable, so lock not required */
19018 + *name_equal = krb5_principal_compare(krbContext,
19019 + name1->krbPrincipal,
19020 + name2->krbPrincipal);
19023 + return GSS_S_COMPLETE;
19025 diff --git a/mech_eap/util_oid.c b/mech_eap/util_oid.c
19026 new file mode 100644
19027 index 0000000..096c9f8
19029 +++ b/mech_eap/util_oid.c
19032 + * Copyright (c) 2011, JANET(UK)
19033 + * All rights reserved.
19035 + * Redistribution and use in source and binary forms, with or without
19036 + * modification, are permitted provided that the following conditions
19039 + * 1. Redistributions of source code must retain the above copyright
19040 + * notice, this list of conditions and the following disclaimer.
19042 + * 2. Redistributions in binary form must reproduce the above copyright
19043 + * notice, this list of conditions and the following disclaimer in the
19044 + * documentation and/or other materials provided with the distribution.
19046 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19047 + * may be used to endorse or promote products derived from this software
19048 + * without specific prior written permission.
19050 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19051 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19052 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19053 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19054 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19055 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19056 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19057 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19058 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19059 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19063 + * Copyright 1995-2010 by the Massachusetts Institute of Technology.
19064 + * All Rights Reserved.
19066 + * Export of this software from the United States of America may
19067 + * require a specific license from the United States Government.
19068 + * It is the responsibility of any person or organization contemplating
19069 + * export to obtain such a license before exporting.
19071 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19072 + * distribute this software and its documentation for any purpose and
19073 + * without fee is hereby granted, provided that the above copyright
19074 + * notice appear in all copies and that both that copyright notice and
19075 + * this permission notice appear in supporting documentation, and that
19076 + * the name of M.I.T. not be used in advertising or publicity pertaining
19077 + * to distribution of the software without specific, written prior
19078 + * permission. Furthermore if you modify this software you must label
19079 + * your software as modified software and not distribute it in such a
19080 + * fashion that it might be confused with the original M.I.T. software.
19081 + * M.I.T. makes no representations about the suitability of
19082 + * this software for any purpose. It is provided "as is" without express
19083 + * or implied warranty.
19088 + * OID utility routines.
19091 +#include "gssapiP_eap.h"
19094 +duplicateOid(OM_uint32 *minor,
19095 + const gss_OID_desc * const oid,
19100 + *newOid = GSS_C_NO_OID;
19102 + p = (gss_OID)GSSEAP_MALLOC(sizeof(*p));
19105 + return GSS_S_FAILURE;
19107 + p->length = oid->length;
19108 + p->elements = GSSEAP_MALLOC(p->length);
19109 + if (p->elements == NULL) {
19112 + return GSS_S_FAILURE;
19115 + memcpy(p->elements, oid->elements, p->length);
19119 + return GSS_S_COMPLETE;
19122 +/* Compose an OID of a prefix and an integer suffix */
19124 +composeOid(OM_uint32 *minor,
19125 + const char *prefix,
19126 + size_t prefix_len,
19128 + gss_OID_desc *oid)
19132 + unsigned char *op;
19134 + if (oid == GSS_C_NO_OID) {
19136 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_FAILURE;
19139 + if (oid->length < prefix_len) {
19140 + *minor = GSSEAP_WRONG_SIZE;
19141 + return GSS_S_FAILURE;
19144 + memcpy(oid->elements, prefix, prefix_len);
19147 + osuffix = suffix;
19152 + suffix = osuffix;
19154 + if (oid->length < prefix_len + nbytes) {
19155 + *minor = GSSEAP_WRONG_SIZE;
19156 + return GSS_S_FAILURE;
19159 + op = (unsigned char *) oid->elements + prefix_len + nbytes;
19162 + op[i] = (unsigned char)suffix & 0x7f;
19169 + oid->length = prefix_len + nbytes;
19172 + return GSS_S_COMPLETE;
19176 +decomposeOid(OM_uint32 *minor,
19177 + const char *prefix,
19178 + size_t prefix_len,
19179 + gss_OID_desc *oid,
19183 + unsigned char *op;
19185 + if (oid->length < prefix_len ||
19186 + memcmp(oid->elements, prefix, prefix_len) != 0) {
19187 + return GSS_S_BAD_MECH;
19190 + op = (unsigned char *) oid->elements + prefix_len;
19194 + slen = oid->length - prefix_len;
19196 + for (i = 0; i < slen; i++) {
19197 + *suffix = (*suffix << 7) | (op[i] & 0x7f);
19198 + if (i + 1 != slen && (op[i] & 0x80) == 0) {
19199 + *minor = GSSEAP_WRONG_SIZE;
19200 + return GSS_S_FAILURE;
19204 + return GSS_S_COMPLETE;
19208 +duplicateOidSet(OM_uint32 *minor,
19209 + const gss_OID_set src,
19210 + gss_OID_set *dst)
19212 + OM_uint32 major, tmpMinor;
19215 + if (src == GSS_C_NO_OID_SET) {
19216 + *dst = GSS_C_NO_OID_SET;
19217 + return GSS_S_COMPLETE;
19220 + major = gss_create_empty_oid_set(minor, dst);
19221 + if (GSS_ERROR(major))
19224 + for (i = 0; i < src->count; i++) {
19225 + gss_OID oid = &src->elements[i];
19227 + major = gss_add_oid_set_member(minor, oid, dst);
19228 + if (GSS_ERROR(major))
19232 + if (GSS_ERROR(major))
19233 + gss_release_oid_set(&tmpMinor, dst);
19237 diff --git a/mech_eap/util_ordering.c b/mech_eap/util_ordering.c
19238 new file mode 100644
19239 index 0000000..71ebfb5
19241 +++ b/mech_eap/util_ordering.c
19244 + * Copyright (c) 2011, JANET(UK)
19245 + * All rights reserved.
19247 + * Redistribution and use in source and binary forms, with or without
19248 + * modification, are permitted provided that the following conditions
19251 + * 1. Redistributions of source code must retain the above copyright
19252 + * notice, this list of conditions and the following disclaimer.
19254 + * 2. Redistributions in binary form must reproduce the above copyright
19255 + * notice, this list of conditions and the following disclaimer in the
19256 + * documentation and/or other materials provided with the distribution.
19258 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19259 + * may be used to endorse or promote products derived from this software
19260 + * without specific prior written permission.
19262 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19263 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19264 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19265 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19266 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19267 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19268 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19269 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19270 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19271 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19275 + * Copyright 1993 by OpenVision Technologies, Inc.
19277 + * Permission to use, copy, modify, distribute, and sell this software
19278 + * and its documentation for any purpose is hereby granted without fee,
19279 + * provided that the above copyright notice appears in all copies and
19280 + * that both that copyright notice and this permission notice appear in
19281 + * supporting documentation, and that the name of OpenVision not be used
19282 + * in advertising or publicity pertaining to distribution of the software
19283 + * without specific, written prior permission. OpenVision makes no
19284 + * representations about the suitability of this software for any
19285 + * purpose. It is provided "as is" without express or implied warranty.
19287 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19288 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19289 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19290 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19291 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19292 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19293 + * PERFORMANCE OF THIS SOFTWARE.
19297 + * Functions to check sequence numbers for replay and sequencing
19300 +#include "gssapiP_eap.h"
19302 +#define QUEUE_LENGTH 20
19304 +typedef struct _queue {
19309 + uint64_t firstnum;
19310 + /* Stored as deltas from firstnum. This way, the high bit won't
19311 + overflow unless we've actually gone through 2**n messages, or
19312 + gotten something *way* out of sequence. */
19313 + uint64_t elem[QUEUE_LENGTH];
19314 + /* All ones for 64-bit sequence numbers; 32 ones for 32-bit
19315 + sequence numbers. */
19320 + * - the queue is a circular queue. The first element (q->elem[q->start])
19321 + * is the oldest. The last element is the newest.
19324 +#define QSIZE(q) (sizeof((q)->elem)/sizeof((q)->elem[0]))
19325 +#define QELEM(q,i) ((q)->elem[(i)%QSIZE(q)])
19328 +queue_insert(queue *q, int after, uint64_t seqnum)
19330 + /* insert. this is not the fastest way, but it's easy, and it's
19331 + optimized for insert at end, which is the common case */
19334 + /* common case: at end, after == q->start+q->length-1 */
19336 + /* move all the elements (after,last] up one slot */
19338 + for (i = q->start + q->length - 1; i > after; i--)
19339 + QELEM(q,i+1) = QELEM(q,i);
19341 + /* fill in slot after+1 */
19343 + QELEM(q,after+1) = seqnum;
19345 + /* Either increase the length by one, or move the starting point up
19346 + one (deleting the first element, which got bashed above), as
19349 + if (q->length == QSIZE(q)) {
19351 + if (q->start == QSIZE(q))
19359 +sequenceInit(OM_uint32 *minor,
19368 + q = (queue *)GSSEAP_CALLOC(1, sizeof(queue));
19371 + return GSS_S_FAILURE;
19374 + q->do_replay = do_replay;
19375 + q->do_sequence = do_sequence;
19376 + q->mask = wide_nums ? ~(uint64_t)0 : 0xffffffffUL;
19380 + q->firstnum = seqnum;
19381 + q->elem[q->start] = ((uint64_t)0 - 1) & q->mask;
19383 + *vqueue = (void *)q;
19385 + return GSS_S_COMPLETE;
19389 +sequenceCheck(OM_uint32 *minor,
19395 + uint64_t expected;
19399 + q = (queue *) (*vqueue);
19401 + if (!q->do_replay && !q->do_sequence)
19402 + return GSS_S_COMPLETE;
19404 + /* All checks are done relative to the initial sequence number, to
19405 + avoid (or at least put off) the pain of wrapping. */
19406 + seqnum -= q->firstnum;
19407 + /* If we're only doing 32-bit values, adjust for that again.
19409 + Note that this will probably be the wrong thing to if we get
19410 + 2**32 messages sent with 32-bit sequence numbers. */
19411 + seqnum &= q->mask;
19413 + /* rule 1: expected sequence number */
19415 + expected = (QELEM(q,q->start+q->length-1)+1) & q->mask;
19416 + if (seqnum == expected) {
19417 + queue_insert(q, q->start+q->length-1, seqnum);
19418 + return GSS_S_COMPLETE;
19421 + /* rule 2: > expected sequence number */
19423 + if ((seqnum > expected)) {
19424 + queue_insert(q, q->start+q->length-1, seqnum);
19425 + if (q->do_replay && !q->do_sequence)
19426 + return GSS_S_COMPLETE;
19428 + return GSS_S_GAP_TOKEN;
19431 + /* rule 3: seqnum < seqnum(first) */
19433 + if ((seqnum < QELEM(q,q->start)) &&
19434 + /* Is top bit of whatever width we're using set?
19436 + We used to check for greater than or equal to firstnum, but
19437 + (1) we've since switched to compute values relative to
19438 + firstnum, so the lowest we can have is 0, and (2) the effect
19439 + of the original scheme was highly dependent on whether
19440 + firstnum was close to either side of 0. (Consider
19441 + firstnum==0xFFFFFFFE and we miss three packets; the next
19442 + packet is *new* but would look old.)
19444 + This check should give us 2**31 or 2**63 messages "new", and
19445 + just as many "old". That's not quite right either. */
19446 + (seqnum & (1 + (q->mask >> 1)))
19448 + if (q->do_replay && !q->do_sequence)
19449 + return GSS_S_OLD_TOKEN;
19451 + return GSS_S_UNSEQ_TOKEN;
19454 + /* rule 4+5: seqnum in [seqnum(first),seqnum(last)] */
19457 + if (seqnum == QELEM(q,q->start+q->length - 1))
19458 + return GSS_S_DUPLICATE_TOKEN;
19460 + for (i = q->start; i < q->start + q->length - 1; i++) {
19461 + if (seqnum == QELEM(q,i))
19462 + return GSS_S_DUPLICATE_TOKEN;
19463 + if ((seqnum > QELEM(q,i)) && (seqnum < QELEM(q,i+1))) {
19464 + queue_insert(q, i, seqnum);
19465 + if (q->do_replay && !q->do_sequence)
19466 + return GSS_S_COMPLETE;
19468 + return GSS_S_UNSEQ_TOKEN;
19473 + /* this should never happen */
19474 + return GSS_S_FAILURE;
19478 +sequenceFree(OM_uint32 *minor, void **vqueue)
19482 + q = (queue *) (*vqueue);
19489 + return GSS_S_COMPLETE;
19493 + * These support functions are for the serialization routines
19496 +sequenceSize(void *vqueue GSSEAP_UNUSED)
19498 + return sizeof(queue);
19502 +sequenceExternalize(OM_uint32 *minor,
19504 + unsigned char **buf,
19505 + size_t *lenremain)
19507 + if (*lenremain < sizeof(queue)) {
19508 + *minor = GSSEAP_WRONG_SIZE;
19509 + return GSS_S_FAILURE;
19511 + memcpy(*buf, vqueue, sizeof(queue));
19512 + *buf += sizeof(queue);
19513 + *lenremain -= sizeof(queue);
19519 +sequenceInternalize(OM_uint32 *minor,
19521 + unsigned char **buf,
19522 + size_t *lenremain)
19526 + if (*lenremain < sizeof(queue)) {
19527 + *minor = GSSEAP_TOK_TRUNC;
19528 + return GSS_S_DEFECTIVE_TOKEN;
19531 + q = GSSEAP_MALLOC(sizeof(queue));
19534 + return GSS_S_FAILURE;
19537 + memcpy(q, *buf, sizeof(queue));
19538 + *buf += sizeof(queue);
19539 + *lenremain -= sizeof(queue);
19543 + return GSS_S_COMPLETE;
19545 diff --git a/mech_eap/util_radius.cpp b/mech_eap/util_radius.cpp
19546 new file mode 100644
19547 index 0000000..9111e20
19549 +++ b/mech_eap/util_radius.cpp
19552 + * Copyright (c) 2011, JANET(UK)
19553 + * All rights reserved.
19555 + * Redistribution and use in source and binary forms, with or without
19556 + * modification, are permitted provided that the following conditions
19559 + * 1. Redistributions of source code must retain the above copyright
19560 + * notice, this list of conditions and the following disclaimer.
19562 + * 2. Redistributions in binary form must reproduce the above copyright
19563 + * notice, this list of conditions and the following disclaimer in the
19564 + * documentation and/or other materials provided with the distribution.
19566 + * 3. Neither the name of JANET(UK) nor the names of its contributors
19567 + * may be used to endorse or promote products derived from this software
19568 + * without specific prior written permission.
19570 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19571 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19572 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19573 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19574 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19575 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19576 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19577 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
19578 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19579 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
19584 + * RADIUS attribute provider implementation.
19587 +#include "gssapiP_eap.h"
19589 +/* stuff that should be provided by libradsec/libfreeradius-radius */
19590 +#define VENDORATTR(vendor, attr) (((vendor) << 16) | (attr))
19593 +#define ATTRID(attr) ((attr) & 0xFFFF)
19596 +static gss_buffer_desc radiusUrnPrefix = {
19597 + sizeof("urn:x-radius:") - 1,
19598 + (void *)"urn:x-radius:"
19601 +static VALUE_PAIR *copyAvps(const VALUE_PAIR *src);
19603 +gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(void)
19606 + m_authenticated = false;
19609 +gss_eap_radius_attr_provider::~gss_eap_radius_attr_provider(void)
19611 + if (m_vps != NULL)
19612 + pairfree(&m_vps);
19616 +gss_eap_radius_attr_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
19617 + const gss_eap_attr_provider *ctx)
19619 + const gss_eap_radius_attr_provider *radius;
19621 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx))
19624 + radius = static_cast<const gss_eap_radius_attr_provider *>(ctx);
19626 + if (radius->m_vps != NULL)
19627 + m_vps = copyAvps(const_cast<VALUE_PAIR *>(radius->getAvps()));
19629 + m_authenticated = radius->m_authenticated;
19635 +gss_eap_radius_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
19636 + const gss_cred_id_t gssCred,
19637 + const gss_ctx_id_t gssCtx)
19639 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
19642 + if (gssCtx != GSS_C_NO_CONTEXT) {
19643 + if (gssCtx->acceptorCtx.vps != NULL) {
19644 + m_vps = copyAvps(gssCtx->acceptorCtx.vps);
19645 + if (m_vps == NULL)
19648 + /* We assume libradsec validated this for us */
19649 + GSSEAP_ASSERT(pairfind(m_vps, PW_MESSAGE_AUTHENTICATOR) != NULL);
19650 + m_authenticated = true;
19658 +alreadyAddedAttributeP(std::vector <std::string> &attrs, VALUE_PAIR *vp)
19660 + for (std::vector<std::string>::const_iterator a = attrs.begin();
19661 + a != attrs.end();
19663 + if (strcmp(vp->name, (*a).c_str()) == 0)
19671 +isSecretAttributeP(uint16_t attrid, uint16_t vendor)
19673 + bool bSecretAttribute = false;
19675 + switch (vendor) {
19676 + case VENDORPEC_MS:
19677 + switch (attrid) {
19678 + case PW_MS_MPPE_SEND_KEY:
19679 + case PW_MS_MPPE_RECV_KEY:
19680 + bSecretAttribute = true;
19689 + return bSecretAttribute;
19693 +isSecretAttributeP(uint32_t attribute)
19695 + return isSecretAttributeP(ATTRID(attribute), VENDOR(attribute));
19699 +isInternalAttributeP(uint16_t attrid, uint16_t vendor)
19701 + bool bInternalAttribute = false;
19703 + /* should have been filtered */
19704 + GSSEAP_ASSERT(!isSecretAttributeP(attrid, vendor));
19706 + switch (vendor) {
19707 + case VENDORPEC_UKERNA:
19708 + switch (attrid) {
19709 + case PW_GSS_ACCEPTOR_SERVICE_NAME:
19710 + case PW_GSS_ACCEPTOR_HOST_NAME:
19711 + case PW_GSS_ACCEPTOR_SERVICE_SPECIFIC:
19712 + case PW_GSS_ACCEPTOR_REALM_NAME:
19713 + case PW_SAML_AAA_ASSERTION:
19714 + bInternalAttribute = true;
19724 + return bInternalAttribute;
19728 +isInternalAttributeP(uint32_t attribute)
19730 + return isInternalAttributeP(ATTRID(attribute), VENDOR(attribute));
19734 +isFragmentedAttributeP(uint16_t attrid, uint16_t vendor)
19736 + /* A bit of a hack for the PAC for now. Should be configurable. */
19737 + return (vendor == VENDORPEC_UKERNA) &&
19738 + !isInternalAttributeP(attrid, vendor);
19742 +isFragmentedAttributeP(uint32_t attribute)
19744 + return isFragmentedAttributeP(ATTRID(attribute), VENDOR(attribute));
19748 + * Copy AVP list, same as paircopy except it filters out attributes
19749 + * containing keys.
19751 +static VALUE_PAIR *
19752 +copyAvps(const VALUE_PAIR *src)
19754 + const VALUE_PAIR *vp;
19755 + VALUE_PAIR *dst = NULL, **pDst = &dst;
19757 + for (vp = src; vp != NULL; vp = vp->next) {
19758 + VALUE_PAIR *vpcopy;
19760 + if (isSecretAttributeP(vp->attribute))
19763 + vpcopy = paircopyvp(vp);
19764 + if (vpcopy == NULL) {
19766 + throw std::bad_alloc();
19769 + pDst = &vpcopy->next;
19776 +gss_eap_radius_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
19777 + void *data) const
19780 + std::vector <std::string> seen;
19782 + for (vp = m_vps; vp != NULL; vp = vp->next) {
19783 + gss_buffer_desc attribute;
19786 + /* Don't advertise attributes that are internal to the GSS-EAP mechanism */
19787 + if (isInternalAttributeP(vp->attribute))
19790 + if (alreadyAddedAttributeP(seen, vp))
19793 + snprintf(attrid, sizeof(attrid), "%s%d",
19794 + (char *)radiusUrnPrefix.value, vp->attribute);
19796 + attribute.value = attrid;
19797 + attribute.length = strlen(attrid);
19799 + if (!addAttribute(m_manager, this, &attribute, data))
19802 + seen.push_back(std::string(vp->name));
19809 +getAttributeId(const gss_buffer_t attr)
19811 + OM_uint32 tmpMinor;
19812 + gss_buffer_desc strAttr = GSS_C_EMPTY_BUFFER;
19815 + uint32_t attrid = 0;
19817 + if (attr->length < radiusUrnPrefix.length ||
19818 + memcmp(attr->value, radiusUrnPrefix.value, radiusUrnPrefix.length) != 0)
19821 + /* need to duplicate because attr may not be NUL terminated */
19822 + duplicateBuffer(*attr, &strAttr);
19823 + s = (char *)strAttr.value + radiusUrnPrefix.length;
19825 + if (isdigit(*s)) {
19826 + attrid = strtoul(s, NULL, 10);
19828 + da = dict_attrbyname(s);
19830 + attrid = da->attr;
19833 + gss_release_buffer(&tmpMinor, &strAttr);
19839 +gss_eap_radius_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
19841 + const gss_buffer_t value)
19843 + OM_uint32 major = GSS_S_UNAVAILABLE, minor;
19845 + if (!isSecretAttributeP(attrid) &&
19846 + !isInternalAttributeP(attrid)) {
19847 + deleteAttribute(attrid);
19849 + major = gssEapRadiusAddAvp(&minor, &m_vps,
19850 + ATTRID(attrid), VENDOR(attrid),
19854 + return !GSS_ERROR(major);
19858 +gss_eap_radius_attr_provider::setAttribute(int complete,
19859 + const gss_buffer_t attr,
19860 + const gss_buffer_t value)
19862 + uint32_t attrid = getAttributeId(attr);
19867 + return setAttribute(complete, attrid, value);
19871 +gss_eap_radius_attr_provider::deleteAttribute(uint32_t attrid)
19873 + if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid) ||
19874 + pairfind(m_vps, attrid) == NULL)
19877 + pairdelete(&m_vps, attrid);
19883 +gss_eap_radius_attr_provider::deleteAttribute(const gss_buffer_t attr)
19885 + uint32_t attrid = getAttributeId(attr);
19890 + return deleteAttribute(attrid);
19894 +gss_eap_radius_attr_provider::getAttribute(const gss_buffer_t attr,
19895 + int *authenticated,
19897 + gss_buffer_t value,
19898 + gss_buffer_t display_value,
19903 + attrid = getAttributeId(attr);
19907 + return getAttribute(attrid, authenticated, complete,
19908 + value, display_value, more);
19912 +gss_eap_radius_attr_provider::getAttribute(uint32_t attrid,
19913 + int *authenticated,
19915 + gss_buffer_t value,
19916 + gss_buffer_t display_value,
19920 + int i = *more, count = 0;
19927 + if (isSecretAttributeP(attrid) || isInternalAttributeP(attrid)) {
19929 + } else if (isFragmentedAttributeP(attrid)) {
19930 + return getFragmentedAttribute(attrid,
19936 + for (vp = pairfind(m_vps, attrid);
19938 + vp = pairfind(vp->next, attrid)) {
19939 + if (count++ == i) {
19940 + if (pairfind(vp->next, attrid) != NULL)
19946 + if (vp == NULL && *more == 0)
19949 + if (value != GSS_C_NO_BUFFER) {
19950 + gss_buffer_desc valueBuf;
19952 + valueBuf.value = (void *)vp->vp_octets;
19953 + valueBuf.length = vp->length;
19955 + duplicateBuffer(valueBuf, value);
19958 + if (display_value != GSS_C_NO_BUFFER &&
19959 + vp->type != PW_TYPE_OCTETS) {
19960 + char displayString[MAX_STRING_LEN];
19961 + gss_buffer_desc displayBuf;
19963 + displayBuf.length = vp_prints_value(displayString,
19964 + sizeof(displayString), vp, 0);
19965 + displayBuf.value = (void *)displayString;
19967 + duplicateBuffer(displayBuf, display_value);
19970 + if (authenticated != NULL)
19971 + *authenticated = m_authenticated;
19972 + if (complete != NULL)
19973 + *complete = true;
19979 +gss_eap_radius_attr_provider::getFragmentedAttribute(uint16_t attribute,
19981 + int *authenticated,
19983 + gss_buffer_t value) const
19985 + OM_uint32 major, minor;
19987 + major = gssEapRadiusGetAvp(&minor, m_vps, attribute, vendor, value, TRUE);
19989 + if (authenticated != NULL)
19990 + *authenticated = m_authenticated;
19991 + if (complete != NULL)
19992 + *complete = true;
19994 + return !GSS_ERROR(major);
19998 +gss_eap_radius_attr_provider::getFragmentedAttribute(uint32_t attrid,
19999 + int *authenticated,
20001 + gss_buffer_t value) const
20003 + return getFragmentedAttribute(ATTRID(attrid), VENDOR(attrid),
20004 + authenticated, complete, value);
20008 +gss_eap_radius_attr_provider::getAttribute(uint16_t attribute,
20010 + int *authenticated,
20012 + gss_buffer_t value,
20013 + gss_buffer_t display_value,
20017 + return getAttribute(VENDORATTR(attribute, vendor),
20018 + authenticated, complete,
20019 + value, display_value, more);
20023 +gss_eap_radius_attr_provider::mapToAny(int authenticated,
20024 + gss_buffer_t type_id GSSEAP_UNUSED) const
20026 + if (authenticated && !m_authenticated)
20027 + return (gss_any_t)NULL;
20029 + return (gss_any_t)copyAvps(m_vps);
20033 +gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
20034 + gss_any_t input) const
20036 + VALUE_PAIR *vp = (VALUE_PAIR *)input;
20041 +gss_eap_radius_attr_provider::init(void)
20043 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_RADIUS, createAttrContext);
20049 +gss_eap_radius_attr_provider::finalize(void)
20051 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_RADIUS);
20054 +gss_eap_attr_provider *
20055 +gss_eap_radius_attr_provider::createAttrContext(void)
20057 + return new gss_eap_radius_attr_provider;
20061 +gssEapRadiusAddAvp(OM_uint32 *minor,
20062 + VALUE_PAIR **vps,
20063 + uint16_t attribute,
20065 + const gss_buffer_t buffer)
20067 + uint32_t attrid = VENDORATTR(vendor, attribute);
20068 + unsigned char *p = (unsigned char *)buffer->value;
20069 + size_t remain = buffer->length;
20073 + size_t n = remain;
20076 + * There's an extra byte of padding; RADIUS AVPs can only
20079 + if (n >= MAX_STRING_LEN)
20080 + n = MAX_STRING_LEN - 1;
20082 + vp = paircreate(attrid, PW_TYPE_OCTETS);
20083 + if (vp == NULL) {
20085 + return GSS_S_FAILURE;
20088 + memcpy(vp->vp_octets, p, n);
20091 + pairadd(vps, vp);
20095 + } while (remain != 0);
20097 + return GSS_S_COMPLETE;
20101 +gssEapRadiusGetRawAvp(OM_uint32 *minor,
20103 + uint16_t attribute,
20107 + uint32_t attr = VENDORATTR(vendor, attribute);
20109 + *vp = pairfind(vps, attr);
20110 + if (*vp == NULL) {
20111 + *minor = GSSEAP_NO_SUCH_ATTR;
20112 + return GSS_S_UNAVAILABLE;
20115 + return GSS_S_COMPLETE;
20119 +gssEapRadiusGetAvp(OM_uint32 *minor,
20121 + uint16_t attribute,
20123 + gss_buffer_t buffer,
20127 + unsigned char *p;
20128 + uint32_t attr = VENDORATTR(vendor, attribute);
20130 + if (buffer != GSS_C_NO_BUFFER) {
20131 + buffer->length = 0;
20132 + buffer->value = NULL;
20135 + vp = pairfind(vps, attr);
20136 + if (vp == NULL) {
20137 + *minor = GSSEAP_NO_SUCH_ATTR;
20138 + return GSS_S_UNAVAILABLE;
20141 + if (buffer != GSS_C_NO_BUFFER) {
20143 + buffer->length += vp->length;
20144 + } while (concat && (vp = pairfind(vp->next, attr)) != NULL);
20146 + buffer->value = GSSEAP_MALLOC(buffer->length);
20147 + if (buffer->value == NULL) {
20149 + return GSS_S_FAILURE;
20152 + p = (unsigned char *)buffer->value;
20154 + for (vp = pairfind(vps, attr);
20155 + concat && vp != NULL;
20156 + vp = pairfind(vp->next, attr)) {
20157 + memcpy(p, vp->vp_octets, vp->length);
20163 + return GSS_S_COMPLETE;
20167 +gssEapRadiusFreeAvps(OM_uint32 *minor,
20168 + VALUE_PAIR **vps)
20172 + return GSS_S_COMPLETE;
20176 +gssEapRadiusAttrProviderInit(OM_uint32 *minor)
20178 + if (!gss_eap_radius_attr_provider::init()) {
20179 + *minor = GSSEAP_RADSEC_INIT_FAILURE;
20180 + return GSS_S_FAILURE;
20183 + return GSS_S_COMPLETE;
20187 +gssEapRadiusAttrProviderFinalize(OM_uint32 *minor)
20189 + gss_eap_radius_attr_provider::finalize();
20192 + return GSS_S_COMPLETE;
20196 +avpToJson(const VALUE_PAIR *vp)
20200 + GSSEAP_ASSERT(vp->length <= MAX_STRING_LEN);
20202 + switch (vp->type) {
20203 + case PW_TYPE_INTEGER:
20204 + case PW_TYPE_IPADDR:
20205 + case PW_TYPE_DATE:
20206 + obj.set("value", vp->lvalue);
20208 + case PW_TYPE_STRING:
20209 + obj.set("value", vp->vp_strvalue);
20214 + if (base64Encode(vp->vp_octets, vp->length, &b64) < 0)
20215 + throw std::bad_alloc();
20217 + obj.set("value", b64);
20218 + GSSEAP_FREE(b64);
20223 + obj.set("type", vp->attribute);
20229 +jsonToAvp(VALUE_PAIR **pVp, JSONObject &obj)
20231 + VALUE_PAIR *vp = NULL;
20235 + JSONObject type = obj["type"];
20236 + JSONObject value = obj["value"];
20238 + if (!type.isInteger())
20241 + attrid = type.integer();
20242 + da = dict_attrbyvalue(attrid);
20243 + if (da != NULL) {
20244 + vp = pairalloc(da);
20246 + int type = base64Valid(value.string()) ?
20247 + PW_TYPE_OCTETS : PW_TYPE_STRING;
20248 + vp = paircreate(attrid, type);
20251 + throw std::bad_alloc();
20253 + switch (vp->type) {
20254 + case PW_TYPE_INTEGER:
20255 + case PW_TYPE_IPADDR:
20256 + case PW_TYPE_DATE:
20257 + if (!value.isInteger())
20261 + vp->lvalue = value.integer();
20263 + case PW_TYPE_STRING: {
20264 + if (!value.isString())
20267 + const char *str = value.string();
20268 + size_t len = strlen(str);
20270 + if (len >= MAX_STRING_LEN)
20273 + vp->length = len;
20274 + memcpy(vp->vp_strvalue, str, len + 1);
20277 + case PW_TYPE_OCTETS:
20279 + if (!value.isString())
20282 + const char *str = value.string();
20283 + ssize_t len = strlen(str);
20285 + /* this optimization requires base64Decode only understand packed encoding */
20286 + if (len >= BASE64_EXPAND(MAX_STRING_LEN))
20289 + len = base64Decode(str, vp->vp_octets);
20293 + vp->length = len;
20304 + pairbasicfree(vp);
20310 +gss_eap_radius_attr_provider::name(void) const
20316 +gss_eap_radius_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
20319 + VALUE_PAIR **pNext = &m_vps;
20321 + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
20324 + JSONObject attrs = obj["attributes"];
20325 + size_t nelems = attrs.size();
20327 + for (size_t i = 0; i < nelems; i++) {
20328 + JSONObject attr = attrs[i];
20331 + if (!jsonToAvp(&vp, attr))
20335 + pNext = &vp->next;
20338 + m_authenticated = obj["authenticated"].integer() ? true : false;
20344 +gss_eap_radius_attr_provider::prefix(void) const
20346 + return "urn:ietf:params:gss-eap:radius-avp";
20350 +gss_eap_radius_attr_provider::jsonRepresentation(void) const
20352 + JSONObject obj, attrs = JSONObject::array();
20354 + for (VALUE_PAIR *vp = m_vps; vp != NULL; vp = vp->next) {
20355 + JSONObject attr = avpToJson(vp);
20356 + attrs.append(attr);
20359 + obj.set("attributes", attrs);
20361 + obj.set("authenticated", m_authenticated);
20367 +gss_eap_radius_attr_provider::getExpiryTime(void) const
20371 + vp = pairfind(m_vps, PW_SESSION_TIMEOUT);
20372 + if (vp == NULL || vp->lvalue == 0)
20375 + return time(NULL) + vp->lvalue;
20379 +gssEapRadiusMapError(OM_uint32 *minor,
20380 + struct rs_error *err)
20384 + GSSEAP_ASSERT(err != NULL);
20386 + code = rs_err_code(err, 0);
20388 + if (code == RSE_OK) {
20390 + return GSS_S_COMPLETE;
20393 + *minor = ERROR_TABLE_BASE_rse + code;
20395 + gssEapSaveStatusInfo(*minor, "%s", rs_err_msg(err));
20396 + rs_err_free(err);
20398 + return GSS_S_FAILURE;
20402 +gssEapCreateRadiusContext(OM_uint32 *minor,
20403 + gss_cred_id_t cred,
20404 + struct rs_context **pRadContext)
20406 + const char *configFile = RS_CONFIG_FILE;
20407 + struct rs_context *radContext;
20408 + struct rs_alloc_scheme ralloc;
20409 + struct rs_error *err;
20412 + *pRadContext = NULL;
20414 + if (rs_context_create(&radContext) != 0) {
20415 + *minor = GSSEAP_RADSEC_CONTEXT_FAILURE;
20416 + return GSS_S_FAILURE;
20419 + if (cred->radiusConfigFile.value != NULL)
20420 + configFile = (const char *)cred->radiusConfigFile.value;
20422 + ralloc.calloc = GSSEAP_CALLOC;
20423 + ralloc.malloc = GSSEAP_MALLOC;
20424 + ralloc.free = GSSEAP_FREE;
20425 + ralloc.realloc = GSSEAP_REALLOC;
20427 + rs_context_set_alloc_scheme(radContext, &ralloc);
20429 + if (rs_context_read_config(radContext, configFile) != 0) {
20430 + err = rs_err_ctx_pop(radContext);
20434 + if (rs_context_init_freeradius_dict(radContext, NULL) != 0) {
20435 + err = rs_err_ctx_pop(radContext);
20439 + *pRadContext = radContext;
20442 + return GSS_S_COMPLETE;
20445 + major = gssEapRadiusMapError(minor, err);
20446 + rs_context_destroy(radContext);
20450 diff --git a/mech_eap/util_radius.h b/mech_eap/util_radius.h
20451 new file mode 100644
20452 index 0000000..481876a
20454 +++ b/mech_eap/util_radius.h
20457 + * Copyright (c) 2011, JANET(UK)
20458 + * All rights reserved.
20460 + * Redistribution and use in source and binary forms, with or without
20461 + * modification, are permitted provided that the following conditions
20464 + * 1. Redistributions of source code must retain the above copyright
20465 + * notice, this list of conditions and the following disclaimer.
20467 + * 2. Redistributions in binary form must reproduce the above copyright
20468 + * notice, this list of conditions and the following disclaimer in the
20469 + * documentation and/or other materials provided with the distribution.
20471 + * 3. Neither the name of JANET(UK) nor the names of its contributors
20472 + * may be used to endorse or promote products derived from this software
20473 + * without specific prior written permission.
20475 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20476 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20477 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20478 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20479 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20480 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20481 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20482 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20483 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20484 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20489 + * RADIUS attribute provider.
20492 +#ifndef _UTIL_RADIUS_H_
20493 +#define _UTIL_RADIUS_H_ 1
20495 +#ifdef __cplusplus
20497 +struct gss_eap_radius_attr_provider : gss_eap_attr_provider {
20499 + gss_eap_radius_attr_provider(void);
20500 + ~gss_eap_radius_attr_provider(void);
20502 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
20503 + const gss_eap_attr_provider *ctx);
20504 + bool initWithGssContext(const gss_eap_attr_ctx *source,
20505 + const gss_cred_id_t cred,
20506 + const gss_ctx_id_t ctx);
20508 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
20509 + bool setAttribute(int complete,
20510 + const gss_buffer_t attr,
20511 + const gss_buffer_t value);
20512 + bool deleteAttribute(const gss_buffer_t attr);
20513 + bool getAttribute(const gss_buffer_t attr,
20514 + int *authenticated,
20516 + gss_buffer_t value,
20517 + gss_buffer_t display_value,
20518 + int *more) const;
20519 + gss_any_t mapToAny(int authenticated,
20520 + gss_buffer_t type_id) const;
20521 + void releaseAnyNameMapping(gss_buffer_t type_id,
20522 + gss_any_t input) const;
20524 + const char *prefix(void) const;
20525 + const char *name(void) const;
20526 + bool initWithJsonObject(const gss_eap_attr_ctx *manager,
20527 + JSONObject &obj);
20528 + JSONObject jsonRepresentation(void) const;
20530 + bool getAttribute(uint32_t attribute,
20531 + int *authenticated,
20533 + gss_buffer_t value,
20534 + gss_buffer_t display_value,
20535 + int *more) const;
20536 + bool getAttribute(uint16_t attribute,
20538 + int *authenticated,
20540 + gss_buffer_t value,
20541 + gss_buffer_t display_value,
20542 + int *more) const;
20543 + bool setAttribute(int complete,
20544 + uint32_t attribute,
20545 + const gss_buffer_t value);
20546 + bool deleteAttribute(uint32_t attribute);
20548 + bool getFragmentedAttribute(uint16_t attribute,
20550 + int *authenticated,
20552 + gss_buffer_t value) const;
20553 + bool getFragmentedAttribute(uint32_t attrid,
20554 + int *authenticated,
20556 + gss_buffer_t value) const;
20558 + bool authenticated(void) const { return m_authenticated; }
20560 + time_t getExpiryTime(void) const;
20562 + static bool init(void);
20563 + static void finalize(void);
20565 + static gss_eap_attr_provider *createAttrContext(void);
20568 + const VALUE_PAIR *getAvps(void) const {
20572 + VALUE_PAIR *m_vps;
20573 + bool m_authenticated;
20581 +gssEapRadiusAddAvp(OM_uint32 *minor,
20585 + const gss_buffer_t buffer);
20588 +gssEapRadiusGetAvp(OM_uint32 *minor,
20592 + gss_buffer_t buffer,
20596 +gssEapRadiusGetRawAvp(OM_uint32 *minor,
20600 + VALUE_PAIR **vp);
20602 +gssEapRadiusFreeAvps(OM_uint32 *minor,
20603 + VALUE_PAIR **vps);
20605 +OM_uint32 gssEapRadiusAttrProviderInit(OM_uint32 *minor);
20606 +OM_uint32 gssEapRadiusAttrProviderFinalize(OM_uint32 *minor);
20609 +gssEapRadiusMapError(OM_uint32 *minor,
20610 + struct rs_error *err);
20613 +gssEapCreateRadiusContext(OM_uint32 *minor,
20614 + gss_cred_id_t cred,
20615 + struct rs_context **pRadContext);
20617 +/* This really needs to be a function call on Windows */
20618 +#define RS_CONFIG_FILE SYSCONFDIR "/radsec.conf"
20620 +#define VENDORPEC_MS 311 /* RFC 2548 */
20622 +#define PW_MS_MPPE_SEND_KEY 16
20623 +#define PW_MS_MPPE_RECV_KEY 17
20625 +#define VENDORPEC_UKERNA 25622
20627 +#define PW_GSS_ACCEPTOR_SERVICE_NAME 128
20628 +#define PW_GSS_ACCEPTOR_HOST_NAME 129
20629 +#define PW_GSS_ACCEPTOR_SERVICE_SPECIFIC 130
20630 +#define PW_GSS_ACCEPTOR_REALM_NAME 131
20631 +#define PW_SAML_AAA_ASSERTION 132
20632 +#define PW_MS_WINDOWS_AUTH_DATA 133
20634 +#ifdef __cplusplus
20638 +#endif /* _UTIL_RADIUS_H_ */
20639 diff --git a/mech_eap/util_reauth.c b/mech_eap/util_reauth.c
20640 new file mode 100644
20641 index 0000000..50011ca
20643 +++ b/mech_eap/util_reauth.c
20646 + * Copyright (c) 2011, JANET(UK)
20647 + * All rights reserved.
20649 + * Redistribution and use in source and binary forms, with or without
20650 + * modification, are permitted provided that the following conditions
20653 + * 1. Redistributions of source code must retain the above copyright
20654 + * notice, this list of conditions and the following disclaimer.
20656 + * 2. Redistributions in binary form must reproduce the above copyright
20657 + * notice, this list of conditions and the following disclaimer in the
20658 + * documentation and/or other materials provided with the distribution.
20660 + * 3. Neither the name of JANET(UK) nor the names of its contributors
20661 + * may be used to endorse or promote products derived from this software
20662 + * without specific prior written permission.
20664 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20665 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20666 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20667 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20668 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20669 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20670 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20671 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20672 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
20673 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20678 + * Fast reauthentication support.
20681 +#include "gssapiP_eap.h"
20683 +#include <dlfcn.h>
20686 + * Fast reauthentication support for EAP GSS.
20690 +krb5_encrypt_tkt_part(krb5_context, const krb5_keyblock *, krb5_ticket *);
20693 +encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code);
20696 +gssDisplayName(OM_uint32 *minor,
20698 + gss_buffer_t buffer,
20699 + gss_OID *name_type);
20702 +gssImportName(OM_uint32 *minor,
20703 + gss_buffer_t buffer,
20704 + gss_OID name_type,
20705 + gss_name_t *name);
20707 +static krb5_error_code
20708 +getAcceptorKey(krb5_context krbContext,
20709 + gss_ctx_id_t ctx,
20710 + gss_cred_id_t cred,
20711 + krb5_principal *princ,
20712 + krb5_keyblock *key)
20714 + krb5_error_code code;
20715 + krb5_keytab keytab = NULL;
20716 + krb5_keytab_entry ktent = { 0 };
20717 + krb5_kt_cursor cursor;
20720 + memset(key, 0, sizeof(*key));
20721 + memset(&cursor, 0, sizeof(cursor));
20723 + code = krb5_kt_default(krbContext, &keytab);
20727 + if (cred != GSS_C_NO_CREDENTIAL && cred->name != GSS_C_NO_NAME) {
20728 + code = krb5_kt_get_entry(krbContext, keytab,
20729 + cred->name->krbPrincipal, 0,
20730 + ctx->encryptionType, &ktent);
20735 + * It's not clear that looking encrypting the ticket in the
20736 + * requested EAP enctype provides any value.
20738 + code = krb5_kt_start_seq_get(krbContext, keytab, &cursor);
20742 + while ((code = krb5_kt_next_entry(krbContext, keytab,
20743 + &ktent, &cursor)) == 0) {
20744 + if (KRB_KEY_TYPE(KRB_KT_ENT_KEYBLOCK(&ktent)) == ctx->encryptionType)
20747 + KRB_KT_ENT_FREE(krbContext, &ktent);
20752 + *princ = ktent.principal;
20753 + *key = *KRB_KT_ENT_KEYBLOCK(&ktent);
20757 + if (cred == GSS_C_NO_CREDENTIAL || cred->name == GSS_C_NO_NAME)
20758 + krb5_kt_end_seq_get(krbContext, keytab, &cursor);
20759 + krb5_kt_close(krbContext, keytab);
20761 + KRB_KT_ENT_FREE(krbContext, &ktent);
20767 +freezeAttrContext(OM_uint32 *minor,
20768 + gss_name_t initiatorName,
20769 + krb5_const_principal acceptorPrinc,
20770 + krb5_keyblock *session,
20771 +#ifdef HAVE_HEIMDAL_VERSION
20772 + krb5_authdata *kdcIssuedAuthData
20774 + krb5_authdata ***kdcIssuedAuthData
20778 + OM_uint32 major, tmpMinor;
20779 + krb5_error_code code;
20780 + krb5_context krbContext;
20781 + gss_buffer_desc attrBuf = GSS_C_EMPTY_BUFFER;
20782 +#ifdef HAVE_HEIMDAL_VERSION
20783 + krb5_authdata authDataBuf, *authData = &authDataBuf;
20784 + AuthorizationDataElement authDatum = { 0 };
20786 + krb5_authdata *authData[2], authDatum = { 0 };
20789 + memset(kdcIssuedAuthData, 0, sizeof(*kdcIssuedAuthData));
20791 + GSSEAP_KRB_INIT(&krbContext);
20793 + major = gssEapExportAttrContext(minor, initiatorName, &attrBuf);
20794 + if (GSS_ERROR(major))
20797 + authDatum.ad_type = KRB5_AUTHDATA_RADIUS_AVP;
20798 +#ifdef HAVE_HEIMDAL_VERSION
20799 + authDatum.ad_data.length = attrBuf.length;
20800 + authDatum.ad_data.data = attrBuf.value;
20801 + authData->len = 1;
20802 + authData->val = &authDatum;
20804 + authDatum.length = attrBuf.length;
20805 + authDatum.contents = attrBuf.value;
20806 + authData[0] = &authDatum;
20807 + authData[1] = NULL;
20810 + code = krbMakeAuthDataKdcIssued(krbContext, session, acceptorPrinc,
20811 + authData, kdcIssuedAuthData);
20813 + major = GSS_S_FAILURE;
20816 + major = GSS_S_COMPLETE;
20819 + gss_release_buffer(&tmpMinor, &attrBuf);
20825 + * Fabricate a ticket to ourselves given a GSS EAP context.
20828 +gssEapMakeReauthCreds(OM_uint32 *minor,
20829 + gss_ctx_id_t ctx,
20830 + gss_cred_id_t cred,
20831 + gss_buffer_t credBuf)
20833 + OM_uint32 major = GSS_S_COMPLETE;
20834 + krb5_error_code code;
20835 + krb5_context krbContext = NULL;
20836 + krb5_keyblock session = { 0 }, acceptorKey = { 0 };
20837 + krb5_principal server = NULL;
20838 +#ifdef HAVE_HEIMDAL_VERSION
20840 + EncTicketPart enc_part;
20841 + AuthorizationData authData = { 0 };
20842 + krb5_crypto krbCrypto = NULL;
20843 + krb5_data ticketData = { 0 };
20844 + krb5_data encPartData = { 0 };
20847 + krb5_ticket ticket;
20848 + krb5_enc_tkt_part enc_part;
20849 + krb5_data *ticketData = NULL;
20851 + krb5_data credsData = { 0 };
20852 + krb5_creds creds = { 0 };
20853 + krb5_auth_context authContext = NULL;
20855 + memset(&ticket, 0, sizeof(ticket));
20856 + memset(&enc_part, 0, sizeof(enc_part));
20858 + credBuf->length = 0;
20859 + credBuf->value = NULL;
20861 + GSSEAP_KRB_INIT(&krbContext);
20863 + code = getAcceptorKey(krbContext, ctx, cred, &server, &acceptorKey);
20866 + return GSS_S_UNAVAILABLE;
20870 + * Generate a random session key to place in the ticket and
20871 + * sign the "KDC-Issued" authorization data element.
20873 +#ifdef HAVE_HEIMDAL_VERSION
20874 + ticket.realm = server->realm;
20875 + ticket.sname = server->name;
20877 + code = krb5_generate_random_keyblock(krbContext, ctx->encryptionType,
20882 + enc_part.flags.initial = 1;
20883 + enc_part.key = session;
20884 + enc_part.crealm = ctx->initiatorName->krbPrincipal->realm;
20885 + enc_part.cname = ctx->initiatorName->krbPrincipal->name;
20886 + enc_part.authtime = time(NULL);
20887 + enc_part.starttime = &enc_part.authtime;
20888 + enc_part.endtime = (ctx->expiryTime != 0)
20889 + ? ctx->expiryTime : KRB_TIME_FOREVER;
20890 + enc_part.renew_till = NULL;
20891 + enc_part.authorization_data = &authData;
20893 + major = freezeAttrContext(minor, ctx->initiatorName, server,
20894 + &session, &authData);
20895 + if (GSS_ERROR(major))
20898 + ASN1_MALLOC_ENCODE(EncTicketPart, encPartData.data, encPartData.length,
20899 + &enc_part, &len, code);
20903 + code = krb5_crypto_init(krbContext, &acceptorKey, 0, &krbCrypto);
20907 + code = krb5_encrypt_EncryptedData(krbContext,
20910 + encPartData.data,
20911 + encPartData.length,
20913 + &ticket.enc_part);
20917 + ASN1_MALLOC_ENCODE(Ticket, ticketData.data, ticketData.length,
20918 + &ticket, &len, code);
20922 + ticket.server = server;
20924 + code = krb5_c_make_random_key(krbContext, ctx->encryptionType,
20929 + enc_part.flags = TKT_FLG_INITIAL;
20930 + enc_part.session = &session;
20931 + enc_part.client = ctx->initiatorName->krbPrincipal;
20932 + enc_part.times.authtime = time(NULL);
20933 + enc_part.times.starttime = enc_part.times.authtime;
20934 + enc_part.times.endtime = (ctx->expiryTime != 0)
20935 + ? ctx->expiryTime
20936 + : KRB_TIME_FOREVER;
20937 + enc_part.times.renew_till = 0;
20939 + major = freezeAttrContext(minor, ctx->initiatorName, server,
20940 + &session, &enc_part.authorization_data);
20941 + if (GSS_ERROR(major))
20944 + ticket.enc_part2 = &enc_part;
20946 + code = krb5_encrypt_tkt_part(krbContext, &acceptorKey, &ticket);
20950 + code = encode_krb5_ticket(&ticket, &ticketData);
20953 +#endif /* HAVE_HEIMDAL_VERSION */
20955 + creds.client = ctx->initiatorName->krbPrincipal;
20956 + creds.server = server;
20957 +#ifdef HAVE_HEIMDAL_VERSION
20958 + creds.session = session;
20959 + creds.times.authtime = enc_part.authtime;
20960 + creds.times.starttime = *enc_part.starttime;
20961 + creds.times.endtime = enc_part.endtime;
20962 + creds.times.renew_till = 0;
20963 + creds.flags.b = enc_part.flags;
20964 + creds.ticket = ticketData;
20965 + creds.authdata = authData;
20967 + creds.keyblock = session;
20968 + creds.times = enc_part.times;
20969 + creds.ticket_flags = enc_part.flags;
20970 + creds.ticket = *ticketData;
20971 + creds.authdata = enc_part.authorization_data;
20974 + code = krb5_auth_con_init(krbContext, &authContext);
20978 + code = krb5_auth_con_setflags(krbContext, authContext, 0);
20982 +#ifdef HAVE_HEIMDAL_VERSION
20983 + code = krb5_auth_con_setlocalsubkey(krbContext, authContext,
20984 + &ctx->rfc3961Key);
20986 + code = krb5_auth_con_setsendsubkey(krbContext, authContext,
20987 + &ctx->rfc3961Key);
20992 + code = krbMakeCred(krbContext, authContext, &creds, &credsData);
20996 + krbDataToGssBuffer(&credsData, credBuf);
20999 +#ifdef HAVE_HEIMDAL_VERSION
21000 + if (krbCrypto != NULL)
21001 + krb5_crypto_destroy(krbContext, krbCrypto);
21002 + free_AuthorizationData(&authData);
21003 + free_EncryptedData(&ticket.enc_part);
21004 + krb5_data_free(&ticketData);
21005 + krb5_data_free(&encPartData);
21007 + krb5_free_authdata(krbContext, enc_part.authorization_data);
21008 + if (ticket.enc_part.ciphertext.data != NULL)
21009 + GSSEAP_FREE(ticket.enc_part.ciphertext.data);
21010 + krb5_free_data(krbContext, ticketData);
21012 + krb5_free_keyblock_contents(krbContext, &session);
21013 + krb5_free_principal(krbContext, server);
21014 + krb5_free_keyblock_contents(krbContext, &acceptorKey);
21015 + krb5_auth_con_free(krbContext, authContext);
21017 + if (major == GSS_S_COMPLETE) {
21019 + major = (code != 0) ? GSS_S_FAILURE : GSS_S_COMPLETE;
21026 +isTicketGrantingServiceP(krb5_context krbContext GSSEAP_UNUSED,
21027 + krb5_const_principal principal)
21029 + if (KRB_PRINC_LENGTH(principal) == 2 &&
21030 +#ifdef HAVE_HEIMDAL_VERSION
21031 + strcmp(KRB_PRINC_NAME(principal)[0], "krbtgt") == 0
21033 + krb5_princ_component(krbContext, principal, 0)->length == 6 &&
21034 + memcmp(krb5_princ_component(krbContext,
21035 + principal, 0)->data, "krbtgt", 6) == 0
21044 + * Returns TRUE if the configuration variable reauth_use_ccache is
21045 + * set in krb5.conf for the eap_gss application and the client realm.
21048 +reauthUseCredsCache(krb5_context krbContext,
21049 + krb5_principal principal)
21051 + int reauthUseCCache;
21053 + /* if reauth_use_ccache, use default credentials cache if ticket is for us */
21054 + krb5_appdefault_boolean(krbContext, "eap_gss",
21055 + KRB_PRINC_REALM(principal),
21056 + "reauth_use_ccache", 0, &reauthUseCCache);
21058 + return reauthUseCCache;
21062 + * Look in default credentials cache for reauthentication credentials,
21063 + * if policy allows.
21066 +getDefaultReauthCredentials(OM_uint32 *minor,
21067 + gss_cred_id_t cred,
21068 + gss_name_t target,
21070 + OM_uint32 timeReq)
21072 + OM_uint32 major = GSS_S_CRED_UNAVAIL;
21073 + krb5_context krbContext = NULL;
21074 + krb5_error_code code = 0;
21075 + krb5_ccache ccache = NULL;
21076 + krb5_creds match = { 0 };
21077 + krb5_creds creds = { 0 };
21079 + GSSEAP_KRB_INIT(&krbContext);
21081 + GSSEAP_ASSERT(cred != GSS_C_NO_CREDENTIAL);
21082 + GSSEAP_ASSERT(target != GSS_C_NO_NAME);
21084 + if (cred->name == GSS_C_NO_NAME ||
21085 + !reauthUseCredsCache(krbContext, cred->name->krbPrincipal))
21088 + match.client = cred->name->krbPrincipal;
21089 + match.server = target->krbPrincipal;
21090 + if (timeReq != 0 && timeReq != GSS_C_INDEFINITE)
21091 + match.times.endtime = now + timeReq;
21093 + code = krb5_cc_default(krbContext, &ccache);
21097 + code = krb5_cc_retrieve_cred(krbContext, ccache, 0, &match, &creds);
21101 + cred->flags |= CRED_FLAG_DEFAULT_CCACHE;
21102 + cred->krbCredCache = ccache;
21105 + major = gss_krb5_import_cred(minor, cred->krbCredCache, NULL, NULL,
21106 + &cred->reauthCred);
21109 + if (major == GSS_S_CRED_UNAVAIL)
21112 + if (ccache != NULL)
21113 + krb5_cc_close(krbContext, ccache);
21114 + krb5_free_cred_contents(krbContext, &creds);
21120 + * Returns TRUE if the credential handle's reauth credentials are
21121 + * valid or if we can use the default credentials cache. Credentials
21122 + * handle must be locked.
21125 +gssEapCanReauthP(gss_cred_id_t cred,
21126 + gss_name_t target,
21127 + OM_uint32 timeReq)
21129 + time_t now, expiryReq;
21132 + if (cred == GSS_C_NO_CREDENTIAL)
21135 + now = time(NULL);
21137 + if (timeReq != GSS_C_INDEFINITE)
21138 + expiryReq += timeReq;
21140 + if (cred->krbCredCache != NULL && cred->expiryTime > expiryReq)
21143 + if (getDefaultReauthCredentials(&minor, cred, target,
21144 + now, timeReq) == GSS_S_COMPLETE)
21151 + * Store re-authentication (Kerberos) credentials in a credential handle.
21152 + * Credentials handle must be locked.
21155 +gssEapStoreReauthCreds(OM_uint32 *minor,
21156 + gss_ctx_id_t ctx,
21157 + gss_cred_id_t cred,
21158 + gss_buffer_t credBuf)
21160 + OM_uint32 major = GSS_S_COMPLETE;
21161 + krb5_error_code code;
21162 + krb5_context krbContext = NULL;
21163 + krb5_auth_context authContext = NULL;
21164 + krb5_data credData = { 0 };
21165 + krb5_creds **creds = NULL;
21166 + krb5_principal canonPrinc;
21167 + krb5_principal ccPrinc = NULL;
21170 + if (credBuf->length == 0 || cred == GSS_C_NO_CREDENTIAL)
21171 + return GSS_S_COMPLETE;
21173 + GSSEAP_KRB_INIT(&krbContext);
21175 + code = krb5_auth_con_init(krbContext, &authContext);
21179 + code = krb5_auth_con_setflags(krbContext, authContext, 0);
21183 + code = krb5_auth_con_setrecvsubkey(krbContext, authContext,
21184 + &ctx->rfc3961Key);
21188 + gssBufferToKrbData(credBuf, &credData);
21190 + code = krb5_rd_cred(krbContext, authContext, &credData, &creds, NULL);
21194 + if (creds == NULL || creds[0] == NULL)
21197 + code = krb5_copy_principal(krbContext, creds[0]->client, &canonPrinc);
21201 + krb5_free_principal(krbContext, cred->name->krbPrincipal);
21202 + cred->name->krbPrincipal = canonPrinc;
21204 + if (creds[0]->times.endtime == KRB_TIME_FOREVER)
21205 + cred->expiryTime = 0;
21207 + cred->expiryTime = creds[0]->times.endtime;
21209 + if (cred->krbCredCache == NULL) {
21210 + if (reauthUseCredsCache(krbContext, creds[0]->client) &&
21211 + krb5_cc_default(krbContext, &cred->krbCredCache) == 0)
21212 + cred->flags |= CRED_FLAG_DEFAULT_CCACHE;
21215 + * If we already have an associated credentials cache, possibly from
21216 + * the last time we stored a reauthentication credential, then we
21217 + * need to clear it out and release the associated GSS credential.
21219 + if (cred->flags & CRED_FLAG_DEFAULT_CCACHE) {
21220 + krb5_cc_remove_cred(krbContext, cred->krbCredCache, 0, creds[0]);
21222 + krb5_cc_destroy(krbContext, cred->krbCredCache);
21223 + cred->krbCredCache = NULL;
21225 + gssReleaseCred(minor, &cred->reauthCred);
21228 + if (cred->krbCredCache == NULL) {
21229 + code = krb5_cc_new_unique(krbContext, "MEMORY", NULL, &cred->krbCredCache);
21234 + if ((cred->flags & CRED_FLAG_DEFAULT_CCACHE) == 0 ||
21235 + krb5_cc_get_principal(krbContext, cred->krbCredCache, &ccPrinc) != 0) {
21236 + code = krb5_cc_initialize(krbContext, cred->krbCredCache,
21237 + creds[0]->client);
21242 + for (i = 0; creds[i] != NULL; i++) {
21243 + krb5_creds kcred = *(creds[i]);
21246 + * Swap in the acceptor name the client asked for so
21247 + * get_credentials() works. We're making the assumption that
21248 + * any service tickets returned are for us. We'll need to
21249 + * reflect some more on whether that is a safe assumption.
21251 + if (!isTicketGrantingServiceP(krbContext, kcred.server))
21252 + kcred.server = ctx->acceptorName->krbPrincipal;
21254 + code = krb5_cc_store_cred(krbContext, cred->krbCredCache, &kcred);
21259 + major = gss_krb5_import_cred(minor, cred->krbCredCache, NULL, NULL,
21260 + &cred->reauthCred);
21261 + if (GSS_ERROR(major))
21267 + krb5_free_principal(krbContext, ccPrinc);
21268 + krb5_auth_con_free(krbContext, authContext);
21269 + if (creds != NULL) {
21270 + for (i = 0; creds[i] != NULL; i++)
21271 + krb5_free_creds(krbContext, creds[i]);
21272 + GSSEAP_FREE(creds);
21274 + if (major == GSS_S_COMPLETE)
21275 + major = *minor ? GSS_S_FAILURE : GSS_S_COMPLETE;
21280 +#ifndef HAVE_HEIMDAL_VERSION
21281 +static gss_buffer_desc radiusAvpKrbAttr = {
21282 + sizeof("urn:authdata-radius-avp") - 1, "urn:authdata-radius-avp"
21287 + * Unfortunately extracting an AD-KDCIssued authorization data element
21288 + * is pretty implementation-dependent. It's not possible to verify the
21289 + * signature ourselves because the ticket session key is not exposed
21290 + * outside GSS. In an ideal world, all AD-KDCIssued elements would be
21291 + * verified by the Kerberos library and authentication would fail if
21292 + * verification failed. We're not quite there yet and as a result have
21293 + * to go through some hoops to get this to work. The alternative would
21294 + * be to sign the authorization data with our long-term key, but it
21295 + * seems a pity to compromise the design because of current implementation
21298 + * (Specifically, the hoops involve a libkrb5 authorisation data plugin
21299 + * that exposes the verified and serialised attribute context through
21300 + * the Kerberos GSS mechanism's naming extensions API.)
21303 +defrostAttrContext(OM_uint32 *minor,
21304 +#ifdef HAVE_HEIMDAL_VERSION
21305 + gss_ctx_id_t glueContext,
21307 + gss_name_t glueName,
21309 + gss_name_t mechName)
21311 + OM_uint32 major, tmpMinor;
21312 +#ifdef HAVE_HEIMDAL_VERSION
21313 + gss_OID_desc oid = { 0 };
21314 + gss_buffer_set_t authData = GSS_C_NO_BUFFER_SET;
21316 + gss_buffer_desc authData = GSS_C_EMPTY_BUFFER;
21317 + gss_buffer_desc authDataDisplay = GSS_C_EMPTY_BUFFER;
21319 + int authenticated, complete;
21322 +#ifdef HAVE_HEIMDAL_VERSION
21323 + major = composeOid(minor,
21324 + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
21325 + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
21326 + KRB5_AUTHDATA_RADIUS_AVP, &oid);
21327 + if (GSS_ERROR(major))
21330 + /* XXX we are assuming that this verifies AD-KDCIssued signature */
21331 + major = gssInquireSecContextByOid(minor, glueContext,
21332 + &oid, &authData);
21333 + if (major == GSS_S_COMPLETE) {
21334 + if (authData == GSS_C_NO_BUFFER_SET || authData->count != 1)
21335 + major = GSS_S_FAILURE;
21337 + major = gssEapImportAttrContext(minor, authData->elements, mechName);
21338 + } else if (major == GSS_S_FAILURE && *minor == ENOENT) {
21339 + /* This is the equivalent of GSS_S_UNAVAILABLE for MIT attr APIs */
21341 + major = GSS_S_COMPLETE;
21344 + gss_release_buffer_set(&tmpMinor, &authData);
21345 + GSSEAP_FREE(oid.elements);
21347 + major = gssGetNameAttribute(minor, glueName, &radiusAvpKrbAttr,
21348 + &authenticated, &complete,
21349 + &authData, &authDataDisplay, &more);
21350 + if (major == GSS_S_COMPLETE) {
21351 + if (authenticated == 0)
21352 + major = GSS_S_BAD_NAME;
21354 + major = gssEapImportAttrContext(minor, &authData, mechName);
21355 + } else if (major == GSS_S_UNAVAILABLE) {
21356 + major = GSS_S_COMPLETE;
21359 + gss_release_buffer(&tmpMinor, &authData);
21360 + gss_release_buffer(&tmpMinor, &authDataDisplay);
21361 +#endif /* HAVE_HEIMDAL_VERSION */
21367 + * Convert a mechanism glue to an EAP mechanism name by displaying and
21368 + * importing it. This also handles the RADIUS attributes.
21371 +gssEapGlueToMechName(OM_uint32 *minor,
21372 + gss_ctx_id_t ctx,
21373 + gss_name_t glueName,
21374 + gss_name_t *pMechName)
21376 + OM_uint32 major, tmpMinor;
21377 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
21379 + *pMechName = GSS_C_NO_NAME;
21381 + major = gssDisplayName(minor, glueName, &nameBuf, NULL);
21382 + if (GSS_ERROR(major))
21385 + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
21386 + ctx->mechanismUsed, pMechName);
21387 + if (GSS_ERROR(major))
21390 + major = defrostAttrContext(minor,
21391 +#ifdef HAVE_HEIMDAL_VERSION
21397 + if (GSS_ERROR(major))
21401 + if (GSS_ERROR(major)) {
21402 + gssReleaseName(&tmpMinor, pMechName);
21403 + *pMechName = GSS_C_NO_NAME;
21406 + gss_release_buffer(&tmpMinor, &nameBuf);
21412 + * Convert an EAP mechanism name to a mechanism glue name by displaying
21413 + * and importing it.
21416 +gssEapMechToGlueName(OM_uint32 *minor,
21417 + gss_name_t mechName,
21418 + gss_name_t *pGlueName)
21420 + OM_uint32 major, tmpMinor;
21421 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
21423 + *pGlueName = GSS_C_NO_NAME;
21425 + major = gssEapDisplayName(minor, mechName, &nameBuf, NULL);
21426 + if (GSS_ERROR(major))
21429 + major = gssImportName(minor, &nameBuf, GSS_C_NT_USER_NAME,
21431 + if (GSS_ERROR(major))
21435 + gss_release_buffer(&tmpMinor, &nameBuf);
21441 + * Suck out the analgous elements of a Kerberos GSS context into an EAP
21442 + * one so that the application doesn't know the difference.
21445 +gssEapReauthComplete(OM_uint32 *minor,
21446 + gss_ctx_id_t ctx,
21447 + gss_cred_id_t cred GSSEAP_UNUSED,
21448 + const gss_OID mech,
21449 + OM_uint32 timeRec)
21451 + OM_uint32 major, tmpMinor;
21452 + gss_buffer_set_t keyData = GSS_C_NO_BUFFER_SET;
21453 + krb5_context krbContext = NULL;
21454 +#ifdef HAVE_HEIMDAL_VERSION
21455 + krb5_storage *sp = NULL;
21458 + GSSEAP_KRB_INIT(&krbContext);
21460 + if (!oidEqual(mech, gss_mech_krb5)) {
21461 + major = GSS_S_BAD_MECH;
21465 + /* Get the raw subsession key and encryption type */
21466 +#ifdef HAVE_HEIMDAL_VERSION
21467 +#define KRB_GSS_SUBKEY_COUNT 1 /* encoded session key */
21468 + major = gssInquireSecContextByOid(minor, ctx->reauthCtx,
21469 + GSS_KRB5_GET_SUBKEY_X, &keyData);
21471 +#define KRB_GSS_SUBKEY_COUNT 2 /* raw session key, enctype OID */
21472 + major = gssInquireSecContextByOid(minor, ctx->reauthCtx,
21473 + GSS_C_INQ_SSPI_SESSION_KEY, &keyData);
21475 + if (GSS_ERROR(major))
21478 + if (keyData == GSS_C_NO_BUFFER_SET || keyData->count < KRB_GSS_SUBKEY_COUNT) {
21479 + *minor = GSSEAP_KEY_UNAVAILABLE;
21480 + major = GSS_S_FAILURE;
21484 +#ifdef HAVE_HEIMDAL_VERSION
21485 + sp = krb5_storage_from_mem(keyData->elements[0].value,
21486 + keyData->elements[0].length);
21487 + if (sp == NULL) {
21489 + major = GSS_S_FAILURE;
21493 + *minor = krb5_ret_keyblock(sp, &ctx->rfc3961Key);
21494 + if (*minor != 0) {
21495 + major = GSS_S_FAILURE;
21500 + gss_OID_desc oid;
21503 + oid.length = keyData->elements[1].length;
21504 + oid.elements = keyData->elements[1].value;
21506 + /* GSS_KRB5_SESSION_KEY_ENCTYPE_OID */
21507 + major = decomposeOid(minor,
21508 + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04",
21509 + 10, &oid, &suffix);
21510 + if (GSS_ERROR(major))
21513 + ctx->encryptionType = suffix;
21517 + krb5_keyblock key;
21519 + KRB_KEY_LENGTH(&key) = keyData->elements[0].length;
21520 + KRB_KEY_DATA(&key) = keyData->elements[0].value;
21521 + KRB_KEY_TYPE(&key) = ctx->encryptionType;
21523 + *minor = krb5_copy_keyblock_contents(krbContext,
21524 + &key, &ctx->rfc3961Key);
21525 + if (*minor != 0) {
21526 + major = GSS_S_FAILURE;
21530 +#endif /* HAVE_HEIMDAL_VERSION */
21532 + major = rfc3961ChecksumTypeForKey(minor, &ctx->rfc3961Key,
21533 + &ctx->checksumType);
21534 + if (GSS_ERROR(major))
21537 + if (timeRec != GSS_C_INDEFINITE)
21538 + ctx->expiryTime = time(NULL) + timeRec;
21540 + /* Initialize our sequence state */
21541 + major = sequenceInit(minor,
21542 + &ctx->seqState, ctx->recvSeq,
21543 + ((ctx->gssFlags & GSS_C_REPLAY_FLAG) != 0),
21544 + ((ctx->gssFlags & GSS_C_SEQUENCE_FLAG) != 0),
21546 + if (GSS_ERROR(major))
21549 + major = GSS_S_COMPLETE;
21552 +#ifdef HAVE_HEIMDAL_VERSION
21554 + krb5_storage_free(sp);
21556 + gss_release_buffer_set(&tmpMinor, &keyData);
21562 + * The remainder of this file consists of wrappers so we can call into the
21563 + * mechanism glue without calling ourselves.
21566 +(*gssInitSecContextNext)(OM_uint32 *,
21573 + gss_channel_bindings_t,
21581 +(*gssAcceptSecContextNext)(OM_uint32 *,
21585 + gss_channel_bindings_t,
21591 + gss_cred_id_t *);
21594 +(*gssReleaseCredNext)(OM_uint32 *, gss_cred_id_t *);
21597 +(*gssReleaseNameNext)(OM_uint32 *, gss_name_t *);
21600 +(*gssInquireSecContextByOidNext)(OM_uint32 *,
21601 + const gss_ctx_id_t,
21603 + gss_buffer_set_t *);
21606 +(*gssDeleteSecContextNext)(OM_uint32 *,
21611 +(*gssDisplayNameNext)(OM_uint32 *,
21617 +(*gssImportNameNext)(OM_uint32 *,
21623 +(*gssStoreCredNext)(OM_uint32 *,
21624 + const gss_cred_id_t,
21625 + gss_cred_usage_t,
21630 + gss_cred_usage_t *);
21633 +(*gssGetNameAttributeNext)(OM_uint32 *,
21642 +#define NEXT_SYMBOL(local, global) do { \
21643 + ((local) = dlsym(RTLD_NEXT, (global))); \
21644 + if ((local) == NULL) { \
21645 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL; \
21646 + major = GSS_S_UNAVAILABLE; \
21647 + /* but continue */ \
21652 +gssEapReauthInitialize(OM_uint32 *minor)
21654 + OM_uint32 major = GSS_S_COMPLETE;
21656 + NEXT_SYMBOL(gssInitSecContextNext, "gss_init_sec_context");
21657 + NEXT_SYMBOL(gssAcceptSecContextNext, "gss_accept_sec_context");
21658 + NEXT_SYMBOL(gssReleaseCredNext, "gss_release_cred");
21659 + NEXT_SYMBOL(gssReleaseNameNext, "gss_release_name");
21660 + NEXT_SYMBOL(gssInquireSecContextByOidNext, "gss_inquire_sec_context_by_oid");
21661 + NEXT_SYMBOL(gssDeleteSecContextNext, "gss_delete_sec_context");
21662 + NEXT_SYMBOL(gssDisplayNameNext, "gss_display_name");
21663 + NEXT_SYMBOL(gssImportNameNext, "gss_import_name");
21664 + NEXT_SYMBOL(gssStoreCredNext, "gss_store_cred");
21665 +#ifndef HAVE_HEIMDAL_VERSION
21666 + NEXT_SYMBOL(gssGetNameAttributeNext, "gss_get_name_attribute");
21673 +gssInitSecContext(OM_uint32 *minor,
21674 + gss_cred_id_t cred,
21675 + gss_ctx_id_t *context_handle,
21676 + gss_name_t target_name,
21677 + gss_OID mech_type,
21678 + OM_uint32 req_flags,
21679 + OM_uint32 time_req,
21680 + gss_channel_bindings_t input_chan_bindings,
21681 + gss_buffer_t input_token,
21682 + gss_OID *actual_mech_type,
21683 + gss_buffer_t output_token,
21684 + OM_uint32 *ret_flags,
21685 + OM_uint32 *time_rec)
21687 + if (gssInitSecContextNext == NULL) {
21688 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21689 + return GSS_S_UNAVAILABLE;
21692 + return gssInitSecContextNext(minor, cred, context_handle,
21693 + target_name, mech_type, req_flags,
21694 + time_req, input_chan_bindings,
21695 + input_token, actual_mech_type,
21696 + output_token, ret_flags, time_rec);
21700 +gssAcceptSecContext(OM_uint32 *minor,
21701 + gss_ctx_id_t *context_handle,
21702 + gss_cred_id_t cred,
21703 + gss_buffer_t input_token,
21704 + gss_channel_bindings_t input_chan_bindings,
21705 + gss_name_t *src_name,
21706 + gss_OID *mech_type,
21707 + gss_buffer_t output_token,
21708 + OM_uint32 *ret_flags,
21709 + OM_uint32 *time_rec,
21710 + gss_cred_id_t *delegated_cred_handle)
21712 + if (gssAcceptSecContextNext == NULL) {
21713 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21714 + return GSS_S_UNAVAILABLE;
21717 + return gssAcceptSecContextNext(minor, context_handle, cred,
21718 + input_token, input_chan_bindings,
21719 + src_name, mech_type, output_token,
21720 + ret_flags, time_rec, delegated_cred_handle);
21724 +gssReleaseCred(OM_uint32 *minor,
21725 + gss_cred_id_t *cred_handle)
21727 + if (gssReleaseCredNext == NULL) {
21728 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21729 + return GSS_S_UNAVAILABLE;
21732 + return gssReleaseCredNext(minor, cred_handle);
21736 +gssReleaseName(OM_uint32 *minor,
21737 + gss_name_t *name)
21739 + if (gssReleaseName == NULL) {
21740 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21741 + return GSS_S_UNAVAILABLE;
21744 + return gssReleaseNameNext(minor, name);
21748 +gssDeleteSecContext(OM_uint32 *minor,
21749 + gss_ctx_id_t *context_handle,
21750 + gss_buffer_t output_token)
21752 + if (gssDeleteSecContextNext == NULL) {
21753 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21754 + return GSS_S_UNAVAILABLE;
21757 + return gssDeleteSecContextNext(minor, context_handle, output_token);
21761 +gssDisplayName(OM_uint32 *minor,
21763 + gss_buffer_t buffer,
21764 + gss_OID *name_type)
21766 + if (gssDisplayNameNext == NULL) {
21767 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21768 + return GSS_S_UNAVAILABLE;
21771 + return gssDisplayNameNext(minor, name, buffer, name_type);
21775 +gssImportName(OM_uint32 *minor,
21776 + gss_buffer_t buffer,
21777 + gss_OID name_type,
21778 + gss_name_t *name)
21780 + if (gssImportNameNext == NULL) {
21781 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21782 + return GSS_S_UNAVAILABLE;
21785 + return gssImportNameNext(minor, buffer, name_type, name);
21789 +gssInquireSecContextByOid(OM_uint32 *minor,
21790 + const gss_ctx_id_t context_handle,
21791 + const gss_OID desired_object,
21792 + gss_buffer_set_t *data_set)
21794 + if (gssInquireSecContextByOidNext == NULL) {
21795 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21796 + return GSS_S_UNAVAILABLE;
21799 + return gssInquireSecContextByOidNext(minor, context_handle,
21800 + desired_object, data_set);
21804 +gssStoreCred(OM_uint32 *minor,
21805 + const gss_cred_id_t input_cred_handle,
21806 + gss_cred_usage_t input_usage,
21807 + const gss_OID desired_mech,
21808 + OM_uint32 overwrite_cred,
21809 + OM_uint32 default_cred,
21810 + gss_OID_set *elements_stored,
21811 + gss_cred_usage_t *cred_usage_stored)
21813 + if (gssStoreCredNext == NULL) {
21814 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21815 + return GSS_S_UNAVAILABLE;
21818 + return gssStoreCredNext(minor, input_cred_handle, input_usage,
21819 + desired_mech, overwrite_cred, default_cred,
21820 + elements_stored, cred_usage_stored);
21824 +gssGetNameAttribute(OM_uint32 *minor,
21826 + gss_buffer_t attr,
21827 + int *authenticated,
21829 + gss_buffer_t value,
21830 + gss_buffer_t display_value,
21833 + if (gssGetNameAttributeNext == NULL) {
21834 + *minor = GSSEAP_NO_MECHGLUE_SYMBOL;
21835 + return GSS_S_UNAVAILABLE;
21838 + return gssGetNameAttributeNext(minor, name, attr, authenticated, complete,
21839 + value, display_value, more);
21841 diff --git a/mech_eap/util_reauth.h b/mech_eap/util_reauth.h
21842 new file mode 100644
21843 index 0000000..9b9f264
21845 +++ b/mech_eap/util_reauth.h
21848 + * Copyright (c) 2011, JANET(UK)
21849 + * All rights reserved.
21851 + * Redistribution and use in source and binary forms, with or without
21852 + * modification, are permitted provided that the following conditions
21855 + * 1. Redistributions of source code must retain the above copyright
21856 + * notice, this list of conditions and the following disclaimer.
21858 + * 2. Redistributions in binary form must reproduce the above copyright
21859 + * notice, this list of conditions and the following disclaimer in the
21860 + * documentation and/or other materials provided with the distribution.
21862 + * 3. Neither the name of JANET(UK) nor the names of its contributors
21863 + * may be used to endorse or promote products derived from this software
21864 + * without specific prior written permission.
21866 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21867 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21868 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21869 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21870 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21871 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21872 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21873 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21874 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21875 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21880 + * Fast reauthentication support.
21883 +#include "gssapiP_eap.h"
21885 +#ifndef _UTIL_REAUTH_H_
21886 +#define _UTIL_REAUTH_H_ 1
21888 +/* AD element containing serialised AVPs. */
21889 +#define KRB5_AUTHDATA_RADIUS_AVP 513
21892 +gssInitSecContext(OM_uint32 *minor,
21893 + gss_cred_id_t cred,
21894 + gss_ctx_id_t *context_handle,
21895 + gss_name_t target_name,
21896 + gss_OID mech_type,
21897 + OM_uint32 req_flags,
21898 + OM_uint32 time_req,
21899 + gss_channel_bindings_t input_chan_bindings,
21900 + gss_buffer_t input_token,
21901 + gss_OID *actual_mech_type,
21902 + gss_buffer_t output_token,
21903 + OM_uint32 *ret_flags,
21904 + OM_uint32 *time_rec);
21907 +gssAcceptSecContext(OM_uint32 *minor,
21908 + gss_ctx_id_t *context_handle,
21909 + gss_cred_id_t cred,
21910 + gss_buffer_t input_token,
21911 + gss_channel_bindings_t input_chan_bindings,
21912 + gss_name_t *src_name,
21913 + gss_OID *mech_type,
21914 + gss_buffer_t output_token,
21915 + OM_uint32 *ret_flags,
21916 + OM_uint32 *time_rec,
21917 + gss_cred_id_t *delegated_cred_handle);
21920 +gssReleaseCred(OM_uint32 *minor,
21921 + gss_cred_id_t *cred_handle);
21924 +gssReleaseName(OM_uint32 *minor,
21925 + gss_name_t *name);
21928 +gssDeleteSecContext(OM_uint32 *minor,
21929 + gss_ctx_id_t *context_handle,
21930 + gss_buffer_t output_token);
21933 +gssInquireSecContextByOid(OM_uint32 *minor,
21934 + const gss_ctx_id_t context_handle,
21935 + const gss_OID desired_object,
21936 + gss_buffer_set_t *data_set);
21939 +gssStoreCred(OM_uint32 *minor,
21940 + const gss_cred_id_t input_cred_handle,
21941 + gss_cred_usage_t input_usage,
21942 + const gss_OID desired_mech,
21943 + OM_uint32 overwrite_cred,
21944 + OM_uint32 default_cred,
21945 + gss_OID_set *elements_stored,
21946 + gss_cred_usage_t *cred_usage_stored);
21949 +gssGetNameAttribute(OM_uint32 *minor,
21951 + gss_buffer_t attr,
21952 + int *authenticated,
21954 + gss_buffer_t value,
21955 + gss_buffer_t display_value,
21959 +gssEapMakeReauthCreds(OM_uint32 *minor,
21960 + gss_ctx_id_t ctx,
21961 + gss_cred_id_t cred,
21962 + gss_buffer_t credBuf);
21965 +gssEapStoreReauthCreds(OM_uint32 *minor,
21966 + gss_ctx_id_t ctx,
21967 + gss_cred_id_t cred,
21968 + gss_buffer_t credBuf);
21972 +gssEapGlueToMechName(OM_uint32 *minor,
21973 + gss_ctx_id_t glueContext,
21974 + gss_name_t glueName,
21975 + gss_name_t *pMechName);
21978 +gssEapMechToGlueName(OM_uint32 *minor,
21979 + gss_name_t mechName,
21980 + gss_name_t *pGlueName);
21983 +gssEapReauthComplete(OM_uint32 *minor,
21984 + gss_ctx_id_t ctx,
21985 + gss_cred_id_t cred,
21986 + const gss_OID mech,
21987 + OM_uint32 timeRec);
21990 +gssEapReauthInitialize(OM_uint32 *minor);
21993 +gssEapCanReauthP(gss_cred_id_t cred,
21994 + gss_name_t target,
21995 + OM_uint32 timeReq);
21997 +#endif /* _UTIL_REAUTH_H_ */
21998 diff --git a/mech_eap/util_saml.cpp b/mech_eap/util_saml.cpp
21999 new file mode 100644
22000 index 0000000..ce7582e
22002 +++ b/mech_eap/util_saml.cpp
22005 + * Copyright (c) 2011, JANET(UK)
22006 + * All rights reserved.
22008 + * Redistribution and use in source and binary forms, with or without
22009 + * modification, are permitted provided that the following conditions
22012 + * 1. Redistributions of source code must retain the above copyright
22013 + * notice, this list of conditions and the following disclaimer.
22015 + * 2. Redistributions in binary form must reproduce the above copyright
22016 + * notice, this list of conditions and the following disclaimer in the
22017 + * documentation and/or other materials provided with the distribution.
22019 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22020 + * may be used to endorse or promote products derived from this software
22021 + * without specific prior written permission.
22023 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22024 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22025 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22026 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22027 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22028 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22029 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22030 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22031 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22032 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22037 + * SAML attribute provider implementation.
22040 +#include "gssapiP_eap.h"
22042 +#include <sstream>
22044 +#include <xercesc/util/XMLUniDefs.hpp>
22045 +#include <xmltooling/unicode.h>
22046 +#include <xmltooling/XMLToolingConfig.h>
22047 +#include <xmltooling/util/XMLHelper.h>
22048 +#include <xmltooling/util/ParserPool.h>
22049 +#include <xmltooling/util/DateTime.h>
22051 +#include <saml/exceptions.h>
22052 +#include <saml/SAMLConfig.h>
22053 +#include <saml/saml1/core/Assertions.h>
22054 +#include <saml/saml2/core/Assertions.h>
22055 +#include <saml/saml2/metadata/Metadata.h>
22056 +#include <saml/saml2/metadata/MetadataProvider.h>
22058 +using namespace xmltooling;
22059 +using namespace opensaml::saml2md;
22060 +using namespace opensaml;
22061 +using namespace xercesc;
22062 +using namespace std;
22064 +static const XMLCh
22065 +base64Binary[] = {'b','a','s','e','6','4','B','i','n','a','r','y',0};
22068 + * gss_eap_saml_assertion_provider is for retrieving the underlying
22071 +gss_eap_saml_assertion_provider::gss_eap_saml_assertion_provider(void)
22073 + m_assertion = NULL;
22074 + m_authenticated = false;
22077 +gss_eap_saml_assertion_provider::~gss_eap_saml_assertion_provider(void)
22079 + delete m_assertion;
22083 +gss_eap_saml_assertion_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
22084 + const gss_eap_attr_provider *ctx)
22086 + /* Then we may be creating from an existing attribute context */
22087 + const gss_eap_saml_assertion_provider *saml;
22089 + GSSEAP_ASSERT(m_assertion == NULL);
22091 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx))
22094 + saml = static_cast<const gss_eap_saml_assertion_provider *>(ctx);
22095 + setAssertion(saml->getAssertion(), saml->authenticated());
22101 +gss_eap_saml_assertion_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
22102 + const gss_cred_id_t gssCred,
22103 + const gss_ctx_id_t gssCtx)
22105 + const gss_eap_radius_attr_provider *radius;
22106 + gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
22107 + int authenticated, complete;
22110 + GSSEAP_ASSERT(m_assertion == NULL);
22112 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
22116 + * XXX TODO we need to support draft-howlett-radius-saml-attr-00
22118 + radius = static_cast<const gss_eap_radius_attr_provider *>
22119 + (m_manager->getProvider(ATTR_TYPE_RADIUS));
22120 + if (radius != NULL &&
22121 + radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION,
22122 + VENDORPEC_UKERNA,
22123 + &authenticated, &complete, &value)) {
22124 + setAssertion(&value, authenticated);
22125 + gss_release_buffer(&minor, &value);
22127 + m_assertion = NULL;
22134 +gss_eap_saml_assertion_provider::setAssertion(const saml2::Assertion *assertion,
22135 + bool authenticated)
22138 + delete m_assertion;
22140 + if (assertion != NULL) {
22142 + m_assertion = (saml2::Assertion *)((void *)assertion->clone());
22144 + m_assertion = dynamic_cast<saml2::Assertion *>(assertion->clone());
22146 + m_authenticated = authenticated;
22148 + m_assertion = NULL;
22149 + m_authenticated = false;
22154 +gss_eap_saml_assertion_provider::setAssertion(const gss_buffer_t buffer,
22155 + bool authenticated)
22157 + delete m_assertion;
22159 + m_assertion = parseAssertion(buffer);
22160 + m_authenticated = (m_assertion != NULL && authenticated);
22163 +saml2::Assertion *
22164 +gss_eap_saml_assertion_provider::parseAssertion(const gss_buffer_t buffer)
22166 + string str((char *)buffer->value, buffer->length);
22167 + istringstream istream(str);
22168 + DOMDocument *doc;
22169 + const XMLObjectBuilder *b;
22172 + doc = XMLToolingConfig::getConfig().getParser().parse(istream);
22176 + b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
22179 + return (saml2::Assertion *)((void *)b->buildFromDocument(doc));
22181 + return dynamic_cast<saml2::Assertion *>(b->buildFromDocument(doc));
22183 + } catch (exception &e) {
22189 +gss_eap_saml_assertion_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
22190 + void *data) const
22194 + /* just add the prefix */
22195 + if (m_assertion != NULL)
22196 + ret = addAttribute(m_manager, this, GSS_C_NO_BUFFER, data);
22204 +gss_eap_saml_assertion_provider::setAttribute(int complete GSSEAP_UNUSED,
22205 + const gss_buffer_t attr,
22206 + const gss_buffer_t value)
22208 + if (attr == GSS_C_NO_BUFFER || attr->length == 0) {
22209 + setAssertion(value);
22217 +gss_eap_saml_assertion_provider::deleteAttribute(const gss_buffer_t value GSSEAP_UNUSED)
22219 + delete m_assertion;
22220 + m_assertion = NULL;
22221 + m_authenticated = false;
22227 +gss_eap_saml_assertion_provider::getExpiryTime(void) const
22229 + saml2::Conditions *conditions;
22230 + time_t expiryTime = 0;
22232 + if (m_assertion == NULL)
22235 + conditions = m_assertion->getConditions();
22237 + if (conditions != NULL && conditions->getNotOnOrAfter() != NULL)
22238 + expiryTime = conditions->getNotOnOrAfter()->getEpoch();
22240 + return expiryTime;
22244 +gss_eap_saml_assertion_provider::mapException(OM_uint32 *minor,
22245 + std::exception &e) const
22247 + if (typeid(e) == typeid(SecurityPolicyException))
22248 + *minor = GSSEAP_SAML_SEC_POLICY_FAILURE;
22249 + else if (typeid(e) == typeid(BindingException))
22250 + *minor = GSSEAP_SAML_BINDING_FAILURE;
22251 + else if (typeid(e) == typeid(ProfileException))
22252 + *minor = GSSEAP_SAML_PROFILE_FAILURE;
22253 + else if (typeid(e) == typeid(FatalProfileException))
22254 + *minor = GSSEAP_SAML_FATAL_PROFILE_FAILURE;
22255 + else if (typeid(e) == typeid(RetryableProfileException))
22256 + *minor = GSSEAP_SAML_RETRY_PROFILE_FAILURE;
22257 + else if (typeid(e) == typeid(MetadataException))
22258 + *minor = GSSEAP_SAML_METADATA_FAILURE;
22260 + return GSS_S_CONTINUE_NEEDED;
22262 + gssEapSaveStatusInfo(*minor, "%s", e.what());
22264 + return GSS_S_FAILURE;
22268 +gss_eap_saml_assertion_provider::getAttribute(const gss_buffer_t attr,
22269 + int *authenticated,
22271 + gss_buffer_t value,
22272 + gss_buffer_t display_value GSSEAP_UNUSED,
22277 + if (attr != GSS_C_NO_BUFFER && attr->length != 0)
22280 + if (m_assertion == NULL)
22286 + if (authenticated != NULL)
22287 + *authenticated = m_authenticated;
22288 + if (complete != NULL)
22289 + *complete = true;
22291 + XMLHelper::serialize(m_assertion->marshall((DOMDocument *)NULL), str);
22293 + if (value != NULL)
22294 + duplicateBuffer(str, value);
22295 + if (display_value != NULL)
22296 + duplicateBuffer(str, display_value);
22304 +gss_eap_saml_assertion_provider::mapToAny(int authenticated,
22305 + gss_buffer_t type_id GSSEAP_UNUSED) const
22307 + if (authenticated && !m_authenticated)
22308 + return (gss_any_t)NULL;
22310 + return (gss_any_t)m_assertion;
22314 +gss_eap_saml_assertion_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
22315 + gss_any_t input) const
22317 + delete ((saml2::Assertion *)input);
22321 +gss_eap_saml_assertion_provider::prefix(void) const
22323 + return "urn:ietf:params:gss-eap:saml-aaa-assertion";
22327 +gss_eap_saml_assertion_provider::init(void)
22329 + bool ret = false;
22332 + ret = SAMLConfig::getConfig().init();
22333 + } catch (exception &e) {
22337 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML_ASSERTION, createAttrContext);
22343 +gss_eap_saml_assertion_provider::finalize(void)
22345 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML_ASSERTION);
22348 +gss_eap_attr_provider *
22349 +gss_eap_saml_assertion_provider::createAttrContext(void)
22351 + return new gss_eap_saml_assertion_provider;
22354 +saml2::Assertion *
22355 +gss_eap_saml_assertion_provider::initAssertion(void)
22357 + delete m_assertion;
22358 + m_assertion = saml2::AssertionBuilder::buildAssertion();
22359 + m_authenticated = false;
22361 + return m_assertion;
22365 + * gss_eap_saml_attr_provider is for retrieving the underlying attributes.
22368 +gss_eap_saml_attr_provider::getAssertion(int *authenticated,
22369 + saml2::Assertion **pAssertion,
22370 + bool createIfAbsent) const
22372 + gss_eap_saml_assertion_provider *saml;
22374 + if (authenticated != NULL)
22375 + *authenticated = false;
22376 + if (pAssertion != NULL)
22377 + *pAssertion = NULL;
22379 + saml = static_cast<gss_eap_saml_assertion_provider *>
22380 + (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
22381 + if (saml == NULL)
22384 + if (authenticated != NULL)
22385 + *authenticated = saml->authenticated();
22386 + if (pAssertion != NULL)
22387 + *pAssertion = saml->getAssertion();
22389 + if (saml->getAssertion() == NULL) {
22390 + if (createIfAbsent) {
22391 + if (authenticated != NULL)
22392 + *authenticated = false;
22393 + if (pAssertion != NULL)
22394 + *pAssertion = saml->initAssertion();
22403 +gss_eap_saml_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
22404 + void *data) const
22406 + saml2::Assertion *assertion;
22407 + int authenticated;
22409 + if (!getAssertion(&authenticated, &assertion))
22413 + * Note: the first prefix is added by the attribute provider manager
22415 + * From draft-hartman-gss-eap-naming-00:
22417 + * Each attribute carried in the assertion SHOULD also be a GSS name
22418 + * attribute. The name of this attribute has three parts, all separated
22419 + * by an ASCII space character. The first part is
22420 + * urn:ietf:params:gss-eap:saml-attr. The second part is the URI for
22421 + * the SAML attribute name format. The final part is the name of the
22422 + * SAML attribute. If the mechanism performs an additional attribute
22423 + * query, the retrieved attributes SHOULD be GSS-API name attributes
22424 + * using the same name syntax.
22426 + /* For each attribute statement, look for an attribute match */
22427 + const vector <saml2::AttributeStatement *> &statements =
22428 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22430 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22431 + s != statements.end();
22433 + const vector<saml2::Attribute*> &attrs =
22434 + const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
22436 + for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
22437 + const XMLCh *attributeName, *attributeNameFormat;
22438 + XMLCh space[2] = { ' ', 0 };
22439 + gss_buffer_desc utf8;
22441 + attributeName = (*a)->getName();
22442 + attributeNameFormat = (*a)->getNameFormat();
22443 + if (attributeNameFormat == NULL || attributeNameFormat[0] == '\0')
22444 + attributeNameFormat = saml2::Attribute::UNSPECIFIED;
22446 + XMLCh qualifiedName[XMLString::stringLen(attributeNameFormat) + 1 +
22447 + XMLString::stringLen(attributeName) + 1];
22448 + XMLString::copyString(qualifiedName, attributeNameFormat);
22449 + XMLString::catString(qualifiedName, space);
22450 + XMLString::catString(qualifiedName, attributeName);
22452 + utf8.value = (void *)toUTF8(qualifiedName);
22453 + utf8.length = strlen((char *)utf8.value);
22455 + if (!addAttribute(m_manager, this, &utf8, data))
22463 +static BaseRefVectorOf<XMLCh> *
22464 +decomposeAttributeName(const gss_buffer_t attr)
22466 + BaseRefVectorOf<XMLCh> *components;
22467 + string str((const char *)attr->value, attr->length);
22468 + auto_ptr_XMLCh qualifiedAttr(str.c_str());
22470 + components = XMLString::tokenizeString(qualifiedAttr.get());
22472 + if (components->size() != 2) {
22473 + delete components;
22474 + components = NULL;
22477 + return components;
22481 +gss_eap_saml_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
22482 + const gss_buffer_t attr,
22483 + const gss_buffer_t value)
22485 + saml2::Assertion *assertion;
22486 + saml2::Attribute *attribute;
22487 + saml2::AttributeValue *attributeValue;
22488 + saml2::AttributeStatement *attributeStatement;
22490 + if (!getAssertion(NULL, &assertion, true))
22493 + if (assertion->getAttributeStatements().size() != 0) {
22494 + attributeStatement = assertion->getAttributeStatements().front();
22496 + attributeStatement = saml2::AttributeStatementBuilder::buildAttributeStatement();
22497 + assertion->getAttributeStatements().push_back(attributeStatement);
22500 + /* Check the attribute name consists of name format | whsp | name */
22501 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22502 + if (components == NULL)
22505 + attribute = saml2::AttributeBuilder::buildAttribute();
22506 + attribute->setNameFormat(components->elementAt(0));
22507 + attribute->setName(components->elementAt(1));
22509 + attributeValue = saml2::AttributeValueBuilder::buildAttributeValue();
22510 + auto_ptr_XMLCh unistr((char *)value->value, value->length);
22511 + attributeValue->setTextContent(unistr.get());
22513 + attribute->getAttributeValues().push_back(attributeValue);
22515 + GSSEAP_ASSERT(attributeStatement != NULL);
22516 + attributeStatement->getAttributes().push_back(attribute);
22518 + delete components;
22524 +gss_eap_saml_attr_provider::deleteAttribute(const gss_buffer_t attr)
22526 + saml2::Assertion *assertion;
22527 + bool ret = false;
22529 + if (!getAssertion(NULL, &assertion) ||
22530 + assertion->getAttributeStatements().size() == 0)
22533 + /* Check the attribute name consists of name format | whsp | name */
22534 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22535 + if (components == NULL)
22538 + /* For each attribute statement, look for an attribute match */
22539 + const vector<saml2::AttributeStatement *> &statements =
22540 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22542 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22543 + s != statements.end();
22545 + const vector<saml2::Attribute *> &attrs =
22546 + const_cast<const saml2::AttributeStatement *>(*s)->getAttributes();
22547 + ssize_t index = -1, i = 0;
22549 + /* There's got to be an easier way to do this */
22550 + for (vector<saml2::Attribute *>::const_iterator a = attrs.begin();
22551 + a != attrs.end();
22553 + if (XMLString::equals((*a)->getNameFormat(), components->elementAt(0)) &&
22554 + XMLString::equals((*a)->getName(), components->elementAt(1))) {
22560 + if (index != -1) {
22561 + (*s)->getAttributes().erase((*s)->getAttributes().begin() + index);
22566 + delete components;
22572 +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr,
22573 + int *authenticated,
22575 + const saml2::Attribute **pAttribute) const
22577 + saml2::Assertion *assertion;
22579 + if (authenticated != NULL)
22580 + *authenticated = false;
22581 + if (complete != NULL)
22582 + *complete = true;
22583 + *pAttribute = NULL;
22585 + if (!getAssertion(authenticated, &assertion) ||
22586 + assertion->getAttributeStatements().size() == 0)
22589 + /* Check the attribute name consists of name format | whsp | name */
22590 + BaseRefVectorOf<XMLCh> *components = decomposeAttributeName(attr);
22591 + if (components == NULL)
22594 + /* For each attribute statement, look for an attribute match */
22595 + const vector <saml2::AttributeStatement *> &statements =
22596 + const_cast<const saml2::Assertion *>(assertion)->getAttributeStatements();
22597 + const saml2::Attribute *ret = NULL;
22599 + for (vector<saml2::AttributeStatement *>::const_iterator s = statements.begin();
22600 + s != statements.end();
22602 + const vector<saml2::Attribute *> &attrs =
22603 + const_cast<const saml2::AttributeStatement*>(*s)->getAttributes();
22605 + for (vector<saml2::Attribute *>::const_iterator a = attrs.begin(); a != attrs.end(); ++a) {
22606 + const XMLCh *attributeName, *attributeNameFormat;
22608 + attributeName = (*a)->getName();
22609 + attributeNameFormat = (*a)->getNameFormat();
22610 + if (attributeNameFormat == NULL || attributeNameFormat[0] == '\0')
22611 + attributeNameFormat = saml2::Attribute::UNSPECIFIED;
22613 + if (XMLString::equals(attributeNameFormat, components->elementAt(0)) &&
22614 + XMLString::equals(attributeName, components->elementAt(1))) {
22624 + delete components;
22626 + *pAttribute = ret;
22628 + return (ret != NULL);
22632 +isBase64EncodedAttributeValueP(const saml2::AttributeValue *av)
22634 + const xmltooling::QName *type = av->getSchemaType();
22636 + if (type == NULL)
22639 + if (!type->hasNamespaceURI() ||
22640 + !XMLString::equals(type->getNamespaceURI(), xmlconstants::XSD_NS))
22643 + if (!type->hasLocalPart() ||
22644 + !XMLString::equals(type->getLocalPart(), base64Binary))
22651 +gss_eap_saml_attr_provider::getAttribute(const gss_buffer_t attr,
22652 + int *authenticated,
22654 + gss_buffer_t value,
22655 + gss_buffer_t display_value,
22658 + const saml2::Attribute *a;
22659 + const saml2::AttributeValue *av;
22660 + int nvalues, i = *more;
22664 + if (!getAttribute(attr, authenticated, complete, &a))
22667 + nvalues = a->getAttributeValues().size();
22671 + if (i >= nvalues)
22674 + av = (const saml2::AttributeValue *)((void *)(a->getAttributeValues().at(i)));
22676 + av = dynamic_cast<const saml2::AttributeValue *>(a->getAttributeValues().at(i));
22678 + if (av != NULL) {
22679 + bool base64Encoded = isBase64EncodedAttributeValueP(av);
22681 + if (value != NULL) {
22682 + char *stringValue = toUTF8(av->getTextContent(), true);
22683 + size_t stringValueLen = strlen(stringValue);
22685 + if (base64Encoded) {
22686 + ssize_t octetLen;
22688 + value->value = GSSEAP_MALLOC(stringValueLen);
22689 + if (value->value == NULL) {
22690 + GSSEAP_FREE(stringValue);
22691 + throw new std::bad_alloc;
22694 + octetLen = base64Decode(stringValue, value->value);
22695 + if (octetLen < 0) {
22696 + GSSEAP_FREE(value->value);
22697 + GSSEAP_FREE(stringValue);
22698 + value->value = NULL;
22701 + value->length = octetLen;
22702 + GSSEAP_FREE(stringValue);
22704 + value->value = stringValue;
22705 + value->length = stringValueLen;
22708 + if (display_value != NULL && base64Encoded == false) {
22709 + display_value->value = toUTF8(av->getTextContent(), true);
22710 + display_value->length = strlen((char *)value->value);
22714 + if (nvalues > ++i)
22721 +gss_eap_saml_attr_provider::mapToAny(int authenticated GSSEAP_UNUSED,
22722 + gss_buffer_t type_id GSSEAP_UNUSED) const
22724 + return (gss_any_t)NULL;
22728 +gss_eap_saml_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
22729 + gss_any_t input GSSEAP_UNUSED) const
22734 +gss_eap_saml_attr_provider::prefix(void) const
22736 + return "urn:ietf:params:gss-eap:saml-attr";
22740 +gss_eap_saml_attr_provider::init(void)
22742 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_SAML, createAttrContext);
22747 +gss_eap_saml_attr_provider::finalize(void)
22749 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_SAML);
22752 +gss_eap_attr_provider *
22753 +gss_eap_saml_attr_provider::createAttrContext(void)
22755 + return new gss_eap_saml_attr_provider;
22759 +gssEapSamlAttrProvidersInit(OM_uint32 *minor)
22761 + if (!gss_eap_saml_assertion_provider::init() ||
22762 + !gss_eap_saml_attr_provider::init()) {
22763 + *minor = GSSEAP_SAML_INIT_FAILURE;
22764 + return GSS_S_FAILURE;
22767 + return GSS_S_COMPLETE;
22771 +gssEapSamlAttrProvidersFinalize(OM_uint32 *minor)
22773 + gss_eap_saml_attr_provider::finalize();
22774 + gss_eap_saml_assertion_provider::finalize();
22777 + return GSS_S_COMPLETE;
22779 diff --git a/mech_eap/util_saml.h b/mech_eap/util_saml.h
22780 new file mode 100644
22781 index 0000000..9110ad4
22783 +++ b/mech_eap/util_saml.h
22786 + * Copyright (c) 2011, JANET(UK)
22787 + * All rights reserved.
22789 + * Redistribution and use in source and binary forms, with or without
22790 + * modification, are permitted provided that the following conditions
22793 + * 1. Redistributions of source code must retain the above copyright
22794 + * notice, this list of conditions and the following disclaimer.
22796 + * 2. Redistributions in binary form must reproduce the above copyright
22797 + * notice, this list of conditions and the following disclaimer in the
22798 + * documentation and/or other materials provided with the distribution.
22800 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22801 + * may be used to endorse or promote products derived from this software
22802 + * without specific prior written permission.
22804 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22805 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22806 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22807 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22808 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22809 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22810 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22811 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22812 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22813 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22818 + * SAML attribute provider.
22821 +#ifndef _UTIL_SAML_H_
22822 +#define _UTIL_SAML_H_ 1
22824 +#ifdef __cplusplus
22826 +namespace opensaml {
22827 + namespace saml2 {
22834 +struct gss_eap_saml_assertion_provider : gss_eap_attr_provider {
22836 + gss_eap_saml_assertion_provider(void);
22837 + ~gss_eap_saml_assertion_provider(void);
22839 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
22840 + const gss_eap_attr_provider *ctx);
22841 + bool initWithGssContext(const gss_eap_attr_ctx *source,
22842 + const gss_cred_id_t cred,
22843 + const gss_ctx_id_t ctx);
22845 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
22846 + bool setAttribute(int complete,
22847 + const gss_buffer_t attr,
22848 + const gss_buffer_t value);
22849 + bool deleteAttribute(const gss_buffer_t value);
22850 + bool getAttribute(const gss_buffer_t attr,
22851 + int *authenticated,
22853 + gss_buffer_t value,
22854 + gss_buffer_t display_value,
22855 + int *more) const;
22856 + gss_any_t mapToAny(int authenticated,
22857 + gss_buffer_t type_id) const;
22858 + void releaseAnyNameMapping(gss_buffer_t type_id,
22859 + gss_any_t input) const;
22861 + const char *prefix(void) const;
22862 + const char *name(void) const { return NULL; }
22863 + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
22864 + JSONObject &object GSSEAP_UNUSED) {
22867 + JSONObject jsonRepresentation(void) const {
22868 + return JSONObject::null();
22871 + opensaml::saml2::Assertion *initAssertion(void);
22873 + opensaml::saml2::Assertion *getAssertion(void) const {
22874 + return m_assertion;
22876 + bool authenticated(void) const {
22877 + return m_authenticated;
22880 + time_t getExpiryTime(void) const;
22881 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
22883 + static bool init(void);
22884 + static void finalize(void);
22886 + static gss_eap_attr_provider *createAttrContext(void);
22889 + static opensaml::saml2::Assertion *
22890 + parseAssertion(const gss_buffer_t buffer);
22892 + void setAssertion(const opensaml::saml2::Assertion *assertion,
22893 + bool authenticated = false);
22894 + void setAssertion(const gss_buffer_t buffer,
22895 + bool authenticated = false);
22897 + opensaml::saml2::Assertion *m_assertion;
22898 + bool m_authenticated;
22901 +struct gss_eap_saml_attr_provider : gss_eap_attr_provider {
22903 + gss_eap_saml_attr_provider(void) {}
22904 + ~gss_eap_saml_attr_provider(void) {}
22906 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
22907 + bool setAttribute(int complete,
22908 + const gss_buffer_t attr,
22909 + const gss_buffer_t value);
22910 + bool deleteAttribute(const gss_buffer_t value);
22911 + bool getAttribute(const gss_buffer_t attr,
22912 + int *authenticated,
22914 + gss_buffer_t value,
22915 + gss_buffer_t display_value,
22916 + int *more) const;
22917 + gss_any_t mapToAny(int authenticated,
22918 + gss_buffer_t type_id) const;
22919 + void releaseAnyNameMapping(gss_buffer_t type_id,
22920 + gss_any_t input) const;
22922 + const char *prefix(void) const;
22923 + const char *name(void) const {
22926 + bool initWithJsonObject(const gss_eap_attr_ctx *manager GSSEAP_UNUSED,
22927 + JSONObject &object GSSEAP_UNUSED) {
22930 + JSONObject jsonRepresentation(void) const {
22931 + return JSONObject::null();
22934 + bool getAttribute(const gss_buffer_t attr,
22935 + int *authenticated,
22937 + const opensaml::saml2::Attribute **pAttribute) const;
22938 + bool getAssertion(int *authenticated,
22939 + opensaml::saml2::Assertion **pAssertion,
22940 + bool createIfAbsent = false) const;
22942 + static bool init(void);
22943 + static void finalize(void);
22945 + static gss_eap_attr_provider *createAttrContext(void);
22953 +OM_uint32 gssEapSamlAttrProvidersInit(OM_uint32 *minor);
22954 +OM_uint32 gssEapSamlAttrProvidersFinalize(OM_uint32 *minor);
22956 +#ifdef __cplusplus
22960 +#endif /* _UTIL_SAML_H_ */
22961 diff --git a/mech_eap/util_shib.cpp b/mech_eap/util_shib.cpp
22962 new file mode 100644
22963 index 0000000..f8c702b
22965 +++ b/mech_eap/util_shib.cpp
22968 + * Copyright (c) 2011, JANET(UK)
22969 + * All rights reserved.
22971 + * Redistribution and use in source and binary forms, with or without
22972 + * modification, are permitted provided that the following conditions
22975 + * 1. Redistributions of source code must retain the above copyright
22976 + * notice, this list of conditions and the following disclaimer.
22978 + * 2. Redistributions in binary form must reproduce the above copyright
22979 + * notice, this list of conditions and the following disclaimer in the
22980 + * documentation and/or other materials provided with the distribution.
22982 + * 3. Neither the name of JANET(UK) nor the names of its contributors
22983 + * may be used to endorse or promote products derived from this software
22984 + * without specific prior written permission.
22986 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22987 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22988 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22989 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22990 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22991 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22992 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22993 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22994 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22995 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22999 + * Copyright 2001-2009 Internet2
23001 + * Licensed under the Apache License, Version 2.0 (the "License");
23002 + * you may not use this file except in compliance with the License.
23003 + * You may obtain a copy of the License at
23005 + * http://www.apache.org/licenses/LICENSE-2.0
23007 + * Unless required by applicable law or agreed to in writing, software
23008 + * distributed under the License is distributed on an "AS IS" BASIS,
23009 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23010 + * See the License for the specific language governing permissions and
23011 + * limitations under the License.
23015 + * Local attribute provider implementation.
23018 +#include "gssapiP_eap.h"
23020 +#include <xmltooling/XMLObject.h>
23021 +#ifndef HAVE_OPENSAML
23022 +#include <xmltooling/XMLToolingConfig.h>
23023 +#include <xmltooling/util/ParserPool.h>
23026 +#include <saml/saml2/core/Assertions.h>
23028 +#include <shibsp/exceptions.h>
23029 +#include <shibsp/attribute/SimpleAttribute.h>
23030 +#include <shibsp/attribute/BinaryAttribute.h>
23031 +#include <shibsp/attribute/ScopedAttribute.h>
23032 +#include <shibresolver/resolver.h>
23034 +#include <sstream>
23036 +using namespace shibsp;
23037 +using namespace shibresolver;
23038 +using namespace xmltooling;
23039 +using namespace std;
23040 +#ifdef HAVE_OPENSAML
23041 +using namespace opensaml::saml2md;
23042 +using namespace opensaml;
23044 +using namespace xercesc;
23047 +gss_eap_shib_attr_provider::gss_eap_shib_attr_provider(void)
23049 + m_initialized = false;
23050 + m_authenticated = false;
23053 +gss_eap_shib_attr_provider::~gss_eap_shib_attr_provider(void)
23055 + for_each(m_attributes.begin(),
23056 + m_attributes.end(),
23057 + xmltooling::cleanup<Attribute>())
23062 +gss_eap_shib_attr_provider::initWithExistingContext(const gss_eap_attr_ctx *manager,
23063 + const gss_eap_attr_provider *ctx)
23065 + const gss_eap_shib_attr_provider *shib;
23067 + if (!gss_eap_attr_provider::initWithExistingContext(manager, ctx)) {
23071 + m_authenticated = false;
23073 + shib = static_cast<const gss_eap_shib_attr_provider *>(ctx);
23074 + if (shib != NULL) {
23075 + m_attributes = duplicateAttributes(shib->getAttributes());
23076 + m_authenticated = shib->authenticated();
23079 + m_initialized = true;
23085 +gss_eap_shib_attr_provider::initWithGssContext(const gss_eap_attr_ctx *manager,
23086 + const gss_cred_id_t gssCred,
23087 + const gss_ctx_id_t gssCtx)
23089 + if (!gss_eap_attr_provider::initWithGssContext(manager, gssCred, gssCtx))
23092 + auto_ptr<ShibbolethResolver> resolver(ShibbolethResolver::create());
23095 + * For now, leave ApplicationID defaulted.
23096 + * Later on, we could allow this via config option to the mechanism
23097 + * or rely on an SPRequest interface to pass in a URI identifying the
23101 + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
23102 + if (gssCred != GSS_C_NO_CREDENTIAL &&
23103 + gssEapDisplayName(&minor, gssCred->name, &nameBuf, NULL) == GSS_S_COMPLETE) {
23104 + resolver->setApplicationID((const char *)nameBuf.value);
23105 + gss_release_buffer(&minor, &nameBuf);
23109 + gss_buffer_desc mechName = GSS_C_EMPTY_BUFFER;
23110 + OM_uint32 major, minor;
23112 + major = gssEapExportNameInternal(&minor, gssCtx->initiatorName, &mechName,
23113 + EXPORT_NAME_FLAG_OID |
23114 + EXPORT_NAME_FLAG_COMPOSITE);
23115 + if (major == GSS_S_COMPLETE) {
23116 + resolver->addToken(&mechName);
23117 + gss_release_buffer(&minor, &mechName);
23120 +#ifdef HAVE_OPENSAML
23121 + const gss_eap_saml_assertion_provider *saml;
23122 + saml = static_cast<const gss_eap_saml_assertion_provider *>
23123 + (m_manager->getProvider(ATTR_TYPE_SAML_ASSERTION));
23124 + if (saml != NULL && saml->getAssertion() != NULL) {
23125 + resolver->addToken(saml->getAssertion());
23128 + /* If no OpenSAML, parse the XML assertion explicitly */
23129 + const gss_eap_radius_attr_provider *radius;
23130 + int authenticated, complete;
23131 + gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
23133 + radius = static_cast<const gss_eap_radius_attr_provider *>
23134 + (m_manager->getProvider(ATTR_TYPE_RADIUS));
23135 + if (radius != NULL &&
23136 + radius->getFragmentedAttribute(PW_SAML_AAA_ASSERTION,
23137 + VENDORPEC_UKERNA,
23138 + &authenticated, &complete, &value)) {
23139 + string str((char *)value.value, value.length);
23140 + istringstream istream(str);
23141 + DOMDocument *doc = XMLToolingConfig::getConfig().getParser().parse(istream);
23142 + const XMLObjectBuilder *b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
23143 + resolver->addToken(b->buildFromDocument(doc));
23144 + gss_release_buffer(&minor, &value);
23146 +#endif /* HAVE_OPENSAML */
23149 + resolver->resolve();
23150 + m_attributes = resolver->getResolvedAttributes();
23151 + resolver->getResolvedAttributes().clear();
23152 + } catch (exception &e) {
23156 + m_authenticated = true;
23157 + m_initialized = true;
23163 +gss_eap_shib_attr_provider::getAttributeIndex(const gss_buffer_t attr) const
23167 + GSSEAP_ASSERT(m_initialized);
23169 + for (vector<Attribute *>::const_iterator a = m_attributes.begin();
23170 + a != m_attributes.end();
23173 + for (vector<string>::const_iterator s = (*a)->getAliases().begin();
23174 + s != (*a)->getAliases().end();
23176 + if (attr->length == (*s).length() &&
23177 + memcmp((*s).c_str(), attr->value, attr->length) == 0) {
23187 +gss_eap_shib_attr_provider::setAttribute(int complete GSSEAP_UNUSED,
23188 + const gss_buffer_t attr,
23189 + const gss_buffer_t value)
23191 + string attrStr((char *)attr->value, attr->length);
23192 + vector <string> ids(1, attrStr);
23193 + BinaryAttribute *a = new BinaryAttribute(ids);
23195 + GSSEAP_ASSERT(m_initialized);
23197 + if (value->length != 0) {
23198 + string valueStr((char *)value->value, value->length);
23200 + a->getValues().push_back(valueStr);
23203 + m_attributes.push_back(a);
23204 + m_authenticated = false;
23210 +gss_eap_shib_attr_provider::deleteAttribute(const gss_buffer_t attr)
23214 + GSSEAP_ASSERT(m_initialized);
23216 + i = getAttributeIndex(attr);
23218 + m_attributes.erase(m_attributes.begin() + i);
23220 + m_authenticated = false;
23226 +gss_eap_shib_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute,
23227 + void *data) const
23229 + GSSEAP_ASSERT(m_initialized);
23231 + for (vector<Attribute*>::const_iterator a = m_attributes.begin();
23232 + a != m_attributes.end();
23235 + gss_buffer_desc attribute;
23237 + attribute.value = (void *)((*a)->getId());
23238 + attribute.length = strlen((char *)attribute.value);
23240 + if (!addAttribute(m_manager, this, &attribute, data))
23248 +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr) const
23250 + const Attribute *ret = NULL;
23252 + GSSEAP_ASSERT(m_initialized);
23254 + for (vector<Attribute *>::const_iterator a = m_attributes.begin();
23255 + a != m_attributes.end();
23258 + for (vector<string>::const_iterator s = (*a)->getAliases().begin();
23259 + s != (*a)->getAliases().end();
23261 + if (attr->length == (*s).length() &&
23262 + memcmp((*s).c_str(), attr->value, attr->length) == 0) {
23275 +gss_eap_shib_attr_provider::getAttribute(const gss_buffer_t attr,
23276 + int *authenticated,
23278 + gss_buffer_t value,
23279 + gss_buffer_t display_value,
23282 + const Attribute *shibAttr = NULL;
23283 + const BinaryAttribute *binaryAttr;
23284 + gss_buffer_desc valueBuf = GSS_C_EMPTY_BUFFER;
23285 + gss_buffer_desc displayValueBuf = GSS_C_EMPTY_BUFFER;
23286 + int nvalues, i = *more;
23288 + GSSEAP_ASSERT(m_initialized);
23292 + shibAttr = getAttribute(attr);
23293 + if (shibAttr == NULL)
23296 + nvalues = shibAttr->valueCount();
23300 + if (i >= nvalues)
23303 + binaryAttr = dynamic_cast<const BinaryAttribute *>(shibAttr);
23304 + if (binaryAttr != NULL) {
23305 + std::string str = binaryAttr->getValues()[*more];
23307 + valueBuf.value = (void *)str.data();
23308 + valueBuf.length = str.size();
23310 + std::string str = shibAttr->getSerializedValues()[*more];
23312 + valueBuf.value = (void *)str.c_str();
23313 + valueBuf.length = str.length();
23315 + const SimpleAttribute *simpleAttr =
23316 + dynamic_cast<const SimpleAttribute *>(shibAttr);
23317 + const ScopedAttribute *scopedAttr =
23318 + dynamic_cast<const ScopedAttribute *>(shibAttr);
23319 + if (simpleAttr != NULL || scopedAttr != NULL)
23320 + displayValueBuf = valueBuf;
23323 + if (authenticated != NULL)
23324 + *authenticated = m_authenticated;
23325 + if (complete != NULL)
23326 + *complete = true;
23327 + if (value != NULL)
23328 + duplicateBuffer(valueBuf, value);
23329 + if (display_value != NULL)
23330 + duplicateBuffer(displayValueBuf, display_value);
23331 + if (nvalues > ++i)
23338 +gss_eap_shib_attr_provider::mapToAny(int authenticated,
23339 + gss_buffer_t type_id GSSEAP_UNUSED) const
23341 + gss_any_t output;
23343 + GSSEAP_ASSERT(m_initialized);
23345 + if (authenticated && !m_authenticated)
23346 + return (gss_any_t)NULL;
23348 + vector <Attribute *>v = duplicateAttributes(m_attributes);
23350 + output = (gss_any_t)new vector <Attribute *>(v);
23356 +gss_eap_shib_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id GSSEAP_UNUSED,
23357 + gss_any_t input) const
23359 + GSSEAP_ASSERT(m_initialized);
23361 + vector <Attribute *> *v = ((vector <Attribute *> *)input);
23366 +gss_eap_shib_attr_provider::prefix(void) const
23372 +gss_eap_shib_attr_provider::name(void) const
23378 +gss_eap_shib_attr_provider::jsonRepresentation(void) const
23382 + if (m_initialized == false)
23383 + return obj; /* don't export incomplete context */
23385 + JSONObject jattrs = JSONObject::array();
23387 + for (vector<Attribute*>::const_iterator a = m_attributes.begin();
23388 + a != m_attributes.end(); ++a) {
23389 + DDF attr = (*a)->marshall();
23390 + JSONObject jattr = JSONObject::ddf(attr);
23391 + jattrs.append(jattr);
23394 + obj.set("attributes", jattrs);
23396 + obj.set("authenticated", m_authenticated);
23402 +gss_eap_shib_attr_provider::initWithJsonObject(const gss_eap_attr_ctx *ctx,
23405 + if (!gss_eap_attr_provider::initWithJsonObject(ctx, obj))
23408 + GSSEAP_ASSERT(m_authenticated == false);
23409 + GSSEAP_ASSERT(m_attributes.size() == 0);
23411 + JSONObject jattrs = obj["attributes"];
23412 + size_t nelems = jattrs.size();
23414 + for (size_t i = 0; i < nelems; i++) {
23415 + JSONObject jattr = jattrs.get(i);
23417 + DDF attr = jattr.ddf();
23418 + Attribute *attribute = Attribute::unmarshall(attr);
23419 + m_attributes.push_back(attribute);
23422 + m_authenticated = obj["authenticated"].integer();
23423 + m_initialized = true;
23429 +gss_eap_shib_attr_provider::init(void)
23431 + bool ret = false;
23434 + ret = ShibbolethResolver::init();
23435 + } catch (exception &e) {
23439 + gss_eap_attr_ctx::registerProvider(ATTR_TYPE_LOCAL, createAttrContext);
23445 +gss_eap_shib_attr_provider::finalize(void)
23447 + gss_eap_attr_ctx::unregisterProvider(ATTR_TYPE_LOCAL);
23448 + ShibbolethResolver::term();
23452 +gss_eap_shib_attr_provider::mapException(OM_uint32 *minor,
23453 + std::exception &e) const
23455 + if (typeid(e) == typeid(AttributeException))
23456 + *minor = GSSEAP_SHIB_ATTR_FAILURE;
23457 + else if (typeid(e) == typeid(AttributeExtractionException))
23458 + *minor = GSSEAP_SHIB_ATTR_EXTRACT_FAILURE;
23459 + else if (typeid(e) == typeid(AttributeFilteringException))
23460 + *minor = GSSEAP_SHIB_ATTR_FILTER_FAILURE;
23461 + else if (typeid(e) == typeid(AttributeResolutionException))
23462 + *minor = GSSEAP_SHIB_ATTR_RESOLVE_FAILURE;
23463 + else if (typeid(e) == typeid(ConfigurationException))
23464 + *minor = GSSEAP_SHIB_CONFIG_FAILURE;
23465 + else if (typeid(e) == typeid(ListenerException))
23466 + *minor = GSSEAP_SHIB_LISTENER_FAILURE;
23468 + return GSS_S_CONTINUE_NEEDED;
23470 + gssEapSaveStatusInfo(*minor, "%s", e.what());
23472 + return GSS_S_FAILURE;
23475 +gss_eap_attr_provider *
23476 +gss_eap_shib_attr_provider::createAttrContext(void)
23478 + return new gss_eap_shib_attr_provider;
23482 +gss_eap_shib_attr_provider::duplicateAttribute(const Attribute *src)
23484 + DDF obj = src->marshall();
23485 + Attribute *attribute = Attribute::unmarshall(obj);
23488 + return attribute;
23491 +vector <Attribute *>
23492 +gss_eap_shib_attr_provider::duplicateAttributes(const vector <Attribute *>src)
23494 + vector <Attribute *> dst;
23496 + for (vector<Attribute *>::const_iterator a = src.begin();
23499 + dst.push_back(duplicateAttribute(*a));
23505 +gssEapLocalAttrProviderInit(OM_uint32 *minor)
23507 + if (!gss_eap_shib_attr_provider::init()) {
23508 + *minor = GSSEAP_SHIB_INIT_FAILURE;
23509 + return GSS_S_FAILURE;
23511 + return GSS_S_COMPLETE;
23515 +gssEapLocalAttrProviderFinalize(OM_uint32 *minor)
23517 + gss_eap_shib_attr_provider::finalize();
23520 + return GSS_S_COMPLETE;
23522 diff --git a/mech_eap/util_shib.h b/mech_eap/util_shib.h
23523 new file mode 100644
23524 index 0000000..4cf7481
23526 +++ b/mech_eap/util_shib.h
23529 + * Copyright (c) 2011, JANET(UK)
23530 + * All rights reserved.
23532 + * Redistribution and use in source and binary forms, with or without
23533 + * modification, are permitted provided that the following conditions
23536 + * 1. Redistributions of source code must retain the above copyright
23537 + * notice, this list of conditions and the following disclaimer.
23539 + * 2. Redistributions in binary form must reproduce the above copyright
23540 + * notice, this list of conditions and the following disclaimer in the
23541 + * documentation and/or other materials provided with the distribution.
23543 + * 3. Neither the name of JANET(UK) nor the names of its contributors
23544 + * may be used to endorse or promote products derived from this software
23545 + * without specific prior written permission.
23547 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23548 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23549 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23550 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23551 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23552 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23553 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23554 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23555 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23556 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23561 + * Local attribute provider.
23564 +#ifndef _UTIL_SHIB_H_
23565 +#define _UTIL_SHIB_H_ 1
23567 +#ifdef __cplusplus
23571 +namespace shibsp {
23575 +namespace shibresolver {
23576 + class ShibbolethResolver;
23579 +struct gss_eap_shib_attr_provider : gss_eap_attr_provider {
23581 + gss_eap_shib_attr_provider(void);
23582 + ~gss_eap_shib_attr_provider(void);
23584 + bool initWithExistingContext(const gss_eap_attr_ctx *source,
23585 + const gss_eap_attr_provider *ctx);
23586 + bool initWithGssContext(const gss_eap_attr_ctx *source,
23587 + const gss_cred_id_t cred,
23588 + const gss_ctx_id_t ctx);
23590 + bool setAttribute(int complete,
23591 + const gss_buffer_t attr,
23592 + const gss_buffer_t value);
23593 + bool deleteAttribute(const gss_buffer_t value);
23594 + bool getAttributeTypes(gss_eap_attr_enumeration_cb, void *data) const;
23595 + bool getAttribute(const gss_buffer_t attr,
23596 + int *authenticated,
23598 + gss_buffer_t value,
23599 + gss_buffer_t display_value,
23600 + int *more) const;
23601 + gss_any_t mapToAny(int authenticated,
23602 + gss_buffer_t type_id) const;
23603 + void releaseAnyNameMapping(gss_buffer_t type_id,
23604 + gss_any_t input) const;
23606 + const char *prefix(void) const;
23607 + const char *name(void) const;
23608 + bool initWithJsonObject(const gss_eap_attr_ctx *manager,
23609 + JSONObject &obj);
23610 + JSONObject jsonRepresentation(void) const;
23612 + static bool init(void);
23613 + static void finalize(void);
23615 + OM_uint32 mapException(OM_uint32 *minor, std::exception &e) const;
23617 + static gss_eap_attr_provider *createAttrContext(void);
23619 + std::vector<shibsp::Attribute *> getAttributes(void) const {
23620 + return m_attributes;
23624 + static shibsp::Attribute *
23625 + duplicateAttribute(const shibsp::Attribute *src);
23626 + static std::vector <shibsp::Attribute *>
23627 + duplicateAttributes(const std::vector <shibsp::Attribute *>src);
23629 + ssize_t getAttributeIndex(const gss_buffer_t attr) const;
23630 + const shibsp::Attribute *getAttribute(const gss_buffer_t attr) const;
23632 + bool authenticated(void) const { return m_authenticated; }
23634 + bool m_initialized;
23635 + bool m_authenticated;
23636 + std::vector<shibsp::Attribute *> m_attributes;
23642 +OM_uint32 gssEapLocalAttrProviderInit(OM_uint32 *minor);
23643 +OM_uint32 gssEapLocalAttrProviderFinalize(OM_uint32 *minor);
23645 +#ifdef __cplusplus
23649 +#endif /* _UTIL_SHIB_H_ */
23650 diff --git a/mech_eap/util_sm.c b/mech_eap/util_sm.c
23651 new file mode 100644
23652 index 0000000..56248d8
23654 +++ b/mech_eap/util_sm.c
23657 + * Copyright (c) 2011, JANET(UK)
23658 + * All rights reserved.
23660 + * Redistribution and use in source and binary forms, with or without
23661 + * modification, are permitted provided that the following conditions
23664 + * 1. Redistributions of source code must retain the above copyright
23665 + * notice, this list of conditions and the following disclaimer.
23667 + * 2. Redistributions in binary form must reproduce the above copyright
23668 + * notice, this list of conditions and the following disclaimer in the
23669 + * documentation and/or other materials provided with the distribution.
23671 + * 3. Neither the name of JANET(UK) nor the names of its contributors
23672 + * may be used to endorse or promote products derived from this software
23673 + * without specific prior written permission.
23675 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23676 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23677 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23678 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23679 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23680 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23681 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23682 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23683 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23684 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23689 + * Context establishment state machine.
23692 +#include "gssapiP_eap.h"
23694 +/* private flags */
23695 +#define SM_FLAG_TRANSITED 0x80000000
23697 +#define SM_ASSERT_VALID(ctx, status) do { \
23698 + GSSEAP_ASSERT(GSS_ERROR((status)) || \
23699 + ((status) == GSS_S_CONTINUE_NEEDED && ((ctx)->state > GSSEAP_STATE_INITIAL && (ctx)->state < GSSEAP_STATE_ESTABLISHED)) || \
23700 + ((status) == GSS_S_COMPLETE && (ctx)->state == GSSEAP_STATE_ESTABLISHED)); \
23703 +#ifdef GSSEAP_DEBUG
23704 +static const char *
23705 +gssEapStateToString(enum gss_eap_state state)
23710 + case GSSEAP_STATE_INITIAL:
23713 + case GSSEAP_STATE_AUTHENTICATE:
23714 + s = "AUTHENTICATE";
23716 + case GSSEAP_STATE_INITIATOR_EXTS:
23717 + s = "INITIATOR_EXTS";
23719 + case GSSEAP_STATE_ACCEPTOR_EXTS:
23720 + s = "ACCEPTOR_EXTS";
23722 +#ifdef GSSEAP_ENABLE_REAUTH
23723 + case GSSEAP_STATE_REAUTHENTICATE:
23724 + s = "REAUTHENTICATE";
23727 + case GSSEAP_STATE_ESTABLISHED:
23728 + s = "ESTABLISHED";
23739 +gssEapSmTransition(gss_ctx_id_t ctx, enum gss_eap_state state)
23741 + GSSEAP_ASSERT(state >= GSSEAP_STATE_INITIAL);
23742 + GSSEAP_ASSERT(state <= GSSEAP_STATE_ESTABLISHED);
23744 + fprintf(stderr, "GSS-EAP: state transition %s->%s\n",
23745 + gssEapStateToString(GSSEAP_SM_STATE(ctx)),
23746 + gssEapStateToString(state));
23748 + ctx->state = state;
23750 +#endif /* GSSEAP_DEBUG */
23753 +makeErrorToken(OM_uint32 *minor,
23754 + OM_uint32 majorStatus,
23755 + OM_uint32 minorStatus,
23756 + struct gss_eap_token_buffer_set *token)
23758 + OM_uint32 major, tmpMinor;
23759 + unsigned char errorData[8];
23760 + gss_buffer_desc errorBuffer;
23762 + GSSEAP_ASSERT(GSS_ERROR(majorStatus));
23765 + * Only return error codes that the initiator could have caused,
23766 + * to avoid information leakage.
23768 + if (IS_RADIUS_ERROR(minorStatus)) {
23769 + /* Squash RADIUS error codes */
23770 + minorStatus = GSSEAP_RADIUS_PROT_FAILURE;
23771 + } else if (!IS_WIRE_ERROR(minorStatus)) {
23772 + /* Don't return non-wire error codes */
23773 + return GSS_S_COMPLETE;
23776 + minorStatus -= ERROR_TABLE_BASE_eapg;
23778 + store_uint32_be(majorStatus, &errorData[0]);
23779 + store_uint32_be(minorStatus, &errorData[4]);
23781 + major = gssEapAllocInnerTokens(&tmpMinor, 1, token);
23782 + if (GSS_ERROR(major)) {
23783 + *minor = tmpMinor;
23787 + errorBuffer.length = sizeof(errorData);
23788 + errorBuffer.value = errorData;
23790 + major = duplicateBuffer(&tmpMinor, &errorBuffer, &token->buffers.elements[0]);
23791 + if (GSS_ERROR(major)) {
23792 + gssEapReleaseInnerTokens(&tmpMinor, token, 1);
23793 + *minor = tmpMinor;
23797 + token->buffers.count = 1;
23798 + token->types[0] = ITOK_TYPE_CONTEXT_ERR | ITOK_FLAG_CRITICAL;
23801 + return GSS_S_COMPLETE;
23805 +gssEapSmStep(OM_uint32 *minor,
23806 + gss_cred_id_t cred,
23807 + gss_ctx_id_t ctx,
23808 + gss_name_t target,
23810 + OM_uint32 reqFlags,
23811 + OM_uint32 timeReq,
23812 + gss_channel_bindings_t chanBindings,
23813 + gss_buffer_t inputToken,
23814 + gss_buffer_t outputToken,
23815 + struct gss_eap_sm *sm, /* ordered by state */
23818 + OM_uint32 major, tmpMajor, tmpMinor;
23819 + struct gss_eap_token_buffer_set inputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
23820 + struct gss_eap_token_buffer_set outputTokens = { { 0, GSS_C_NO_BUFFER }, NULL };
23821 + gss_buffer_desc unwrappedInputToken = GSS_C_EMPTY_BUFFER;
23822 + gss_buffer_desc unwrappedOutputToken = GSS_C_EMPTY_BUFFER;
23823 + unsigned int smFlags = 0;
23825 + int initialContextToken = 0;
23826 + enum gss_eap_token_type tokType;
23828 + GSSEAP_ASSERT(smCount > 0);
23832 + outputToken->length = 0;
23833 + outputToken->value = NULL;
23835 + if (inputToken != GSS_C_NO_BUFFER && inputToken->length != 0) {
23836 + major = gssEapVerifyToken(minor, ctx, inputToken, &tokType,
23837 + &unwrappedInputToken);
23838 + if (GSS_ERROR(major))
23841 + if (tokType != (CTX_IS_INITIATOR(ctx)
23842 + ? TOK_TYPE_ACCEPTOR_CONTEXT : TOK_TYPE_INITIATOR_CONTEXT)) {
23843 + major = GSS_S_DEFECTIVE_TOKEN;
23844 + *minor = GSSEAP_WRONG_TOK_ID;
23847 + } else if (!CTX_IS_INITIATOR(ctx) || ctx->state != GSSEAP_STATE_INITIAL) {
23848 + major = GSS_S_DEFECTIVE_TOKEN;
23849 + *minor = GSSEAP_WRONG_SIZE;
23852 + initialContextToken = 1;
23855 + if (CTX_IS_ESTABLISHED(ctx)) {
23856 + major = GSS_S_BAD_STATUS;
23857 + *minor = GSSEAP_CONTEXT_ESTABLISHED;
23861 + GSSEAP_ASSERT(ctx->state < GSSEAP_STATE_ESTABLISHED);
23863 + major = gssEapDecodeInnerTokens(minor, &unwrappedInputToken, &inputTokens);
23864 + if (GSS_ERROR(major))
23867 + major = gssEapAllocInnerTokens(minor, smCount, &outputTokens);
23868 + if (GSS_ERROR(major))
23871 + ctx->inputTokens = &inputTokens;
23872 + ctx->outputTokens = &outputTokens;
23874 + /* Process all the tokens that are valid for the current state. */
23875 + for (i = 0; i < smCount; i++) {
23876 + struct gss_eap_sm *smp = &sm[i];
23877 + int processToken = 0;
23878 + gss_buffer_t innerInputToken = GSS_C_NO_BUFFER;
23879 + OM_uint32 *inputTokenType = NULL;
23880 + gss_buffer_desc innerOutputToken = GSS_C_EMPTY_BUFFER;
23882 + if ((smp->validStates & ctx->state) == 0)
23886 + * We special case the first call to gss_init_sec_context so that
23887 + * all token providers have the opportunity to generate an initial
23888 + * context token. Providers where inputTokenType is ITOK_TYPE_NONE
23889 + * are always called and generally act on state transition boundaries,
23890 + * for example to advance the state after a series of optional tokens
23891 + * (as is the case with the extension token exchange) or to generate
23892 + * a new token after the state was advanced by a provider which did
23893 + * not emit a token.
23895 + if (smp->inputTokenType == ITOK_TYPE_NONE || initialContextToken) {
23896 + processToken = 1;
23897 + } else if ((smFlags & SM_FLAG_TRANSITED) == 0) {
23898 + /* Don't regurgitate a token which belonds to a previous state. */
23899 + for (j = 0; j < inputTokens.buffers.count; j++) {
23900 + if ((inputTokens.types[j] & ITOK_TYPE_MASK) == smp->inputTokenType) {
23901 + if (processToken) {
23902 + /* Check for duplicate inner tokens */
23903 + major = GSS_S_DEFECTIVE_TOKEN;
23904 + *minor = GSSEAP_DUPLICATE_ITOK;
23907 + processToken = 1;
23908 + innerInputToken = &inputTokens.buffers.elements[j];
23909 + inputTokenType = &inputTokens.types[j];
23912 + if (GSS_ERROR(major))
23916 + if (processToken) {
23917 + enum gss_eap_state oldState = ctx->state;
23920 + if (inputTokenType != NULL && (*inputTokenType & ITOK_FLAG_CRITICAL))
23921 + smFlags |= SM_FLAG_INPUT_TOKEN_CRITICAL;
23923 + major = smp->processToken(minor, cred, ctx, target, mech, reqFlags,
23924 + timeReq, chanBindings, innerInputToken,
23925 + &innerOutputToken, &smFlags);
23926 + if (GSS_ERROR(major))
23929 + if (inputTokenType != NULL)
23930 + *inputTokenType |= ITOK_FLAG_VERIFIED;
23931 + if (ctx->state < oldState)
23932 + i = 0; /* restart */
23933 + else if (ctx->state != oldState)
23934 + smFlags |= SM_FLAG_TRANSITED;
23936 + if (innerOutputToken.value != NULL) {
23937 + outputTokens.buffers.elements[outputTokens.buffers.count] = innerOutputToken;
23938 + GSSEAP_ASSERT(smp->outputTokenType != ITOK_TYPE_NONE);
23939 + outputTokens.types[outputTokens.buffers.count] = smp->outputTokenType;
23940 + if (smFlags & SM_FLAG_OUTPUT_TOKEN_CRITICAL)
23941 + outputTokens.types[outputTokens.buffers.count] |= ITOK_FLAG_CRITICAL;
23942 + outputTokens.buffers.count++;
23945 + * Break out if we made a state transition and have some tokens to send.
23947 + if ((smFlags & SM_FLAG_TRANSITED) &&
23948 + ((smFlags & SM_FLAG_FORCE_SEND_TOKEN) || outputTokens.buffers.count != 0)) {
23949 + SM_ASSERT_VALID(ctx, major);
23952 + } else if ((smp->itokFlags & SM_ITOK_FLAG_REQUIRED) &&
23953 + smp->inputTokenType != ITOK_TYPE_NONE) {
23954 + /* Check for required inner tokens */
23955 + major = GSS_S_DEFECTIVE_TOKEN;
23956 + *minor = GSSEAP_MISSING_REQUIRED_ITOK;
23961 + GSSEAP_ASSERT(outputTokens.buffers.count <= smCount);
23963 + /* Check we understood all critical tokens sent by peer */
23964 + if (!GSS_ERROR(major)) {
23965 + for (j = 0; j < inputTokens.buffers.count; j++) {
23966 + if ((inputTokens.types[j] & ITOK_FLAG_CRITICAL) &&
23967 + (inputTokens.types[j] & ITOK_FLAG_VERIFIED) == 0) {
23968 + major = GSS_S_UNAVAILABLE;
23969 + *minor = GSSEAP_CRIT_ITOK_UNAVAILABLE;
23975 + /* Optionaly emit an error token if we are the acceptor */
23976 + if (GSS_ERROR(major)) {
23977 + if (CTX_IS_INITIATOR(ctx))
23978 + goto cleanup; /* return error directly to caller */
23980 + /* replace any emitted tokens with error token */
23981 + gssEapReleaseInnerTokens(&tmpMinor, &outputTokens, 1);
23983 + tmpMajor = makeErrorToken(&tmpMinor, major, *minor, &outputTokens);
23984 + if (GSS_ERROR(tmpMajor)) {
23985 + major = tmpMajor;
23986 + *minor = tmpMinor;
23991 + /* Format output token from inner tokens */
23992 + if (outputTokens.buffers.count != 0 || /* inner tokens to send */
23993 + !CTX_IS_INITIATOR(ctx) || /* any leg acceptor */
23994 + !CTX_IS_ESTABLISHED(ctx)) { /* non-last leg initiator */
23995 + tmpMajor = gssEapEncodeInnerTokens(&tmpMinor, &outputTokens, &unwrappedOutputToken);
23996 + if (tmpMajor == GSS_S_COMPLETE) {
23997 + if (CTX_IS_INITIATOR(ctx))
23998 + tokType = TOK_TYPE_INITIATOR_CONTEXT;
24000 + tokType = TOK_TYPE_ACCEPTOR_CONTEXT;
24002 + tmpMajor = gssEapMakeToken(&tmpMinor, ctx, &unwrappedOutputToken,
24003 + tokType, outputToken);
24004 + if (GSS_ERROR(tmpMajor)) {
24005 + major = tmpMajor;
24006 + *minor = tmpMinor;
24012 + /* If the context is established, empty tokens only to be emitted by initiator */
24013 + GSSEAP_ASSERT(!CTX_IS_ESTABLISHED(ctx) || ((outputToken->length == 0) == CTX_IS_INITIATOR(ctx)));
24015 + SM_ASSERT_VALID(ctx, major);
24018 + gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 0);
24019 + gssEapReleaseInnerTokens(&tmpMinor, &inputTokens, 1);
24021 + gss_release_buffer(&tmpMinor, &unwrappedOutputToken);
24023 + ctx->inputTokens = NULL;
24024 + ctx->outputTokens = NULL;
24028 diff --git a/mech_eap/util_tld.c b/mech_eap/util_tld.c
24029 new file mode 100644
24030 index 0000000..05bc3d1
24032 +++ b/mech_eap/util_tld.c
24035 + * Copyright (c) 2011, JANET(UK)
24036 + * All rights reserved.
24038 + * Redistribution and use in source and binary forms, with or without
24039 + * modification, are permitted provided that the following conditions
24042 + * 1. Redistributions of source code must retain the above copyright
24043 + * notice, this list of conditions and the following disclaimer.
24045 + * 2. Redistributions in binary form must reproduce the above copyright
24046 + * notice, this list of conditions and the following disclaimer in the
24047 + * documentation and/or other materials provided with the distribution.
24049 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24050 + * may be used to endorse or promote products derived from this software
24051 + * without specific prior written permission.
24053 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24054 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24055 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24056 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24057 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24058 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24059 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24060 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24061 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24062 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24067 + * Thread local data abstraction, using pthreads on Unix and the TlsXXX
24068 + * APIs on Windows.
24071 +#include "gssapiP_eap.h"
24073 +/* Clean up thread-local data; called on thread detach */
24075 +destroyThreadLocalData(struct gss_eap_thread_local_data *tld)
24077 + if (tld->statusInfo != NULL)
24078 + gssEapDestroyStatusInfo(tld->statusInfo);
24079 + if (tld->krbContext != NULL)
24080 + gssEapDestroyKrbContext(tld->krbContext);
24081 + GSSEAP_FREE(tld);
24087 + * This is the TLS index returned by TlsAlloc() on process init.
24088 + * Each thread, on thread attach in DllMain(), allocates its thread-local
24089 + * data and uses this index with TlsSetValue() to store it.
24090 + * It can then subsequently be retrieved with TlsGetValue().
24092 +static DWORD tlsIndex = TLS_OUT_OF_INDEXES;
24094 +/* Access thread-local data */
24095 +struct gss_eap_thread_local_data *
24096 +gssEapGetThreadLocalData(void)
24098 + struct gss_eap_thread_local_data *tlsData;
24100 + GSSEAP_ASSERT(tlsIndex != TLS_OUT_OF_INDEXES);
24102 + tlsData = TlsGetValue(tlsIndex);
24103 + if (tlsData == NULL) {
24104 + tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
24105 + TlsSetValue(tlsIndex, tlsData);
24112 +DllMain(HINSTANCE hDLL, /* DLL module handle */
24113 + DWORD reason, /* reason called */
24114 + LPVOID reserved) /* reserved */
24116 + struct gss_eap_thread_local_data *tlsData;
24117 + OM_uint32 major, minor;
24119 + switch (reason) {
24120 + case DLL_PROCESS_ATTACH:
24121 + /* Allocate a TLS index. */
24122 + major = gssEapInitiatorInit(&minor);
24123 + if (GSS_ERROR(major))
24126 + tlsIndex = TlsAlloc();
24127 + if (tlsIndex == TLS_OUT_OF_INDEXES)
24129 + /* No break: Initialize the index for first thread.*/
24130 + case DLL_THREAD_ATTACH:
24131 + /* Initialize the TLS index for this thread. */
24132 + tlsData = GSSEAP_CALLOC(1, sizeof(*tlsData));
24133 + if (tlsData == NULL)
24135 + TlsSetValue(tlsIndex, tlsData);
24137 + case DLL_THREAD_DETACH:
24138 + /* Release the allocated memory for this thread. */
24139 + tlsData = TlsGetValue(tlsIndex);
24140 + if (tlsData != NULL) {
24141 + destroyThreadLocalData(tlsData);
24142 + TlsSetValue(tlsIndex, NULL);
24145 + case DLL_PROCESS_DETACH:
24146 + /* Release the TLS index. */
24147 + TlsFree(tlsIndex);
24148 + gssEapFinalize();
24155 + UNREFERENCED_PARAMETER(hDLL);
24156 + UNREFERENCED_PARAMETER(reserved);
24161 +/* pthreads implementation */
24163 +static GSSEAP_THREAD_ONCE tldKeyOnce = GSSEAP_ONCE_INITIALIZER;
24164 +static GSSEAP_THREAD_KEY tldKey;
24167 +pthreadDestroyThreadLocalData(void *arg)
24169 + struct gss_eap_thread_local_data* tld = arg;
24172 + destroyThreadLocalData(tld);
24176 +createThreadLocalDataKey(void)
24178 + GSSEAP_KEY_CREATE(&tldKey, pthreadDestroyThreadLocalData);
24181 +struct gss_eap_thread_local_data *
24182 +gssEapGetThreadLocalData()
24184 + struct gss_eap_thread_local_data *tld;
24186 + GSSEAP_ONCE(&tldKeyOnce, createThreadLocalDataKey);
24188 + tld = GSSEAP_GETSPECIFIC(tldKey);
24189 + if (tld == NULL) {
24190 + tld = GSSEAP_CALLOC(1, sizeof(*tld));
24194 + GSSEAP_SETSPECIFIC(tldKey, tld);
24200 +#endif /* WIN32 */
24201 diff --git a/mech_eap/util_token.c b/mech_eap/util_token.c
24202 new file mode 100644
24203 index 0000000..a1aea0c
24205 +++ b/mech_eap/util_token.c
24208 + * Copyright (c) 2011, JANET(UK)
24209 + * All rights reserved.
24211 + * Redistribution and use in source and binary forms, with or without
24212 + * modification, are permitted provided that the following conditions
24215 + * 1. Redistributions of source code must retain the above copyright
24216 + * notice, this list of conditions and the following disclaimer.
24218 + * 2. Redistributions in binary form must reproduce the above copyright
24219 + * notice, this list of conditions and the following disclaimer in the
24220 + * documentation and/or other materials provided with the distribution.
24222 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24223 + * may be used to endorse or promote products derived from this software
24224 + * without specific prior written permission.
24226 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24227 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24228 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24229 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24230 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24231 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24232 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24233 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24234 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24235 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24239 + * Portions Copyright 1993 by OpenVision Technologies, Inc.
24241 + * Permission to use, copy, modify, distribute, and sell this software
24242 + * and its documentation for any purpose is hereby granted without fee,
24243 + * provided that the above copyright notice appears in all copies and
24244 + * that both that copyright notice and this permission notice appear in
24245 + * supporting documentation, and that the name of OpenVision not be used
24246 + * in advertising or publicity pertaining to distribution of the software
24247 + * without specific, written prior permission. OpenVision makes no
24248 + * representations about the suitability of this software for any
24249 + * purpose. It is provided "as is" without express or implied warranty.
24251 + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24252 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
24253 + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24254 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24255 + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
24256 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24257 + * PERFORMANCE OF THIS SOFTWARE.
24261 + * Utility routines for GSS tokens.
24264 +#include "gssapiP_eap.h"
24267 +gssEapEncodeInnerTokens(OM_uint32 *minor,
24268 + struct gss_eap_token_buffer_set *tokens,
24269 + gss_buffer_t buffer)
24271 + OM_uint32 major, tmpMinor;
24272 + size_t required = 0, i;
24273 + unsigned char *p;
24275 + buffer->value = NULL;
24276 + buffer->length = 0;
24278 + for (i = 0; i < tokens->buffers.count; i++) {
24279 + required += 8 + tokens->buffers.elements[i].length;
24283 + * We must always return a non-NULL token otherwise the calling state
24284 + * machine assumes we are finished. Hence care in case malloc(0) does
24287 + buffer->value = GSSEAP_MALLOC(required ? required : 1);
24288 + if (buffer->value == NULL) {
24289 + major = GSS_S_FAILURE;
24294 + buffer->length = required;
24295 + p = (unsigned char *)buffer->value;
24297 + for (i = 0; i < tokens->buffers.count; i++) {
24298 + gss_buffer_t tokenBuffer = &tokens->buffers.elements[i];
24300 + GSSEAP_ASSERT((tokens->types[i] & ITOK_FLAG_VERIFIED) == 0); /* private flag */
24303 + * Extensions are encoded as type-length-value, where the upper
24304 + * bit of the type indicates criticality.
24306 + store_uint32_be(tokens->types[i], &p[0]);
24307 + store_uint32_be(tokenBuffer->length, &p[4]);
24308 + memcpy(&p[8], tokenBuffer->value, tokenBuffer->length);
24310 + p += 8 + tokenBuffer->length;
24313 + GSSEAP_ASSERT(p == (unsigned char *)buffer->value + required);
24314 + GSSEAP_ASSERT(buffer->value != NULL);
24316 + major = GSS_S_COMPLETE;
24320 + if (GSS_ERROR(major)) {
24321 + gss_release_buffer(&tmpMinor, buffer);
24328 +gssEapDecodeInnerTokens(OM_uint32 *minor,
24329 + const gss_buffer_t buffer,
24330 + struct gss_eap_token_buffer_set *tokens)
24332 + OM_uint32 major, tmpMinor;
24333 + unsigned char *p;
24334 + size_t count = 0;
24337 + tokens->buffers.count = 0;
24338 + tokens->buffers.elements = NULL;
24339 + tokens->types = NULL;
24341 + if (buffer->length == 0) {
24342 + major = GSS_S_COMPLETE;
24346 + p = (unsigned char *)buffer->value;
24347 + remain = buffer->length;
24350 + OM_uint32 *ntypes;
24351 + gss_buffer_desc tokenBuffer, *newTokenBuffers;
24353 + if (remain < 8) {
24354 + major = GSS_S_DEFECTIVE_TOKEN;
24355 + *minor = GSSEAP_TOK_TRUNC;
24359 + if (tokens->buffers.count <= count) {
24365 + ntypes = GSSEAP_MALLOC(count * sizeof(OM_uint32));
24366 + if (ntypes == NULL) {
24367 + major = GSS_S_FAILURE;
24371 + if (tokens->types != NULL) {
24372 + memcpy(ntypes, tokens->types, tokens->buffers.count * sizeof(OM_uint32));
24373 + GSSEAP_FREE(tokens->types);
24375 + tokens->types = ntypes;
24377 + newTokenBuffers = GSSEAP_MALLOC(count * sizeof(gss_buffer_desc));
24378 + if (newTokenBuffers == NULL) {
24379 + major = GSS_S_FAILURE;
24383 + if (tokens->buffers.elements != NULL) {
24384 + memcpy(newTokenBuffers, tokens->buffers.elements,
24385 + tokens->buffers.count * sizeof(gss_buffer_desc));
24386 + GSSEAP_FREE(tokens->buffers.elements);
24388 + tokens->buffers.elements = newTokenBuffers;
24391 + tokens->types[tokens->buffers.count] = load_uint32_be(&p[0]);
24392 + tokenBuffer.length = load_uint32_be(&p[4]);
24394 + if (remain < 8 + tokenBuffer.length) {
24395 + major = GSS_S_DEFECTIVE_TOKEN;
24396 + *minor = GSSEAP_TOK_TRUNC;
24399 + tokenBuffer.value = &p[8];
24401 + tokens->buffers.elements[tokens->buffers.count] = tokenBuffer;
24402 + tokens->buffers.count++;
24404 + p += 8 + tokenBuffer.length;
24405 + remain -= 8 + tokenBuffer.length;
24406 + } while (remain != 0);
24408 + major = GSS_S_COMPLETE;
24412 + if (GSS_ERROR(major))
24413 + gssEapReleaseInnerTokens(&tmpMinor, tokens, 0);
24419 + * $Id: util_token.c 23457 2009-12-08 00:04:48Z tlyu $
24422 +/* XXXX this code currently makes the assumption that a mech oid will
24423 + never be longer than 127 bytes. This assumption is not inherent in
24424 + the interfaces, so the code can be fixed if the OSI namespace
24425 + balloons unexpectedly. */
24428 + * Each token looks like this:
24429 + * 0x60 tag for APPLICATION 0, SEQUENCE
24430 + * (constructed, definite-length)
24431 + * <length> possible multiple bytes, need to parse/generate
24432 + * 0x06 tag for OBJECT IDENTIFIER
24433 + * <moid_length> compile-time constant string (assume 1 byte)
24434 + * <moid_bytes> compile-time constant string
24435 + * <inner_bytes> the ANY containing the application token
24436 + * bytes 0,1 are the token type
24437 + * bytes 2,n are the token data
24439 + * Note that the token type field is a feature of RFC 1964 mechanisms and
24440 + * is not used by other GSSAPI mechanisms. As such, a token type of -1
24441 + * is interpreted to mean that no token type should be expected or
24444 + * For the purposes of this abstraction, the token "header" consists of
24445 + * the sequence tag and length octets, the mech OID DER encoding, and the
24446 + * first two inner bytes, which indicate the token type. The token
24447 + * "body" consists of everything else.
24451 +der_length_size(size_t length)
24453 + if (length < (1<<7))
24455 + else if (length < (1<<8))
24457 +#if INT_MAX == 0x7fff
24461 + else if (length < (1<<16))
24463 + else if (length < (1<<24))
24471 +der_write_length(unsigned char **buf, size_t length)
24473 + if (length < (1<<7)) {
24474 + *(*buf)++ = (unsigned char)length;
24476 + *(*buf)++ = (unsigned char)(der_length_size(length)+127);
24477 +#if INT_MAX > 0x7fff
24478 + if (length >= (1<<24))
24479 + *(*buf)++ = (unsigned char)(length>>24);
24480 + if (length >= (1<<16))
24481 + *(*buf)++ = (unsigned char)((length>>16)&0xff);
24483 + if (length >= (1<<8))
24484 + *(*buf)++ = (unsigned char)((length>>8)&0xff);
24485 + *(*buf)++ = (unsigned char)(length&0xff);
24489 +/* returns decoded length, or < 0 on failure. Advances buf and
24490 + decrements bufsize */
24493 +der_read_length(unsigned char **buf, ssize_t *bufsize)
24495 + unsigned char sf;
24498 + if (*bufsize < 1)
24504 + if ((sf &= 0x7f) > ((*bufsize)-1))
24506 + if (sf > sizeof(int))
24509 + for (; sf; sf--) {
24510 + ret = (ret<<8) + (*(*buf)++);
24520 +/* returns the length of a token, given the mech oid and the body size */
24523 +tokenSize(const gss_OID_desc *mech, size_t body_size)
24525 + GSSEAP_ASSERT(mech != GSS_C_NO_OID);
24527 + /* set body_size to sequence contents size */
24528 + body_size += 4 + (size_t) mech->length; /* NEED overflow check */
24529 + return 1 + der_length_size(body_size) + body_size;
24532 +/* fills in a buffer with the token header. The buffer is assumed to
24533 + be the right size. buf is advanced past the token header */
24537 + const gss_OID_desc *mech,
24538 + size_t body_size,
24539 + unsigned char **buf,
24540 + enum gss_eap_token_type tok_type)
24542 + *(*buf)++ = 0x60;
24543 + der_write_length(buf, (tok_type == -1) ?2:4 + mech->length + body_size);
24544 + *(*buf)++ = 0x06;
24545 + *(*buf)++ = (unsigned char)mech->length;
24546 + memcpy(*buf, mech->elements, mech->length);
24547 + *buf += mech->length;
24548 + GSSEAP_ASSERT(tok_type != TOK_TYPE_NONE);
24549 + *(*buf)++ = (unsigned char)((tok_type>>8) & 0xff);
24550 + *(*buf)++ = (unsigned char)(tok_type & 0xff);
24554 + * Given a buffer containing a token, reads and verifies the token,
24555 + * leaving buf advanced past the token header, and setting body_size
24556 + * to the number of remaining bytes. Returns 0 on success,
24557 + * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
24558 + * mechanism in the token does not match the mech argument. buf and
24559 + * *body_size are left unmodified on error.
24563 +verifyTokenHeader(OM_uint32 *minor,
24565 + size_t *body_size,
24566 + unsigned char **buf_in,
24567 + size_t toksize_in,
24568 + enum gss_eap_token_type *ret_tok_type)
24570 + unsigned char *buf = *buf_in;
24572 + gss_OID_desc toid;
24573 + ssize_t toksize = (ssize_t)toksize_in;
24575 + *minor = GSSEAP_BAD_TOK_HEADER;
24577 + if (ret_tok_type != NULL)
24578 + *ret_tok_type = TOK_TYPE_NONE;
24580 + if ((toksize -= 1) < 0)
24581 + return GSS_S_DEFECTIVE_TOKEN;
24583 + if (*buf++ != 0x60)
24584 + return GSS_S_DEFECTIVE_TOKEN;
24586 + seqsize = der_read_length(&buf, &toksize);
24588 + return GSS_S_DEFECTIVE_TOKEN;
24590 + if (seqsize != toksize)
24591 + return GSS_S_DEFECTIVE_TOKEN;
24593 + if ((toksize -= 1) < 0)
24594 + return GSS_S_DEFECTIVE_TOKEN;
24596 + if (*buf++ != 0x06)
24597 + return GSS_S_DEFECTIVE_TOKEN;
24599 + if ((toksize -= 1) < 0)
24600 + return GSS_S_DEFECTIVE_TOKEN;
24602 + toid.length = *buf++;
24604 + if ((toksize -= toid.length) < 0)
24605 + return GSS_S_DEFECTIVE_TOKEN;
24607 + toid.elements = buf;
24608 + buf += toid.length;
24610 + if (mech->elements == NULL) {
24612 + if (toid.length == 0)
24613 + return GSS_S_BAD_MECH;
24614 + } else if (!oidEqual(&toid, mech)) {
24615 + *minor = GSSEAP_WRONG_MECH;
24616 + return GSS_S_BAD_MECH;
24619 + if (ret_tok_type != NULL) {
24620 + if ((toksize -= 2) < 0)
24621 + return GSS_S_DEFECTIVE_TOKEN;
24623 + *ret_tok_type = load_uint16_be(buf);
24628 + *body_size = toksize;
24631 + return GSS_S_COMPLETE;
24635 +gssEapAllocInnerTokens(OM_uint32 *minor,
24637 + struct gss_eap_token_buffer_set *tokens)
24641 + tokens->buffers.count = 0;
24642 + tokens->buffers.elements = (gss_buffer_desc *)GSSEAP_CALLOC(count, sizeof(gss_buffer_desc));
24643 + if (tokens->buffers.elements == NULL) {
24644 + major = GSS_S_FAILURE;
24649 + tokens->types = (OM_uint32 *)GSSEAP_CALLOC(count, sizeof(OM_uint32));
24650 + if (tokens->types == NULL) {
24651 + major = GSS_S_FAILURE;
24656 + major = GSS_S_COMPLETE;
24660 + if (GSS_ERROR(major)) {
24661 + if (tokens->buffers.elements != NULL) {
24662 + GSSEAP_FREE(tokens->buffers.elements);
24663 + tokens->buffers.elements = NULL;
24665 + if (tokens->types != NULL) {
24666 + GSSEAP_FREE(tokens->types);
24667 + tokens->types = NULL;
24675 +gssEapReleaseInnerTokens(OM_uint32 *minor,
24676 + struct gss_eap_token_buffer_set *tokens,
24679 + OM_uint32 tmpMinor;
24682 + if (tokens->buffers.elements != NULL) {
24683 + if (freeBuffers) {
24684 + for (i = 0; i < tokens->buffers.count; i++)
24685 + gss_release_buffer(&tmpMinor, &tokens->buffers.elements[i]);
24687 + GSSEAP_FREE(tokens->buffers.elements);
24688 + tokens->buffers.elements = NULL;
24690 + tokens->buffers.count = 0;
24692 + if (tokens->types != NULL) {
24693 + GSSEAP_FREE(tokens->types);
24694 + tokens->types = NULL;
24698 + return GSS_S_COMPLETE;
24700 diff --git a/mech_eap/verify_mic.c b/mech_eap/verify_mic.c
24701 new file mode 100644
24702 index 0000000..c0829f5
24704 +++ b/mech_eap/verify_mic.c
24707 + * Copyright (c) 2011, JANET(UK)
24708 + * All rights reserved.
24710 + * Redistribution and use in source and binary forms, with or without
24711 + * modification, are permitted provided that the following conditions
24714 + * 1. Redistributions of source code must retain the above copyright
24715 + * notice, this list of conditions and the following disclaimer.
24717 + * 2. Redistributions in binary form must reproduce the above copyright
24718 + * notice, this list of conditions and the following disclaimer in the
24719 + * documentation and/or other materials provided with the distribution.
24721 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24722 + * may be used to endorse or promote products derived from this software
24723 + * without specific prior written permission.
24725 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24726 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24727 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24728 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24729 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24730 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24731 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24732 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24733 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24734 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24739 + * Message protection services: verify a message integrity check.
24742 +#include "gssapiP_eap.h"
24744 +OM_uint32 GSSAPI_CALLCONV
24745 +gss_verify_mic(OM_uint32 *minor,
24746 + gss_ctx_id_t ctx,
24747 + gss_buffer_t message_buffer,
24748 + gss_buffer_t message_token,
24749 + gss_qop_t *qop_state)
24752 + gss_iov_buffer_desc iov[3];
24755 + if (message_token->length < 16) {
24756 + *minor = GSSEAP_TOK_TRUNC;
24757 + return GSS_S_BAD_SIG;
24762 + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
24763 + iov[0].buffer = *message_buffer;
24765 + iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER;
24766 + iov[1].buffer = *message_token;
24768 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
24770 + major = gssEapUnwrapOrVerifyMIC(minor, ctx, &conf_state, qop_state,
24771 + iov, 2, TOK_TYPE_MIC);
24773 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
24777 diff --git a/mech_eap/wrap.c b/mech_eap/wrap.c
24778 new file mode 100644
24779 index 0000000..2e27fb3
24781 +++ b/mech_eap/wrap.c
24784 + * Copyright (c) 2011, JANET(UK)
24785 + * All rights reserved.
24787 + * Redistribution and use in source and binary forms, with or without
24788 + * modification, are permitted provided that the following conditions
24791 + * 1. Redistributions of source code must retain the above copyright
24792 + * notice, this list of conditions and the following disclaimer.
24794 + * 2. Redistributions in binary form must reproduce the above copyright
24795 + * notice, this list of conditions and the following disclaimer in the
24796 + * documentation and/or other materials provided with the distribution.
24798 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24799 + * may be used to endorse or promote products derived from this software
24800 + * without specific prior written permission.
24802 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24803 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24804 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24805 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24806 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24807 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24808 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24809 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24810 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24811 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24816 + * Message protection services: wrap.
24819 +#include "gssapiP_eap.h"
24821 +OM_uint32 GSSAPI_CALLCONV
24822 +gss_wrap(OM_uint32 *minor,
24823 + gss_ctx_id_t ctx,
24824 + int conf_req_flag,
24825 + gss_qop_t qop_req,
24826 + gss_buffer_t input_message_buffer,
24828 + gss_buffer_t output_message_buffer)
24832 + if (ctx == GSS_C_NO_CONTEXT) {
24834 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
24839 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
24841 + if (!CTX_IS_ESTABLISHED(ctx)) {
24842 + major = GSS_S_NO_CONTEXT;
24843 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
24847 + major = gssEapWrap(minor, ctx, conf_req_flag, qop_req,
24848 + input_message_buffer,
24849 + conf_state, output_message_buffer);
24850 + if (GSS_ERROR(major))
24854 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
24860 +gssEapWrap(OM_uint32 *minor,
24861 + gss_ctx_id_t ctx,
24862 + int conf_req_flag,
24863 + gss_qop_t qop_req,
24864 + gss_buffer_t input_message_buffer,
24866 + gss_buffer_t output_message_buffer)
24868 + OM_uint32 major, tmpMinor;
24869 + gss_iov_buffer_desc iov[4];
24870 + unsigned char *p;
24873 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
24874 + iov[0].buffer.value = NULL;
24875 + iov[0].buffer.length = 0;
24877 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
24878 + iov[1].buffer = *input_message_buffer;
24880 + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
24881 + iov[2].buffer.value = NULL;
24882 + iov[2].buffer.length = 0;
24884 + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
24885 + iov[3].buffer.value = NULL;
24886 + iov[3].buffer.length = 0;
24888 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
24890 + if (GSS_ERROR(major)) {
24894 + for (i = 0, output_message_buffer->length = 0; i < 4; i++) {
24895 + output_message_buffer->length += iov[i].buffer.length;
24898 + output_message_buffer->value = GSSEAP_MALLOC(output_message_buffer->length);
24899 + if (output_message_buffer->value == NULL) {
24901 + return GSS_S_FAILURE;
24904 + for (i = 0, p = output_message_buffer->value; i < 4; i++) {
24905 + if (iov[i].type == GSS_IOV_BUFFER_TYPE_DATA) {
24906 + memcpy(p, input_message_buffer->value, input_message_buffer->length);
24908 + iov[i].buffer.value = p;
24909 + p += iov[i].buffer.length;
24912 + major = gssEapWrapOrGetMIC(minor, ctx, conf_req_flag, conf_state,
24913 + iov, 4, TOK_TYPE_WRAP);
24914 + if (GSS_ERROR(major)) {
24915 + gss_release_buffer(&tmpMinor, output_message_buffer);
24920 diff --git a/mech_eap/wrap_iov.c b/mech_eap/wrap_iov.c
24921 new file mode 100644
24922 index 0000000..be890b6
24924 +++ b/mech_eap/wrap_iov.c
24927 + * Copyright (c) 2011, JANET(UK)
24928 + * All rights reserved.
24930 + * Redistribution and use in source and binary forms, with or without
24931 + * modification, are permitted provided that the following conditions
24934 + * 1. Redistributions of source code must retain the above copyright
24935 + * notice, this list of conditions and the following disclaimer.
24937 + * 2. Redistributions in binary form must reproduce the above copyright
24938 + * notice, this list of conditions and the following disclaimer in the
24939 + * documentation and/or other materials provided with the distribution.
24941 + * 3. Neither the name of JANET(UK) nor the names of its contributors
24942 + * may be used to endorse or promote products derived from this software
24943 + * without specific prior written permission.
24945 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24946 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24947 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24948 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24949 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24950 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24951 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24952 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24953 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24954 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24958 + * Copyright 2008 by the Massachusetts Institute of Technology.
24959 + * All Rights Reserved.
24961 + * Export of this software from the United States of America may
24962 + * require a specific license from the United States Government.
24963 + * It is the responsibility of any person or organization contemplating
24964 + * export to obtain such a license before exporting.
24966 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
24967 + * distribute this software and its documentation for any purpose and
24968 + * without fee is hereby granted, provided that the above copyright
24969 + * notice appear in all copies and that both that copyright notice and
24970 + * this permission notice appear in supporting documentation, and that
24971 + * the name of M.I.T. not be used in advertising or publicity pertaining
24972 + * to distribution of the software without specific, written prior
24973 + * permission. Furthermore if you modify this software you must label
24974 + * your software as modified software and not distribute it in such a
24975 + * fashion that it might be confused with the original M.I.T. software.
24976 + * M.I.T. makes no representations about the suitability of
24977 + * this software for any purpose. It is provided "as is" without express
24978 + * or implied warranty.
24982 + * Message protection services: wrap with scatter-gather API.
24985 +#include "gssapiP_eap.h"
24988 +rfc4121Flags(gss_ctx_id_t ctx, int receiving)
24990 + unsigned char flags;
24993 + isAcceptor = !CTX_IS_INITIATOR(ctx);
24995 + isAcceptor = !isAcceptor;
24999 + flags |= TOK_FLAG_SENDER_IS_ACCEPTOR;
25001 + if ((ctx->flags & CTX_FLAG_KRB_REAUTH) &&
25002 + (ctx->gssFlags & GSS_C_MUTUAL_FLAG))
25003 + flags |= TOK_FLAG_ACCEPTOR_SUBKEY;
25009 +gssEapWrapOrGetMIC(OM_uint32 *minor,
25010 + gss_ctx_id_t ctx,
25011 + int conf_req_flag,
25013 + gss_iov_buffer_desc *iov,
25015 + enum gss_eap_token_type toktype)
25017 + krb5_error_code code = 0;
25018 + gss_iov_buffer_t header;
25019 + gss_iov_buffer_t padding;
25020 + gss_iov_buffer_t trailer;
25021 + unsigned char flags;
25022 + unsigned char *outbuf = NULL;
25023 + unsigned char *tbuf = NULL;
25026 + size_t gssHeaderLen, gssTrailerLen;
25027 + size_t dataLen, assocDataLen;
25028 + krb5_context krbContext;
25029 +#ifdef HAVE_HEIMDAL_VERSION
25030 + krb5_crypto krbCrypto = NULL;
25033 + if (ctx->encryptionType == ENCTYPE_NULL) {
25034 + *minor = GSSEAP_KEY_UNAVAILABLE;
25035 + return GSS_S_UNAVAILABLE;
25038 + GSSEAP_KRB_INIT(&krbContext);
25040 + flags = rfc4121Flags(ctx, FALSE);
25042 + if (toktype == TOK_TYPE_WRAP) {
25043 + keyUsage = CTX_IS_INITIATOR(ctx)
25044 + ? KEY_USAGE_INITIATOR_SEAL
25045 + : KEY_USAGE_ACCEPTOR_SEAL;
25047 + keyUsage = CTX_IS_INITIATOR(ctx)
25048 + ? KEY_USAGE_INITIATOR_SIGN
25049 + : KEY_USAGE_ACCEPTOR_SIGN;
25052 + gssEapIovMessageLength(iov, iov_count, &dataLen, &assocDataLen);
25054 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
25055 + if (header == NULL) {
25056 + *minor = GSSEAP_MISSING_IOV;
25057 + return GSS_S_FAILURE;
25060 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
25061 + if (padding != NULL)
25062 + padding->buffer.length = 0;
25064 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
25066 +#ifdef HAVE_HEIMDAL_VERSION
25067 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
25072 + if (toktype == TOK_TYPE_WRAP && conf_req_flag) {
25073 + size_t krbHeaderLen, krbTrailerLen, krbPadLen;
25074 + size_t ec = 0, confDataLen = dataLen - assocDataLen;
25076 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25077 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
25081 + code = krbPaddingLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25082 + confDataLen + 16 /* E(Header) */,
25087 + if (krbPadLen == 0 && (ctx->gssFlags & GSS_C_DCE_STYLE)) {
25088 + /* Windows rejects AEAD tokens with non-zero EC */
25089 + code = krbBlockSize(krbContext, KRB_CRYPTO_CONTEXT(ctx), &ec);
25095 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25096 + KRB5_CRYPTO_TYPE_TRAILER, &krbTrailerLen);
25100 + gssHeaderLen = 16 /* Header */ + krbHeaderLen;
25101 + gssTrailerLen = ec + 16 /* E(Header) */ + krbTrailerLen;
25103 + if (trailer == NULL) {
25104 + rrc = gssTrailerLen;
25105 + /* Workaround for Windows bug where it rotates by EC + RRC */
25106 + if (ctx->gssFlags & GSS_C_DCE_STYLE)
25108 + gssHeaderLen += gssTrailerLen;
25111 + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
25112 + code = gssEapAllocIov(header, (size_t)gssHeaderLen);
25113 + } else if (header->buffer.length < gssHeaderLen)
25114 + code = GSSEAP_WRONG_SIZE;
25117 + outbuf = (unsigned char *)header->buffer.value;
25118 + header->buffer.length = (size_t)gssHeaderLen;
25120 + if (trailer != NULL) {
25121 + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25122 + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen);
25123 + else if (trailer->buffer.length < gssTrailerLen)
25124 + code = GSSEAP_WRONG_SIZE;
25127 + trailer->buffer.length = (size_t)gssTrailerLen;
25131 + store_uint16_be((uint16_t)toktype, outbuf);
25133 + outbuf[2] = flags
25134 + | (conf_req_flag ? TOK_FLAG_WRAP_CONFIDENTIAL : 0);
25136 + outbuf[3] = 0xFF;
25138 + store_uint16_be(ec, outbuf + 4);
25140 + store_uint16_be(0, outbuf + 6);
25141 + store_uint64_be(ctx->sendSeq, outbuf + 8);
25144 + * EC | copy of header to be encrypted, located in
25145 + * (possibly rotated) trailer
25147 + if (trailer == NULL)
25148 + tbuf = (unsigned char *)header->buffer.value + 16; /* Header */
25150 + tbuf = (unsigned char *)trailer->buffer.value;
25152 + memset(tbuf, 0xFF, ec);
25153 + memcpy(tbuf + ec, header->buffer.value, 16);
25155 + code = gssEapEncrypt(krbContext,
25156 + ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0),
25157 + ec, rrc, KRB_CRYPTO_CONTEXT(ctx),
25158 + keyUsage, iov, iov_count);
25163 + store_uint16_be(rrc, outbuf + 6);
25166 + } else if (toktype == TOK_TYPE_WRAP && !conf_req_flag) {
25167 + wrap_with_checksum:
25169 + gssHeaderLen = 16;
25171 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25172 + KRB5_CRYPTO_TYPE_CHECKSUM, &gssTrailerLen);
25176 + GSSEAP_ASSERT(gssTrailerLen <= 0xFFFF);
25178 + if (trailer == NULL) {
25179 + rrc = gssTrailerLen;
25180 + gssHeaderLen += gssTrailerLen;
25183 + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25184 + code = gssEapAllocIov(header, (size_t)gssHeaderLen);
25185 + else if (header->buffer.length < gssHeaderLen)
25186 + code = GSSEAP_WRONG_SIZE;
25189 + outbuf = (unsigned char *)header->buffer.value;
25190 + header->buffer.length = (size_t)gssHeaderLen;
25192 + if (trailer != NULL) {
25193 + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
25194 + code = gssEapAllocIov(trailer, (size_t)gssTrailerLen);
25195 + else if (trailer->buffer.length < gssTrailerLen)
25196 + code = GSSEAP_WRONG_SIZE;
25199 + trailer->buffer.length = (size_t)gssTrailerLen;
25203 + store_uint16_be((uint16_t)toktype, outbuf);
25205 + outbuf[2] = flags;
25207 + outbuf[3] = 0xFF;
25208 + if (toktype == TOK_TYPE_WRAP) {
25209 + /* Use 0 for checksum calculation, substitute
25210 + * checksum length later.
25213 + store_uint16_be(0, outbuf + 4);
25215 + store_uint16_be(0, outbuf + 6);
25217 + /* MIC and DEL store 0xFF in EC and RRC */
25218 + store_uint16_be(0xFFFF, outbuf + 4);
25219 + store_uint16_be(0xFFFF, outbuf + 6);
25221 + store_uint64_be(ctx->sendSeq, outbuf + 8);
25223 + code = gssEapSign(krbContext, ctx->checksumType, rrc,
25224 + KRB_CRYPTO_CONTEXT(ctx), keyUsage,
25231 + if (toktype == TOK_TYPE_WRAP) {
25232 + /* Fix up EC field */
25233 + store_uint16_be(gssTrailerLen, outbuf + 4);
25234 + /* Fix up RRC field */
25235 + store_uint16_be(rrc, outbuf + 6);
25237 + } else if (toktype == TOK_TYPE_MIC) {
25239 + goto wrap_with_checksum;
25240 + } else if (toktype == TOK_TYPE_DELETE_CONTEXT) {
25242 + goto wrap_with_checksum;
25248 + if (conf_state != NULL)
25249 + *conf_state = conf_req_flag;
25253 + gssEapReleaseIov(iov, iov_count);
25254 +#ifdef HAVE_HEIMDAL_VERSION
25255 + if (krbCrypto != NULL)
25256 + krb5_crypto_destroy(krbContext, krbCrypto);
25261 + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
25264 +OM_uint32 GSSAPI_CALLCONV
25265 +gss_wrap_iov(OM_uint32 *minor,
25266 + gss_ctx_id_t ctx,
25267 + int conf_req_flag,
25268 + gss_qop_t qop_req,
25270 + gss_iov_buffer_desc *iov,
25275 + if (ctx == GSS_C_NO_CONTEXT) {
25277 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25280 + if (qop_req != GSS_C_QOP_DEFAULT) {
25281 + *minor = GSSEAP_UNKNOWN_QOP;
25282 + return GSS_S_UNAVAILABLE;
25287 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25289 + if (!CTX_IS_ESTABLISHED(ctx)) {
25290 + major = GSS_S_NO_CONTEXT;
25291 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25295 + major = gssEapWrapOrGetMIC(minor, ctx, conf_req_flag, conf_state,
25296 + iov, iov_count, TOK_TYPE_WRAP);
25297 + if (GSS_ERROR(major))
25301 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
25305 diff --git a/mech_eap/wrap_iov_length.c b/mech_eap/wrap_iov_length.c
25306 new file mode 100644
25307 index 0000000..247b78d
25309 +++ b/mech_eap/wrap_iov_length.c
25312 + * Copyright (c) 2011, JANET(UK)
25313 + * All rights reserved.
25315 + * Redistribution and use in source and binary forms, with or without
25316 + * modification, are permitted provided that the following conditions
25319 + * 1. Redistributions of source code must retain the above copyright
25320 + * notice, this list of conditions and the following disclaimer.
25322 + * 2. Redistributions in binary form must reproduce the above copyright
25323 + * notice, this list of conditions and the following disclaimer in the
25324 + * documentation and/or other materials provided with the distribution.
25326 + * 3. Neither the name of JANET(UK) nor the names of its contributors
25327 + * may be used to endorse or promote products derived from this software
25328 + * without specific prior written permission.
25330 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25331 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25332 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25333 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25334 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25335 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25336 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25337 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25338 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25339 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25343 + * Copyright 2008 by the Massachusetts Institute of Technology.
25344 + * All Rights Reserved.
25346 + * Export of this software from the United States of America may
25347 + * require a specific license from the United States Government.
25348 + * It is the responsibility of any person or organization contemplating
25349 + * export to obtain such a license before exporting.
25351 + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
25352 + * distribute this software and its documentation for any purpose and
25353 + * without fee is hereby granted, provided that the above copyright
25354 + * notice appear in all copies and that both that copyright notice and
25355 + * this permission notice appear in supporting documentation, and that
25356 + * the name of M.I.T. not be used in advertising or publicity pertaining
25357 + * to distribution of the software without specific, written prior
25358 + * permission. Furthermore if you modify this software you must label
25359 + * your software as modified software and not distribute it in such a
25360 + * fashion that it might be confused with the original M.I.T. software.
25361 + * M.I.T. makes no representations about the suitability of
25362 + * this software for any purpose. It is provided "as is" without express
25363 + * or implied warranty.
25367 + * Message protection services: determine protected message size.
25370 +#include "gssapiP_eap.h"
25372 +#define INIT_IOV_DATA(_iov) do { (_iov)->buffer.value = NULL; \
25373 + (_iov)->buffer.length = 0; } \
25377 +gssEapWrapIovLength(OM_uint32 *minor,
25378 + gss_ctx_id_t ctx,
25379 + int conf_req_flag,
25380 + gss_qop_t qop_req,
25382 + gss_iov_buffer_desc *iov,
25385 + gss_iov_buffer_t header, trailer, padding;
25386 + size_t dataLength, assocDataLength;
25387 + size_t gssHeaderLen, gssPadLen, gssTrailerLen;
25388 + size_t krbHeaderLen = 0, krbTrailerLen = 0, krbPadLen = 0;
25389 + krb5_error_code code;
25390 + krb5_context krbContext;
25393 +#ifdef HAVE_HEIMDAL_VERSION
25394 + krb5_crypto krbCrypto = NULL;
25397 + if (qop_req != GSS_C_QOP_DEFAULT) {
25398 + *minor = GSSEAP_UNKNOWN_QOP;
25399 + return GSS_S_UNAVAILABLE;
25402 + if (ctx->encryptionType == ENCTYPE_NULL) {
25403 + *minor = GSSEAP_KEY_UNAVAILABLE;
25404 + return GSS_S_UNAVAILABLE;
25407 + GSSEAP_KRB_INIT(&krbContext);
25409 + header = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
25410 + if (header == NULL) {
25411 + *minor = GSSEAP_MISSING_IOV;
25412 + return GSS_S_FAILURE;
25414 + INIT_IOV_DATA(header);
25416 + trailer = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
25417 + if (trailer != NULL) {
25418 + INIT_IOV_DATA(trailer);
25421 + dce_style = ((ctx->gssFlags & GSS_C_DCE_STYLE) != 0);
25423 + /* For CFX, EC is used instead of padding, and is placed in header or trailer */
25424 + padding = gssEapLocateIov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
25425 + if (padding != NULL) {
25426 + INIT_IOV_DATA(padding);
25429 + gssEapIovMessageLength(iov, iov_count, &dataLength, &assocDataLength);
25431 + if (conf_req_flag && gssEapIsIntegrityOnly(iov, iov_count))
25432 + conf_req_flag = FALSE;
25434 + gssHeaderLen = gssPadLen = gssTrailerLen = 0;
25436 +#ifdef HAVE_HEIMDAL_VERSION
25437 + code = krb5_crypto_init(krbContext, &ctx->rfc3961Key, ETYPE_NULL, &krbCrypto);
25442 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25444 + KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM,
25448 + return GSS_S_FAILURE;
25451 + if (conf_req_flag) {
25452 + code = krbCryptoLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25453 + KRB5_CRYPTO_TYPE_HEADER, &krbHeaderLen);
25456 + return GSS_S_FAILURE;
25460 + gssHeaderLen = 16; /* Header */
25461 + if (conf_req_flag) {
25462 + gssHeaderLen += krbHeaderLen; /* Kerb-Header */
25463 + gssTrailerLen = 16 /* E(Header) */ + krbTrailerLen; /* Kerb-Trailer */
25465 + code = krbPaddingLength(krbContext, KRB_CRYPTO_CONTEXT(ctx),
25466 + dataLength - assocDataLength + 16 /* E(Header) */,
25470 + return GSS_S_FAILURE;
25473 + if (krbPadLen == 0 && dce_style) {
25474 + /* Windows rejects AEAD tokens with non-zero EC */
25475 + code = krbBlockSize(krbContext, KRB_CRYPTO_CONTEXT(ctx), &ec);
25478 + return GSS_S_FAILURE;
25483 + gssTrailerLen += ec;
25485 + gssTrailerLen = krbTrailerLen; /* Kerb-Checksum */
25488 + dataLength += gssPadLen;
25490 + if (trailer == NULL)
25491 + gssHeaderLen += gssTrailerLen;
25493 + trailer->buffer.length = gssTrailerLen;
25495 + GSSEAP_ASSERT(gssPadLen == 0 || padding != NULL);
25497 + if (padding != NULL)
25498 + padding->buffer.length = gssPadLen;
25500 + header->buffer.length = gssHeaderLen;
25502 + if (conf_state != NULL)
25503 + *conf_state = conf_req_flag;
25506 + return GSS_S_COMPLETE;
25509 +OM_uint32 GSSAPI_CALLCONV
25510 +gss_wrap_iov_length(OM_uint32 *minor,
25511 + gss_ctx_id_t ctx,
25512 + int conf_req_flag,
25513 + gss_qop_t qop_req,
25515 + gss_iov_buffer_desc *iov,
25520 + if (ctx == GSS_C_NO_CONTEXT) {
25522 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25527 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25529 + if (!CTX_IS_ESTABLISHED(ctx)) {
25530 + major = GSS_S_NO_CONTEXT;
25531 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25535 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
25536 + conf_state, iov, iov_count);
25537 + if (GSS_ERROR(major))
25541 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);
25545 diff --git a/mech_eap/wrap_size_limit.c b/mech_eap/wrap_size_limit.c
25546 new file mode 100644
25547 index 0000000..d11fd63
25549 +++ b/mech_eap/wrap_size_limit.c
25552 + * Copyright (c) 2011, JANET(UK)
25553 + * All rights reserved.
25555 + * Redistribution and use in source and binary forms, with or without
25556 + * modification, are permitted provided that the following conditions
25559 + * 1. Redistributions of source code must retain the above copyright
25560 + * notice, this list of conditions and the following disclaimer.
25562 + * 2. Redistributions in binary form must reproduce the above copyright
25563 + * notice, this list of conditions and the following disclaimer in the
25564 + * documentation and/or other materials provided with the distribution.
25566 + * 3. Neither the name of JANET(UK) nor the names of its contributors
25567 + * may be used to endorse or promote products derived from this software
25568 + * without specific prior written permission.
25570 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25571 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25572 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25573 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25574 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25575 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25576 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25577 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25578 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25579 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25584 + * Message protection services: determine maximum input size.
25587 +#include "gssapiP_eap.h"
25589 +OM_uint32 GSSAPI_CALLCONV
25590 +gss_wrap_size_limit(OM_uint32 *minor,
25591 + gss_ctx_id_t ctx,
25592 + int conf_req_flag,
25593 + gss_qop_t qop_req,
25594 + OM_uint32 req_output_size,
25595 + OM_uint32 *max_input_size)
25597 + gss_iov_buffer_desc iov[4];
25598 + OM_uint32 major, overhead;
25600 + if (ctx == GSS_C_NO_CONTEXT) {
25602 + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
25607 + GSSEAP_MUTEX_LOCK(&ctx->mutex);
25609 + if (!CTX_IS_ESTABLISHED(ctx)) {
25610 + major = GSS_S_NO_CONTEXT;
25611 + *minor = GSSEAP_CONTEXT_INCOMPLETE;
25615 + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
25616 + iov[0].buffer.value = NULL;
25617 + iov[0].buffer.length = 0;
25619 + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
25620 + iov[1].buffer.length = req_output_size;
25621 + iov[1].buffer.value = NULL;
25623 + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
25624 + iov[2].buffer.value = NULL;
25625 + iov[2].buffer.length = 0;
25627 + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
25628 + iov[3].buffer.value = NULL;
25629 + iov[3].buffer.length = 0;
25631 + major = gssEapWrapIovLength(minor, ctx, conf_req_flag, qop_req,
25633 + if (GSS_ERROR(major))
25636 + overhead = iov[0].buffer.length + iov[3].buffer.length;
25638 + if (iov[2].buffer.length == 0 && overhead < req_output_size)
25639 + *max_input_size = req_output_size - overhead;
25641 + *max_input_size = 0;
25644 + GSSEAP_MUTEX_UNLOCK(&ctx->mutex);