194
207
extern int wpa_debug_level;
210
#define CHBIND_SERVICE_NAME_FLAG 0x01
211
#define CHBIND_HOST_NAME_FLAG 0x02
212
#define CHBIND_SERVICE_SPECIFIC_FLAG 0x04
213
#define CHBIND_REALM_NAME_FLAG 0x08
216
peerInitEapChannelBinding(OM_uint32 *minor, gss_ctx_id_t ctx)
218
struct wpabuf *buf = NULL;
219
unsigned int chbindReqFlags = 0;
220
krb5_principal princ = NULL;
221
gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER;
222
OM_uint32 major = GSS_S_COMPLETE;
223
krb5_context krbContext = NULL;
225
/* XXX is this check redundant? */
226
if (ctx->acceptorName == GSS_C_NO_NAME) {
227
major = GSS_S_BAD_NAME;
228
*minor = GSSEAP_NO_ACCEPTOR_NAME;
232
princ = ctx->acceptorName->krbPrincipal;
234
krbPrincComponentToGssBuffer(princ, 0, &nameBuf);
235
if (nameBuf.length > 0) {
236
major = gssEapRadiusAddAttr(minor, &buf, PW_GSS_ACCEPTOR_SERVICE_NAME,
238
if (GSS_ERROR(major))
241
chbindReqFlags |= CHBIND_SERVICE_NAME_FLAG;
244
krbPrincComponentToGssBuffer(princ, 1, &nameBuf);
245
if (nameBuf.length > 0) {
246
major = gssEapRadiusAddAttr(minor, &buf, PW_GSS_ACCEPTOR_HOST_NAME,
248
if (GSS_ERROR(major))
251
chbindReqFlags |= CHBIND_HOST_NAME_FLAG;
254
GSSEAP_KRB_INIT(&krbContext);
256
*minor = krbPrincUnparseServiceSpecifics(krbContext, princ, &nameBuf);
260
if (nameBuf.length > 0) {
261
major = gssEapRadiusAddAttr(minor, &buf,
262
PW_GSS_ACCEPTOR_SERVICE_SPECIFICS,
264
if (GSS_ERROR(major))
267
chbindReqFlags |= CHBIND_SERVICE_SPECIFIC_FLAG;
270
krbFreeUnparsedName(krbContext, &nameBuf);
271
krbPrincRealmToGssBuffer(princ, &nameBuf);
273
if (nameBuf.length > 0) {
274
major = gssEapRadiusAddAttr(minor, &buf,
275
PW_GSS_ACCEPTOR_REALM_NAME,
277
chbindReqFlags |= CHBIND_REALM_NAME_FLAG;
280
if (chbindReqFlags == 0) {
281
major = GSS_S_BAD_NAME;
282
*minor = GSSEAP_BAD_ACCEPTOR_NAME;
286
ctx->initiatorCtx.chbindData = buf;
287
ctx->initiatorCtx.chbindReqFlags = chbindReqFlags;
291
major = GSS_S_COMPLETE;
295
krbFreeUnparsedName(krbContext, &nameBuf);
302
peerProcessChbindResponse(void *context, int code, int nsid,
303
u8 *data, size_t len)
306
gss_ctx_id_t ctx = (gss_ctx_id_t )context;
310
u32 chbindRetFlags = 0;
313
if (nsid != CHBIND_NSID_RADIUS)
318
msg = radius_parser_start(data, len);
322
while (radius_parser_parse_tlv(msg, &type, &vendor_id, &vsadata,
323
&vsadata_len) == 0) {
325
case PW_GSS_ACCEPTOR_SERVICE_NAME:
326
chbindRetFlags |= CHBIND_SERVICE_NAME_FLAG;
328
case PW_GSS_ACCEPTOR_HOST_NAME:
329
chbindRetFlags |= CHBIND_HOST_NAME_FLAG;
331
case PW_GSS_ACCEPTOR_SERVICE_SPECIFICS:
332
chbindRetFlags |= CHBIND_SERVICE_SPECIFIC_FLAG;
334
case PW_GSS_ACCEPTOR_REALM_NAME:
335
chbindRetFlags |= CHBIND_REALM_NAME_FLAG;
340
radius_parser_finish(msg);
342
if (code == CHBIND_CODE_SUCCESS &&
343
((chbindRetFlags & ctx->initiatorCtx.chbindReqFlags) == ctx->initiatorCtx.chbindReqFlags)) {
344
ctx->flags |= CTX_FLAG_EAP_CHBIND_ACCEPT;
345
ctx->gssFlags |= GSS_C_MUTUAL_FLAG;
346
} /* else log failures? */
198
350
peerConfigInit(OM_uint32 *minor, gss_ctx_id_t ctx)
201
353
krb5_context krbContext;
202
354
struct eap_peer_config *eapPeerConfig = &ctx->initiatorCtx.eapPeerConfig;
355
struct wpa_config_blob *configBlobs = ctx->initiatorCtx.configBlobs;
203
356
gss_buffer_desc identity = GSS_C_EMPTY_BUFFER;
204
357
gss_buffer_desc realm = GSS_C_EMPTY_BUFFER;
205
358
gss_cred_id_t cred = ctx->cred;
250
403
eapPeerConfig->anonymous_identity_len = 1 + realm.length;
253
eapPeerConfig->password = (unsigned char *)cred->password.value;
254
eapPeerConfig->password_len = cred->password.length;
406
if ((cred->flags & CRED_FLAG_CERTIFICATE) == 0) {
407
eapPeerConfig->password = (unsigned char *)cred->password.value;
408
eapPeerConfig->password_len = cred->password.length;
257
412
eapPeerConfig->ca_cert = (unsigned char *)cred->caCertificate.value;
258
413
eapPeerConfig->subject_match = (unsigned char *)cred->subjectNameConstraint.value;
259
414
eapPeerConfig->altsubject_match = (unsigned char *)cred->subjectAltNameConstraint.value;
416
/* eap channel binding */
417
if (ctx->initiatorCtx.chbindData != NULL) {
418
struct eap_peer_chbind_config *chbind_config =
419
(struct eap_peer_chbind_config *)GSSEAP_MALLOC(sizeof(struct eap_peer_chbind_config));
420
if (chbind_config == NULL) {
422
return GSS_S_FAILURE;
425
chbind_config->req_data = wpabuf_mhead_u8(ctx->initiatorCtx.chbindData);
426
chbind_config->req_data_len = wpabuf_len(ctx->initiatorCtx.chbindData);
427
chbind_config->nsid = CHBIND_NSID_RADIUS;
428
chbind_config->response_cb = &peerProcessChbindResponse;
429
chbind_config->ctx = ctx;
430
eapPeerConfig->chbind_config = chbind_config;
431
eapPeerConfig->chbind_config_len = 1;
433
eapPeerConfig->chbind_config = NULL;
434
eapPeerConfig->chbind_config_len = 0;
436
if (cred->flags & CRED_FLAG_CERTIFICATE) {
438
* CRED_FLAG_CONFIG_BLOB is an internal flag which will be used in the
439
* future to directly pass certificate and private key data to the
440
* EAP implementation, rather than an indirected string pointer.
442
if (cred->flags & CRED_FLAG_CONFIG_BLOB) {
443
eapPeerConfig->client_cert = (unsigned char *)"blob://client-cert";
444
configBlobs[CONFIG_BLOB_CLIENT_CERT].data = cred->clientCertificate.value;
445
configBlobs[CONFIG_BLOB_CLIENT_CERT].len = cred->clientCertificate.length;
447
eapPeerConfig->client_cert = (unsigned char *)"blob://private-key";
448
configBlobs[CONFIG_BLOB_PRIVATE_KEY].data = cred->clientCertificate.value;
449
configBlobs[CONFIG_BLOB_PRIVATE_KEY].len = cred->privateKey.length;
451
eapPeerConfig->client_cert = (unsigned char *)cred->clientCertificate.value;
452
eapPeerConfig->private_key = (unsigned char *)cred->privateKey.value;
454
eapPeerConfig->private_key_passwd = (unsigned char *)cred->password.value;
262
458
return GSS_S_COMPLETE;