Merge branch 'oldradius'
authorLuke Howard <lukeh@padl.com>
Tue, 21 Sep 2010 10:49:23 +0000 (12:49 +0200)
committerLuke Howard <lukeh@padl.com>
Tue, 21 Sep 2010 10:49:23 +0000 (12:49 +0200)
Conflicts:
mech_eap/accept_sec_context.c
mech_eap/init_sec_context.c

1  2 
util_radius.cpp

diff --combined util_radius.cpp
  
  #include "gssapiP_eap.h"
  
+ VALUE_PAIR *
+ gss_eap_radius_attr_provider::copyAvps(const VALUE_PAIR *src)
+ {
+     const VALUE_PAIR *vp;
+     VALUE_PAIR *dst = NULL, **pDst = &dst;
+     for (vp = src; vp != NULL; vp = vp->next) {
+         VALUE_PAIR *vp2;
+         vp2 = (VALUE_PAIR *)GSSEAP_CALLOC(1, sizeof(*vp2));
+         if (vp2 == NULL) {
+             rc_avpair_free(dst);
+             return NULL;
+         }
+         memcpy(vp2, vp, sizeof(*vp));
+         vp2->next = NULL;
+         *pDst = vp2;
+         pDst = &vp2->next;
+     }
+     return dst;
+ }
  gss_eap_radius_attr_provider::gss_eap_radius_attr_provider(void)
  {
+     m_rh = NULL;
+     m_avps = NULL;
      m_authenticated = false;
  }
  
  gss_eap_radius_attr_provider::~gss_eap_radius_attr_provider(void)
  {
+     if (m_rh != NULL)
+         rc_config_free(m_rh);
+     if (m_avps != NULL)
+         rc_avpair_free(m_avps);
+ }
+ bool
+ gss_eap_radius_attr_provider::initFromGssCred(const gss_cred_id_t cred)
+ {
+     OM_uint32 minor;
+     return !GSS_ERROR(gssEapRadiusAllocHandle(&minor, cred, &m_rh));
  }
  
  bool
  gss_eap_radius_attr_provider::initFromExistingContext(const gss_eap_attr_ctx *manager,
                                                        const gss_eap_attr_provider *ctx)
  {
+     const gss_eap_radius_attr_provider *radius;
      if (!gss_eap_attr_provider::initFromExistingContext(manager, ctx))
          return false;
  
+     if (!initFromGssCred(GSS_C_NO_CREDENTIAL))
+         return false;
+     radius = static_cast<const gss_eap_radius_attr_provider *>(ctx);
+     if (radius->m_avps != NULL) {
+         m_avps = copyAvps(radius->getAvps());
+     }
      return true;
  }
  
@@@ -59,12 -106,54 +106,79 @@@ gss_eap_radius_attr_provider::initFromG
      if (!gss_eap_attr_provider::initFromGssContext(manager, gssCred, gssCtx))
          return false;
  
+     if (!initFromGssCred(gssCred))
+         return false;
+     if (gssCtx != GSS_C_NO_CONTEXT) {
+         if (gssCtx->acceptorCtx.avps != NULL) {
+             m_avps = copyAvps(gssCtx->acceptorCtx.avps);
+             if (m_avps == NULL)
+                 return false;
+         }
+     }
      return true;
  }
  
+ static bool
+ alreadyAddedAttributeP(std::vector <std::string> &attrs, VALUE_PAIR *vp)
+ {
+     for (std::vector<std::string>::const_iterator a = attrs.begin();
+          a != attrs.end();
+          ++a) {
+         if (strcmp(vp->name, (*a).c_str()) == 0)
+             return true;
+     }
+     return false;
+ }
++static bool
++isSecretAttributeP(int attrid, int vendor)
++{
++    bool ret = false;
++
++    switch (vendor) {
++    case RADIUS_VENDOR_ID_MICROSOFT:
++        switch (attrid) {
++        case RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY:
++        case RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY:
++            ret = true;
++            break;
++        default:
++            break;
++        }
++    default:
++        break;
++    }
++
++    return ret;
++}
++
  bool
  gss_eap_radius_attr_provider::getAttributeTypes(gss_eap_attr_enumeration_cb addAttribute, void *data) const
  {
+     VALUE_PAIR *vp;
+     std::vector <std::string> seen;
+     for (vp = m_avps; vp != NULL; vp = vp->next) {
+         gss_buffer_desc attribute;
++        if (isSecretAttributeP(ATTRID(vp->attribute), VENDOR(vp->attribute)))
++            continue;
++
+         if (alreadyAddedAttributeP(seen, vp))
+             continue;
+         attribute.value = (void *)vp->name;
+         attribute.length = strlen(vp->name);
+         if (!addAttribute(this, &attribute, data))
+             return false;
+         seen.push_back(std::string(vp->name));
+     }
      return true;
  }
  
@@@ -88,31 -177,147 +202,152 @@@ gss_eap_radius_attr_provider::getAttrib
                                             gss_buffer_t display_value,
                                             int *more) const
  {
-     return false;
+     OM_uint32 tmpMinor;
+     gss_buffer_desc strAttr = GSS_C_EMPTY_BUFFER;
+     DICT_ATTR *d;
+     int attrid;
+     char *s;
+     /* XXX vendor */
+     duplicateBuffer(*attr, &strAttr);
+     s = (char *)strAttr.value;
+     if (isdigit(((char *)strAttr.value)[0])) {
+         attrid = strtoul(s, NULL, 10);
+     } else {
+         d = rc_dict_findattr(m_rh, (char *)s);
+         if (d == NULL) {
+             gss_release_buffer(&tmpMinor, &strAttr);
+             return false;
+         }
+         attrid = d->value;
+     }
+     gss_release_buffer(&tmpMinor, &strAttr);
+     return getAttribute(attrid, authenticated, complete,
+                         value, display_value, more);
+ }
+ static bool
+ isPrintableAttributeP(VALUE_PAIR *vp)
+ {
+     size_t i;
+     for (i = 0; i < sizeof(vp->strvalue); i++) {
+         if (!isprint(vp->strvalue[i]))
+             return false;
+     }
+     return true;
  }
  
  bool
- gss_eap_radius_attr_provider::getAttribute(unsigned int attr,
+ gss_eap_radius_attr_provider::getAttribute(int attrid,
+                                            int vendor,
                                             int *authenticated,
                                             int *complete,
                                             gss_buffer_t value,
                                             gss_buffer_t display_value,
                                             int *more) const
  {
-     return false;
+     OM_uint32 tmpMinor;
+     VALUE_PAIR *vp;
+     int i = *more;
+     int max = 0;
+     char name[NAME_LENGTH + 1];
+     char displayString[AUTH_STRING_LEN + 1];
+     gss_buffer_desc valueBuf = GSS_C_EMPTY_BUFFER;
+     gss_buffer_desc displayBuf = GSS_C_EMPTY_BUFFER;
+     *more = 0;
++    if (isSecretAttributeP(attrid, vendor))
++        return false;
++
+     vp = rc_avpair_get(m_avps, attrid, vendor);
+     if (vp == NULL)
+         return false;
+     if (i == -1)
+         i = 0;
+     do {
+         if (i == max)
+             break;
+         max++;
+     } while ((vp = rc_avpair_get(vp->next, attrid, vendor)) != NULL);
+     if (i > max)
+         return false;
+     if (vp->type == PW_TYPE_STRING) {
+         valueBuf.value = (void *)vp->strvalue;
+         valueBuf.length = vp->lvalue;
+     } else {
+         valueBuf.value = (void *)&vp->lvalue;
+         valueBuf.length = 4;
+     }
+     if (value != GSS_C_NO_BUFFER)
+         duplicateBuffer(valueBuf, value);
+     if (display_value != GSS_C_NO_BUFFER &&
+         isPrintableAttributeP(vp)) {
+         if (rc_avpair_tostr(m_rh, vp, name, NAME_LENGTH,
+                             displayString, AUTH_STRING_LEN) != 0) {
+             gss_release_buffer(&tmpMinor, value);
+             return false;
+         }
+         displayBuf.value = (void *)displayString;
+         displayBuf.length = strlen(displayString);
+         duplicateBuffer(displayBuf, display_value);
+     }
+     if (authenticated != NULL)
+         *authenticated = m_authenticated;
+     if (complete != NULL)
+         *complete = true;
+     if (max > i)
+         *more = i;
+     return true;
+ }
+ bool
+ gss_eap_radius_attr_provider::getAttribute(int attrid,
+                                            int *authenticated,
+                                            int *complete,
+                                            gss_buffer_t value,
+                                            gss_buffer_t display_value,
+                                            int *more) const
+ {
 -    return getAttribute(attrid, 0, authenticated, complete,
++
++    return getAttribute(ATTRID(attrid), VENDOR(attrid),
++                        authenticated, complete,
+                         value, display_value, more);
  }
  
  gss_any_t
  gss_eap_radius_attr_provider::mapToAny(int authenticated,
                                         gss_buffer_t type_id) const
  {
-     return (gss_any_t)NULL;
+     if (authenticated && !m_authenticated)
+         return (gss_any_t)NULL;
+     return (gss_any_t)copyAvps(m_avps);
  }
  
  void
  gss_eap_radius_attr_provider::releaseAnyNameMapping(gss_buffer_t type_id,
                                                      gss_any_t input) const
  {
+     rc_avpair_free((VALUE_PAIR *)input);
  }
  
  void
@@@ -129,6 -334,9 +364,9 @@@ gss_eap_radius_attr_provider::initFromB
      if (!gss_eap_attr_provider::initFromBuffer(ctx, buffer))
          return false;
  
+     if (!initFromGssCred(GSS_C_NO_CREDENTIAL))
+         return false;
      return true;
  }
  
@@@ -154,6 -362,60 +392,60 @@@ gss_eap_radius_attr_provider::createAtt
  }
  
  OM_uint32
+ addAvpFromBuffer(OM_uint32 *minor,
+                  rc_handle *rh,
+                  VALUE_PAIR **vp,
+                  int type,
+                  gss_buffer_t buffer)
+ {
+     if (rc_avpair_add(rh, vp, type, buffer->value, buffer->length, 0) == NULL) {
+         return GSS_S_FAILURE;
+     }
+     return GSS_S_COMPLETE;
+ }
+ OM_uint32
+ getBufferFromAvps(OM_uint32 *minor,
+                   VALUE_PAIR *vps,
+                   int type,
+                   gss_buffer_t buffer,
+                   int concat)
+ {
+     VALUE_PAIR *vp;
+     unsigned char *p;
+     buffer->length = 0;
+     buffer->value = NULL;
+     vp = rc_avpair_get(vps, type, 0);
+     if (vp == NULL)
+         return GSS_S_UNAVAILABLE;
+     do {
+         buffer->length += vp->lvalue;
+     } while (concat && (vp = rc_avpair_get(vp->next, type, 0)) != NULL);
+     buffer->value = GSSEAP_MALLOC(buffer->length);
+     if (buffer->value == NULL) {
+         *minor = ENOMEM;
+         return GSS_S_FAILURE;
+     }
+     p = (unsigned char *)buffer->value;
+     for (vp = rc_avpair_get(vps, type, 0);
+          concat && vp != NULL;
+          vp = rc_avpair_get(vp->next, type, 0)) {
+         memcpy(p, vp->strvalue, vp->lvalue);
+         p += vp->lvalue;
+     }
+     *minor = 0;
+     return GSS_S_COMPLETE;
+ }
+ OM_uint32
  gssEapRadiusAttrProviderInit(OM_uint32 *minor)
  {
      return gss_eap_radius_attr_provider::init()
@@@ -166,3 -428,32 +458,32 @@@ gssEapRadiusAttrProviderFinalize(OM_uin
      gss_eap_radius_attr_provider::finalize();
      return GSS_S_COMPLETE;
  }
+ OM_uint32
+ gssEapRadiusAllocHandle(OM_uint32 *minor,
+                         const gss_cred_id_t cred,
+                         rc_handle **pHandle)
+ {
+     rc_handle *rh;
+     const char *config = RC_CONFIG_FILE;
+     *pHandle = NULL;
+     if (cred != GSS_C_NO_CREDENTIAL && cred->radiusConfigFile != NULL)
+         config = cred->radiusConfigFile;
+     rh = rc_read_config((char *)config);
+     if (rh == NULL) {
+         *minor = errno;
+         rc_config_free(rh);
+         return GSS_S_FAILURE;
+     }
+     if (rc_read_dictionary(rh, rc_conf_str(rh, (char *)"dictionary")) != 0) {
+         *minor = errno;
+         return GSS_S_FAILURE;
+     }
+     *pHandle = rh;
+     return GSS_S_COMPLETE;
+ }