Uploaded image for project: 'OpenAM'
  1. OpenAM
  2. OPENAM-9567

The HttpServletRequest from the DAS can be null at the authentication module level

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 11.0.3, 12.0.0, 12.0.1, 12.0.2, 12.0.3
    • Fix Version/s: 12.0.4
    • Component/s: DAS
    • Labels:
    • Sprint:
      AM Sustaining Sprint 26

      Description

      Before thinking you're hitting this issue, which is, in my opition, difficulte to hit, make sure that the option

      openam.remoteauth.include.reqres=true
      

      is true.

      How to reproduce

      Unfortunately, we were not able to narrow the environment condition to explain how to reproduce it. However, debug logs demonstrate that this is actually happening.
      For QA testing this issue, just make sure that the DAS can deserialize the
      HttpServletRequest.
      Any module calling "getHttpServletRequest()" would do the job. Adaptive risk, Cert, etc.

      What's happening

      In some rare condition, the deserialization of the HttpServletRequest, more precisely the attribute:

      RemoteHttpServletRequest.java
      private CaseInsensitiveHashMap internalHeaders
      

      can end in a corrupted state, which prevents reading headers.

      This map is supposed to store: CaseInsentitveKey -> Object but offers an API which allows accessing the Object via their sensitive value.

      public boolean containsKey(Object key) {
              boolean retval;
              if (key instanceof String) {
                  CaseInsensitiveKey ciKey = new CaseInsensitiveKey((String) key);
                  retval = super.containsKey(ciKey);
              } else {
                  retval = super.containsKey(key);
              }
              return retval;
          }
      

      The problem from this design, which can allows a String key to be stored instead of its equivalent CaseInsentitiveKey.

      As CaseInsentitiveKey overrides the hashcode function:

          public int hashCode() {
              return mKey.toLowerCase().hashCode();
          }
      

      The String key would be stored in a different place in the map.
      ie : "myHeader" would be stored in

      table[10]

      , whereas "new CaseInsentitiveKey("myHeader")" would be stored in

      table[21]

      For reference, that's how objects are stored in a HashMap.

      HashMap.java
          public V get(Object key) {
              if (key == null)
                  return getForNullKey();
              int hash = hash(key.hashCode());
              for (Entry<K,V> e = table[indexFor(hash, table.length)];
                   e != null;
                   e = e.next) {
                  Object k;
                  if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                      return e.value;
              }
              return null;
          }
      

      In the case of the RemoteHttpServletRequest, the headers can be ended stored as a String, causing the deserialization to fail on the OpenAM server side. ie: OpenAM tries to find a header "myHeader" on position 21 but can't find it.

      How to fix this issue

      The fact that the RemoteHttpServletRequest uses this CaseInsensitiveHashMap is not necessary. It's probably imported for an old OpenAM that needed to be Java 5 compliant. We could simplify this function by refactoring the internalHeaders attribute into:

      private Map<CaseInsensitiveKey, Object> internalHeaders
      

      That way, Java itself will make sure we couldn't end with a String key on this map.

        Attachments

          Activity

            People

            • Assignee:
              quentin.castel Quentin CASTEL [X] (Inactive)
              Reporter:
              quentin.castel Quentin CASTEL [X] (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 4h
                4h
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 4h
                4h