Merge branch 'master' into tlv-mic
authorLuke Howard <lukeh@padl.com>
Mon, 28 Mar 2011 22:37:38 +0000 (09:37 +1100)
committerLuke Howard <lukeh@padl.com>
Mon, 28 Mar 2011 22:37:38 +0000 (09:37 +1100)
Conflicts:
mech_eap/export_sec_context.c
mech_eap/import_sec_context.c

1  2 
mech_eap/export_sec_context.c
mech_eap/gssapiP_eap.h
mech_eap/util.h
mech_eap/util_attr.cpp

@@@ -38,7 -38,7 +38,7 @@@
  #include "gssapiP_eap.h"
  
  static OM_uint32
 -gssEapExportPartialContext(OM_uint32 *minor,
 +exportPartialRadiusContext(OM_uint32 *minor,
                             gss_ctx_id_t ctx,
                             gss_buffer_t token)
  {
      if (ctx->acceptorCtx.radConn != NULL) {
          if (rs_conn_get_current_peer(ctx->acceptorCtx.radConn,
                                       serverBuf, sizeof(serverBuf)) != 0) {
+ #if 0
              return gssEapRadiusMapError(minor,
                                          rs_err_conn_pop(ctx->acceptorCtx.radConn));
+ #else
+             serverBuf[0] = '\0'; /* not implemented yet */
+ #endif
          }
          serverLen = strlen(serverBuf);
      }
@@@ -95,7 -99,7 +99,7 @@@ cleanup
      return major;
  }
  
static OM_uint32
+ OM_uint32
  gssEapExportSecContext(OM_uint32 *minor,
                         gss_ctx_id_t ctx,
                         gss_buffer_t token)
          if (GSS_ERROR(major))
              goto cleanup;
      }
      if (ctx->acceptorName != GSS_C_NO_NAME) {
          major = gssEapExportNameInternal(minor, ctx->acceptorName,
                                           &acceptorName,
       * The partial context is only transmitted for unestablished acceptor
       * contexts.
       */
-     if (!CTX_IS_INITIATOR(ctx) &&
-         !CTX_IS_ESTABLISHED(ctx) &&
-         ((ctx->flags & CTX_FLAG_KRB_REAUTH) == 0)) {
-         major = exportPartialRadiusContext(minor, ctx, &partialCtx);
+     if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx) &&
+         (ctx->flags & CTX_FLAG_KRB_REAUTH) == 0) {
+         major = gssEapExportPartialContext(minor, ctx, &partialCtx);
          if (GSS_ERROR(major))
              goto cleanup;
      }
      length += 4 + acceptorName.length;          /* acceptorName.value */
      length += 24 + sequenceSize(ctx->seqState); /* seqState */
  
 +    if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx))
 +        length += 4 + ctx->conversation.length;
 +
      if (partialCtx.value != NULL)
          length += 4 + partialCtx.length;        /* partialCtx.value */
  
      if (GSS_ERROR(major))
          goto cleanup;
  
 +    if (!CTX_IS_INITIATOR(ctx) && !CTX_IS_ESTABLISHED(ctx))
 +        p = store_buffer(&ctx->conversation, &p, FALSE);
 +
      if (partialCtx.value != NULL)
          p = store_buffer(&partialCtx, p, FALSE);
  
diff --combined mech_eap/gssapiP_eap.h
@@@ -141,7 -141,6 +141,7 @@@ struct gss_cred_id_struc
  
  #define CTX_FLAG_INITIATOR                  0x00000001
  #define CTX_FLAG_KRB_REAUTH                 0x00000002
 +#define CTX_FLAG_KRB_REAUTH_SUPPORTED       0x00000004
  
  #define CTX_IS_INITIATOR(ctx)               (((ctx)->flags & CTX_FLAG_INITIATOR) != 0)
  
@@@ -206,7 -205,6 +206,7 @@@ struct gss_ctx_id_struc
          #define kerberosCtx          ctxU.kerberos
  #endif
      } ctxU;
 +    gss_buffer_desc conversation;
  };
  
  #define TOK_FLAG_SENDER_IS_ACCEPTOR         0x01
@@@ -264,6 -262,13 +264,13 @@@ gssEapSaveStatusInfo(OM_uint32 minor, c
  #define IS_WIRE_ERROR(err)              ((err) > GSSEAP_RESERVED && \
                                           (err) <= GSSEAP_RADIUS_PROT_FAILURE)
  
+ /* export_sec_context.c */
+ OM_uint32
+ gssEapExportSecContext(OM_uint32 *minor,
+                        gss_ctx_id_t ctx,
+                        gss_buffer_t token);
  #ifdef __cplusplus
  }
  #endif
diff --combined mech_eap/util.h
@@@ -164,65 -164,46 +164,65 @@@ enum gss_eap_token_type 
      TOK_TYPE_ACCEPTOR_CONTEXT        = 0x0602,  /* acceptor-sent context token */
  };
  
 +struct gss_eap_itok_map {
 +    OM_uint32 type;                             /* inner token type */
 +    OM_uint32 flag;                             /* context flag */
 +};
 +
  /* inner token types and flags */
 -#define ITOK_TYPE_NONE                  0x00000000
 -#define ITOK_TYPE_CONTEXT_ERR           0x00000001 /* critical */
 -#define ITOK_TYPE_ACCEPTOR_NAME_REQ     0x00000002 /* TBD */
 -#define ITOK_TYPE_ACCEPTOR_NAME_RESP    0x00000003 /* TBD */
 -#define ITOK_TYPE_EAP_RESP              0x00000004 /* critical, required, if not reauth */
 -#define ITOK_TYPE_EAP_REQ               0x00000005 /* critical, required, if not reauth */
 -#define ITOK_TYPE_GSS_CHANNEL_BINDINGS  0x00000006 /* critical, required, if not reauth */
 -#define ITOK_TYPE_REAUTH_CREDS          0x00000007 /* optional */
 -#define ITOK_TYPE_REAUTH_REQ            0x00000008 /* optional */
 -#define ITOK_TYPE_REAUTH_RESP           0x00000009 /* optional */
 -#define ITOK_TYPE_VERSION_INFO          0x0000000A /* optional */
 -#define ITOK_TYPE_VENDOR_INFO           0x0000000B /* optional */
 -
 -#define ITOK_FLAG_CRITICAL              0x80000000  /* critical, wire flag */
 -#define ITOK_FLAG_VERIFIED              0x40000000  /* verified, API flag */
 -
 -#define ITOK_TYPE_MASK                  (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
 +#define ITOK_TYPE_NONE                      0x00000000
 +#define ITOK_TYPE_CONTEXT_ERR               0x00000001 /* critical */
 +#define ITOK_TYPE_ACCEPTOR_NAME_REQ         0x00000002 /* TBD */
 +#define ITOK_TYPE_ACCEPTOR_NAME_RESP        0x00000003 /* TBD */
 +#define ITOK_TYPE_EAP_RESP                  0x00000004 /* critical, required, if not reauth */
 +#define ITOK_TYPE_EAP_REQ                   0x00000005 /* critical, required, if not reauth */
 +#define ITOK_TYPE_GSS_CHANNEL_BINDINGS      0x00000006 /* optional */
 +#define ITOK_TYPE_REAUTH_CREDS              0x00000007 /* optional */
 +#define ITOK_TYPE_REAUTH_REQ                0x00000008 /* optional */
 +#define ITOK_TYPE_REAUTH_RESP               0x00000009 /* optional */
 +#define ITOK_TYPE_GSS_FLAGS                 0x0000000A /* optional */
 +#define ITOK_TYPE_INITIATOR_MIC             0x0000000B /* required */
 +#define ITOK_TYPE_ACCEPTOR_MIC              0x0000000C /* required */
 +#define ITOK_TYPE_SUPPORTED_ACCEPTOR_EXTS   0x0000000D /* optional */
 +#define ITOK_TYPE_SUPPORTED_INITIATOR_EXTS  0x0000000E /* optional */
 +
 +/* experimental */
 +#define ITOK_TYPE_VERSION_INFO              0x00000080 /* optional */
 +#define ITOK_TYPE_VENDOR_INFO               0x00000081 /* optional */
 +
 +#define ITOK_FLAG_CRITICAL                  0x80000000  /* critical, wire flag */
 +#define ITOK_FLAG_VERIFIED                  0x40000000  /* verified, API flag */
 +
 +#define ITOK_TYPE_MASK                      (~(ITOK_FLAG_CRITICAL | ITOK_FLAG_VERIFIED))
 +
 +#define ITOK_HEADER_LENGTH                  8           /* type || length */
 +
 +#define GSSEAP_WIRE_FLAGS_MASK              ( GSS_C_MUTUAL_FLAG )
  
  OM_uint32 gssEapAllocContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
  OM_uint32 gssEapReleaseContext(OM_uint32 *minor, gss_ctx_id_t *pCtx);
  
  OM_uint32
 -gssEapMakeToken(OM_uint32 *minor,
 -                gss_ctx_id_t ctx,
 -                const gss_buffer_t innerToken,
 -                enum gss_eap_token_type tokenType,
 -                gss_buffer_t outputToken);
 +gssEapContextTime(OM_uint32 *minor,
 +                  gss_ctx_id_t context_handle,
 +                  OM_uint32 *time_rec);
  
  OM_uint32
 -gssEapVerifyToken(OM_uint32 *minor,
 -                  gss_ctx_id_t ctx,
 -                  const gss_buffer_t inputToken,
 -                  enum gss_eap_token_type *tokenType,
 -                  gss_buffer_t innerInputToken);
 +gssEapGetConversationMIC(OM_uint32 *minor,
 +                         gss_ctx_id_t ctx,
 +                         gss_buffer_t convMIC);
  
  OM_uint32
 -gssEapContextTime(OM_uint32 *minor,
 -                  gss_ctx_id_t context_handle,
 -                  OM_uint32 *time_rec);
 +gssEapVerifyConversationMIC(OM_uint32 *minor,
 +                            gss_ctx_id_t ctx,
 +                            const gss_buffer_t convMIC);
 +
 +OM_uint32
 +gssEapMakeTokenChannelBindings(OM_uint32 *minor,
 +                               gss_ctx_id_t ctx,
 +                               gss_channel_bindings_t userBindings,
 +                               gss_buffer_t inputToken,
 +                               gss_channel_bindings_t wireBindings);
  
  /* util_cred.c */
  OM_uint32 gssEapAllocCred(OM_uint32 *minor, gss_cred_id_t *pCred);
@@@ -472,8 -453,8 +472,8 @@@ gss_OI
  gssEapSaslNameToOid(const gss_buffer_t name);
  
  /* util_name.c */
- #define EXPORT_NAME_FLAG_OID        0x1
- #define EXPORT_NAME_FLAG_COMPOSITE  0x2
+ #define EXPORT_NAME_FLAG_OID                    0x1
+ #define EXPORT_NAME_FLAG_COMPOSITE              0x2
  
  OM_uint32 gssEapAllocName(OM_uint32 *minor, gss_name_t *pName);
  OM_uint32 gssEapReleaseName(OM_uint32 *minor, gss_name_t *pName);
@@@ -483,7 -464,7 +483,7 @@@ OM_uint32 gssEapExportName(OM_uint32 *m
  OM_uint32 gssEapExportNameInternal(OM_uint32 *minor,
                                     const gss_name_t name,
                                     gss_buffer_t exportedName,
-                                    unsigned int flags);
+                                    OM_uint32 flags);
  OM_uint32 gssEapImportName(OM_uint32 *minor,
                             const gss_buffer_t input_name_buffer,
                             const gss_OID input_name_type,
  OM_uint32 gssEapImportNameInternal(OM_uint32 *minor,
                                     const gss_buffer_t input_name_buffer,
                                     gss_name_t *output_name,
-                                    unsigned int flags);
+                                    OM_uint32 flags);
  OM_uint32
  gssEapDuplicateName(OM_uint32 *minor,
                      const gss_name_t input_name,
@@@ -625,7 -606,7 +625,7 @@@ struct gss_eap_sm 
  };
  
  /* state machine flags, set by handler */
 -#define SM_FLAG_FORCE_SEND_TOKEN            0x00000001  /* send token even if no inner tokens */
 +#define SM_FLAG_SEND_TOKEN                  0x00000001  /* exit state machine, send token */
  #define SM_FLAG_OUTPUT_TOKEN_CRITICAL       0x00000002  /* output token is critical */
  
  /* state machine flags, set by state machine */
@@@ -652,48 -633,24 +652,48 @@@ gssEapSmTransition(gss_ctx_id_t ctx, en
  
  /* util_token.c */
  OM_uint32
 -gssEapEncodeInnerTokens(OM_uint32 *minor,
 -                        gss_buffer_set_t extensions,
 -                        OM_uint32 *types,
 -                        gss_buffer_t buffer);
 -OM_uint32
  gssEapDecodeInnerTokens(OM_uint32 *minor,
                          const gss_buffer_t buffer,
                          gss_buffer_set_t *pExtensions,
                          OM_uint32 **pTypes);
  
 +OM_uint32
 +gssEapRecordContextTokenHeader(OM_uint32 *minor,
 +                               gss_ctx_id_t ctx,
 +                               enum gss_eap_token_type tokType);
 +
 +OM_uint32
 +gssEapRecordInnerContextToken(OM_uint32 *minor,
 +                              gss_ctx_id_t ctx,
 +                              gss_buffer_t innerToken,
 +                              OM_uint32 type);
 +
 +OM_uint32
 +gssEapVerifyContextToken(OM_uint32 *minor,
 +                         gss_ctx_id_t ctx,
 +                         const gss_buffer_t inputToken,
 +                         enum gss_eap_token_type tokenType,
 +                         gss_buffer_t innerInputToken);
 +
 +OM_uint32
 +gssEapEncodeSupportedExts(OM_uint32 *minor,
 +                          OM_uint32 *types,
 +                          size_t typesCount,
 +                          gss_buffer_t outputToken);
 +
 +OM_uint32
 +gssEapProcessSupportedExts(OM_uint32 *minor,
 +                           gss_buffer_t inputToken,
 +                           struct gss_eap_itok_map *map,
 +                           size_t mapCount,
 +                           OM_uint32 *flags);
 +
  size_t
 -tokenSize(const gss_OID_desc *mech, size_t body_size);
 +tokenSize(size_t bodySize);
  
  void
 -makeTokenHeader(const gss_OID_desc *mech,
 -                size_t body_size,
 -                unsigned char **buf,
 -                enum gss_eap_token_type tok_type);
 +makeTokenHeader(size_t body_size,
 +                unsigned char **buf);
  
  OM_uint32
  verifyTokenHeader(OM_uint32 *minor,
@@@ -888,7 -845,9 +888,9 @@@ gssBufferToKrbData(gss_buffer_t buffer
  }
  #endif
  
+ #include "util_json.h"
  #include "util_attr.h"
+ #include "util_base64.h"
  #ifdef GSSEAP_ENABLE_REAUTH
  #include "util_reauth.h"
  #endif
diff --combined mech_eap/util_attr.cpp
@@@ -38,7 -38,9 +38,9 @@@
  
  #include <typeinfo>
  #include <string>
+ #include <sstream>
  #include <exception>
+ #include <stdexcept>
  #include <new>
  
  /* lazy initialisation */
@@@ -273,58 -275,27 +275,27 @@@ gss_eap_attr_ctx::initFromGssContext(co
      return ret;
  }
  
- #define UPDATE_REMAIN(n)    do {                \
-         p += (n);                               \
-         remain -= (n);                          \
-     } while (0)
- #define CHECK_REMAIN(n)     do {                \
-         if (remain < (n)) {                     \
-             return false;                       \
-         }                                       \
-     } while (0)
- /*
-  * Initialize a context from an exported context or name token
-  */
  bool
- gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
+ gss_eap_attr_ctx::initWithJsonObject(JSONObject &obj)
  {
      bool ret = false;
-     size_t remain = buffer->length;
-     unsigned char *p = (unsigned char *)buffer->value;
-     bool didInit[ATTR_TYPE_MAX + 1];
+     bool foundSource[ATTR_TYPE_MAX + 1];
      unsigned int type;
  
      for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++)
-         didInit[type] = false;
-     /* flags */
-     CHECK_REMAIN(4);
-     m_flags = load_uint32_be(p);
-     UPDATE_REMAIN(4);
+         foundSource[type] = false;
  
-     while (remain) {
-         OM_uint32 type;
-         gss_buffer_desc providerToken;
-         gss_eap_attr_provider *provider;
-         /* TLV encoding of provider type, length, value */
-         CHECK_REMAIN(4);
-         type = load_uint32_be(p);
-         UPDATE_REMAIN(4);
+     if (obj["version"].integer() != 1)
+         return false;
  
-         CHECK_REMAIN(4);
-         providerToken.length = load_uint32_be(p);
-         UPDATE_REMAIN(4);
+     m_flags = obj["flags"].integer();
  
-         CHECK_REMAIN(providerToken.length);
-         providerToken.value = p;
-         UPDATE_REMAIN(providerToken.length);
+     JSONObject sources = obj["sources"];
  
-         if (type < ATTR_TYPE_MIN || type > ATTR_TYPE_MAX ||
-             didInit[type])
-             return false;
+     /* Initialize providers from serialized state */
+     for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
+         gss_eap_attr_provider *provider;
+         const char *key;
  
          if (!providerEnabled(type)) {
              releaseProvider(type);
          }
  
          provider = m_providers[type];
+         key = provider->name();
+         if (key == NULL)
+             continue;
  
-         ret = provider->initFromBuffer(this, &providerToken);
-         if (ret == false) {
+         JSONObject source = sources.get(key);
+         if (!source.isnull() &&
+             !provider->initWithJsonObject(this, source)) {
              releaseProvider(type);
-             break;
+             return false;
          }
-         didInit[type] = true;
-     }
  
-     if (ret == false)
-         return ret;
+         foundSource[type] = true;
+     }
  
-     /*
-      * The call the initFromGssContext methods for attribute
-      * providers that can initialize themselves from other
-      * providers.
-      */
+     /* Initialize remaining providers from initialized providers */
      for (type = ATTR_TYPE_MIN; type <= ATTR_TYPE_MAX; type++) {
          gss_eap_attr_provider *provider;
  
-         if (didInit[type] || !providerEnabled(type))
+         if (foundSource[type] || !providerEnabled(type))
              continue;
  
          provider = m_providers[type];
      return true;
  }
  
+ JSONObject
+ gss_eap_attr_ctx::jsonRepresentation(void) const
+ {
+     JSONObject obj, sources;
+     unsigned int i;
+     obj.set("version", 1);
+     obj.set("flags", m_flags);
+     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
+         gss_eap_attr_provider *provider;
+         const char *key;
+         provider = m_providers[i];
+         if (provider == NULL)
+             continue; /* provider not initialised */
+         key = provider->name();
+         if (key == NULL)
+             continue; /* provider does not have state */
+         JSONObject source = provider->jsonRepresentation();
+         sources.set(key, source);
+     }
+     obj.set("sources", sources);
+     return obj;
+ }
+ /*
+  * Initialize a context from an exported context or name token
+  */
+ bool
+ gss_eap_attr_ctx::initFromBuffer(const gss_buffer_t buffer)
+ {
+     OM_uint32 major, minor;
+     bool ret;
+     char *s;
+     json_error_t error;
+     major = bufferToString(&minor, buffer, &s);
+     if (GSS_ERROR(major))
+         return false;
+     JSONObject obj = JSONObject::load(s, 0, &error);
+     if (!obj.isnull()) {
+         ret = initWithJsonObject(obj);
+     } else
+         ret = false;
+     GSSEAP_FREE(s);
+     return ret;
+ }
  gss_eap_attr_ctx::~gss_eap_attr_ctx(void)
  {
      for (unsigned int i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++)
@@@ -502,10 -527,8 +527,8 @@@ gss_eap_attr_ctx::getAttributeTypes(gss
      unsigned int i;
  
      major = gss_create_empty_buffer_set(&minor, attrs);
-     if (GSS_ERROR(major)) {
+     if (GSS_ERROR(major))
          throw new std::bad_alloc;
-         return false;
-     }
  
      args.attrs = *attrs;
  
@@@ -601,51 -624,19 +624,19 @@@ gss_eap_attr_ctx::releaseAnyNameMapping
  void
  gss_eap_attr_ctx::exportToBuffer(gss_buffer_t buffer) const
  {
-     OM_uint32 tmpMinor;
-     gss_buffer_desc providerTokens[ATTR_TYPE_MAX + 1];
-     size_t length = 4; /* m_flags */
-     unsigned char *p;
-     unsigned int i;
+     OM_uint32 minor;
+     char *s;
  
-     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
-         providerTokens[i].length = 0;
-         providerTokens[i].value = NULL;
-     }
+     JSONObject obj = jsonRepresentation();
  
-     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
-         gss_eap_attr_provider *provider = m_providers[i];
-         if (provider == NULL)
-             continue;
-         provider->exportToBuffer(&providerTokens[i]);
+ #if 0
+     obj.dump(stdout, JSON_INDENT(3));
+ #endif
  
-         if (providerTokens[i].value != NULL)
-             length += 8 + providerTokens[i].length;
-     }
+     s = obj.dump(JSON_COMPACT);
  
-     buffer->length = length;
-     buffer->value = GSSEAP_MALLOC(length);
-     if (buffer->value == NULL)
+     if (GSS_ERROR(makeStringBuffer(&minor, s, buffer)))
          throw new std::bad_alloc;
-     p = (unsigned char *)buffer->value;
-     store_uint32_be(m_flags, p);
-     p += 4;
-     for (i = ATTR_TYPE_MIN; i <= ATTR_TYPE_MAX; i++) {
-         if (providerTokens[i].value == NULL)
-             continue;
-         store_uint32_be(i, p);
-         p += 4;
-         store_uint32_be(providerTokens[i].length, p);
-         p += 4;
-         memcpy(p, providerTokens[i].value, providerTokens[i].length);
-         p += providerTokens[i].length;
-         gss_release_buffer(&tmpMinor, &providerTokens[i]);
-     }
  }
  
  /*
@@@ -859,15 -850,13 +850,15 @@@ gssEapInquireName(OM_uint32 *minor
          return GSS_S_UNAVAILABLE;
      }
  
 -    try {
 -        if (!name->attrCtx->getAttributeTypes(attrs)) {
 -            *minor = GSSEAP_NO_ATTR_CONTEXT;
 -            return GSS_S_UNAVAILABLE;
 +    if (attrs != NULL) {
 +        try {
 +            if (!name->attrCtx->getAttributeTypes(attrs)) {
 +                *minor = GSSEAP_NO_ATTR_CONTEXT;
 +                return GSS_S_UNAVAILABLE;
 +            }
 +        } catch (std::exception &e) {
 +            return name->attrCtx->mapException(minor, e);
          }
 -    } catch (std::exception &e) {
 -        return name->attrCtx->mapException(minor, e);
      }
  
      return GSS_S_COMPLETE;
@@@ -1145,12 -1134,10 +1136,10 @@@ gssEapCreateAttrContext(OM_uint32 *mino
      major = GSS_S_FAILURE;
  
      try {
-         ctx = new gss_eap_attr_ctx();
+         *pAttrContext = ctx = new gss_eap_attr_ctx();
          if (ctx->initFromGssContext(gssCred, gssCtx)) {
              *minor = 0;
              major = GSS_S_COMPLETE;
-         } else {
-             delete ctx;
          }
      } catch (std::exception &e) {
          if (ctx != NULL)
      }
  
      if (major == GSS_S_COMPLETE) {
-         *pAttrContext = ctx;
          *pExpiryTime = ctx->getExpiryTime();
+     } else {
+         delete ctx;
+         *pAttrContext = NULL;
      }
  
      return major;