X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=util_cred.c;h=1cabdcf7a6f73ee7c1b2adc62567544e2390bace;hb=refs%2Fheads%2Fjson-name;hp=6878bc22e39de0a628f930ecdc9a9ab9c1dab800;hpb=07c30f8b470c931dbf814eb2a9cb10e33c35129d;p=mech_eap.orig diff --git a/util_cred.c b/util_cred.c index 6878bc2..1cabdcf 100644 --- a/util_cred.c +++ b/util_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, JANET(UK) + * Copyright (c) 2011, JANET(UK) * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,8 @@ #include "gssapiP_eap.h" +#include + OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred) { @@ -107,11 +109,96 @@ gssEapReleaseCred(OM_uint32 *minor, gss_cred_id_t *pCred) return GSS_S_COMPLETE; } +static OM_uint32 +readDefaultIdentityAndCreds(OM_uint32 *minor, + gss_buffer_t defaultIdentity, + gss_buffer_t defaultCreds) +{ + OM_uint32 major, tmpMinor; + FILE *fp = NULL; + char pwbuf[BUFSIZ], buf[BUFSIZ]; + char *ccacheName; + struct passwd *pw = NULL, pwd; + + defaultIdentity->length = 0; + defaultIdentity->value = NULL; + + defaultCreds->length = 0; + defaultCreds->value = NULL; + + ccacheName = getenv("GSSEAP_IDENTITY"); + if (ccacheName == NULL) { + if (getpwuid_r(getuid(), &pwd, pwbuf, sizeof(pwbuf), &pw) != 0 || + pw == NULL || pw->pw_dir == NULL) { + major = GSS_S_CRED_UNAVAIL; + *minor = errno; + goto cleanup; + } + + snprintf(buf, sizeof(buf), "%s/.gss_eap_id", pw->pw_dir); + ccacheName = buf; + } + + fp = fopen(ccacheName, "r"); + if (fp == NULL) { + major = GSS_S_CRED_UNAVAIL; + *minor = GSSEAP_NO_DEFAULT_CRED; + goto cleanup; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + gss_buffer_desc src, *dst; + + src.length = strlen(buf); + src.value = buf; + + if (src.length == 0) + break; + + if (buf[src.length - 1] == '\n') { + buf[src.length - 1] = '\0'; + if (--src.length == 0) + break; + } + + if (defaultIdentity->value == NULL) + dst = defaultIdentity; + else if (defaultCreds->value == NULL) + dst = defaultCreds; + else + break; + + major = duplicateBuffer(minor, &src, dst); + if (GSS_ERROR(major)) + goto cleanup; + } + + if (defaultIdentity->length == 0) { + major = GSS_S_CRED_UNAVAIL; + *minor = GSSEAP_NO_DEFAULT_CRED; + goto cleanup; + } + + major = GSS_S_COMPLETE; + *minor = 0; + +cleanup: + if (fp != NULL) + fclose(fp); + + if (GSS_ERROR(major)) { + gss_release_buffer(&tmpMinor, defaultIdentity); + gss_release_buffer(&tmpMinor, defaultCreds); + } + + return major; +} + OM_uint32 gssEapAcquireCred(OM_uint32 *minor, const gss_name_t desiredName, const gss_buffer_t password, - OM_uint32 timeReq, + OM_uint32 timeReq GSSEAP_UNUSED, const gss_OID_set desiredMechs, int credUsage, gss_cred_id_t *pCred, @@ -120,6 +207,10 @@ gssEapAcquireCred(OM_uint32 *minor, { OM_uint32 major, tmpMinor; gss_cred_id_t cred; + gss_buffer_desc defaultIdentity = GSS_C_EMPTY_BUFFER; + gss_name_t defaultIdentityName = GSS_C_NO_NAME; + gss_buffer_desc defaultCreds = GSS_C_EMPTY_BUFFER; + gss_OID nameMech = GSS_C_NO_OID; /* XXX TODO validate with changed set_cred_option API */ *pCred = GSS_C_NO_CREDENTIAL; @@ -128,6 +219,46 @@ gssEapAcquireCred(OM_uint32 *minor, if (GSS_ERROR(major)) goto cleanup; + switch (credUsage) { + case GSS_C_BOTH: + cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT; + break; + case GSS_C_INITIATE: + cred->flags |= CRED_FLAG_INITIATE; + break; + case GSS_C_ACCEPT: + cred->flags |= CRED_FLAG_ACCEPT; + break; + default: + major = GSS_S_FAILURE; + *minor = GSSEAP_BAD_USAGE; + goto cleanup; + break; + } + + major = gssEapValidateMechs(minor, desiredMechs); + if (GSS_ERROR(major)) + goto cleanup; + + major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms); + if (GSS_ERROR(major)) + goto cleanup; + + if (cred->mechanisms != GSS_C_NO_OID_SET && + cred->mechanisms->count == 1) + nameMech = &cred->mechanisms->elements[0]; + + if (cred->flags & CRED_FLAG_INITIATE) { + major = readDefaultIdentityAndCreds(minor, &defaultIdentity, &defaultCreds); + if (major == GSS_S_COMPLETE) { + major = gssEapImportName(minor, &defaultIdentity, GSS_C_NT_USER_NAME, + nameMech, &defaultIdentityName); + if (GSS_ERROR(major)) + goto cleanup; + } else if (major != GSS_S_CRED_UNAVAIL) + goto cleanup; + } + if (desiredName != GSS_C_NO_NAME) { GSSEAP_MUTEX_LOCK(&desiredName->mutex); @@ -138,14 +269,24 @@ gssEapAcquireCred(OM_uint32 *minor, } GSSEAP_MUTEX_UNLOCK(&desiredName->mutex); - } else { - gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; - gss_OID nameType = GSS_C_NO_OID; + if (defaultIdentityName != GSS_C_NO_NAME) { + int nameEqual; + + major = gssEapCompareName(minor, desiredName, + defaultIdentityName, &nameEqual); + if (GSS_ERROR(major)) + goto cleanup; + else if (nameEqual) + cred->flags |= CRED_FLAG_DEFAULT_IDENTITY; + } + } else { if (cred->flags & CRED_FLAG_ACCEPT) { - char serviceName[5 + MAXHOSTNAMELEN] = "host@"; + gss_buffer_desc nameBuf = GSS_C_EMPTY_BUFFER; + char serviceName[5 + MAXHOSTNAMELEN]; /* default host-based service is host@localhost */ + memcpy(serviceName, "host@", 5); if (gethostname(&serviceName[5], MAXHOSTNAMELEN) != 0) { major = GSS_S_FAILURE; *minor = GSSEAP_NO_HOSTNAME; @@ -155,30 +296,40 @@ gssEapAcquireCred(OM_uint32 *minor, nameBuf.value = serviceName; nameBuf.length = strlen((char *)nameBuf.value); - nameType = GSS_C_NT_HOSTBASED_SERVICE; - } else if (cred->flags & CRED_FLAG_INITIATE) { - nameBuf.value = getlogin(); /* XXX */ - nameBuf.length = strlen((char *)nameBuf.value); - - nameType = GSS_C_NT_USER_NAME; - } - - if (nameBuf.length != 0) { - major = gssEapImportName(minor, &nameBuf, nameType, &cred->name); + major = gssEapImportName(minor, &nameBuf, GSS_C_NT_HOSTBASED_SERVICE, + nameMech, &cred->name); if (GSS_ERROR(major)) goto cleanup; - } + } else if (cred->flags & CRED_FLAG_INITIATE) { + if (defaultIdentityName == GSS_C_NO_NAME) { + major = GSS_S_CRED_UNAVAIL; + *minor = GSSEAP_NO_DEFAULT_IDENTITY; + goto cleanup; + } + cred->name = defaultIdentityName; + defaultIdentityName = GSS_C_NO_NAME; + } cred->flags |= CRED_FLAG_DEFAULT_IDENTITY; } + assert(cred->name != GSS_C_NO_NAME); + if (password != GSS_C_NO_BUFFER) { major = duplicateBuffer(minor, password, &cred->password); if (GSS_ERROR(major)) goto cleanup; cred->flags |= CRED_FLAG_PASSWORD; - } else if (credUsage == GSS_C_INITIATE) { + } else if (defaultCreds.value != NULL && + (cred->flags & CRED_FLAG_DEFAULT_IDENTITY)) { + cred->password = defaultCreds; + + defaultCreds.length = 0; + defaultCreds.value = NULL; + + cred->flags |= CRED_FLAG_PASSWORD; + } else if (cred->flags & CRED_FLAG_INITIATE) { /* * OK, here we need to ask the supplicant if we have creds or it * will acquire them, so GS2 can know whether to prompt for a @@ -188,34 +339,10 @@ gssEapAcquireCred(OM_uint32 *minor, && !gssEapCanReauthP(cred, GSS_C_NO_NAME, timeReq) #endif major = GSS_S_CRED_UNAVAIL; + *minor = GSSEAP_NO_DEFAULT_CRED; goto cleanup; } - switch (credUsage) { - case GSS_C_BOTH: - cred->flags |= CRED_FLAG_INITIATE | CRED_FLAG_ACCEPT; - break; - case GSS_C_INITIATE: - cred->flags |= CRED_FLAG_INITIATE; - break; - case GSS_C_ACCEPT: - cred->flags |= CRED_FLAG_ACCEPT; - break; - default: - major = GSS_S_FAILURE; - *minor = GSSEAP_BAD_USAGE; - goto cleanup; - break; - } - - major = gssEapValidateMechs(minor, desiredMechs); - if (GSS_ERROR(major)) - goto cleanup; - - major = duplicateOidSet(minor, desiredMechs, &cred->mechanisms); - if (GSS_ERROR(major)) - goto cleanup; - if (pActualMechs != NULL) { major = duplicateOidSet(minor, cred->mechanisms, pActualMechs); if (GSS_ERROR(major)) @@ -233,6 +360,12 @@ gssEapAcquireCred(OM_uint32 *minor, cleanup: if (GSS_ERROR(major)) gssEapReleaseCred(&tmpMinor, &cred); + gssEapReleaseName(&tmpMinor, &defaultIdentityName); + gss_release_buffer(&tmpMinor, &defaultIdentity); + if (defaultCreds.value != NULL) { + memset(defaultCreds.value, 0, defaultCreds.length); + gss_release_buffer(&tmpMinor, &defaultCreds); + } return major; }