com.hierynomus.msdfsc.DomainCache Maven / Gradle / Ivy
/*
* Copyright (C)2016 - SMBJ Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hierynomus.msdfsc;
import com.hierynomus.msdfsc.messages.DFSReferral;
import com.hierynomus.msdfsc.messages.SMB2GetDFSReferralResponse;
import com.hierynomus.protocol.commons.EnumWithValue;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* [MS-DFSC].pdf 3.1.1 Abstract Data Model DomainCache: Applicable only for a
* computer joined to a domain. This cache contains a list of trusted domains in
* both NetBIOS and fully qualified domain name forms, in addition to a list of
* DC host names for each domain. Conceptually, this is an array of tuples of
* the form . Cache lookup involves finding a
* DomainCache entry with a matching DomainName. This can be used to check for a
* valid domain name or to find a DC host name for a given domain name. DCHint
* identifies a DC host name from DCList that is the DC that was last
* successfully used by the DFS client.
*/
@SuppressWarnings("squid:S00116")
public class DomainCache {
private Map cache = new ConcurrentHashMap<>();
public static class DomainCacheEntry {
String domainName;
String DCHint;
List DCList;
/**
* 3.1.5.4.2 Receiving a DC Referral Response
* This is applicable only to a domain-joined computer. The DFS client receives this referral response for the DC referral request that it
* sent in step 5.2 of section 3.1.4.1. The DC referral response MUST be version 3 or later; otherwise, the client MUST ignore the referral response.
* The client MUST verify that the NumberOfReferrals field of the referral header is 1 and that the NameListReferral bit is set in the referral entry.
* The other bits of ReferralEntryFlags in the referral entry MUST be ignored. The NumberOfExpandedNames in the referral entry contains the number
* of DC names returned. The client MUST use the value in the NumberOfExpandedNames field to determine how many names are present in the list at
* ExpandedNameOffset. The client can access the first null-terminated Unicode DC name string that is returned by adding the value in the
* ExpandedNameOffset field to the address of the referral entry. Immediately following the null termination of a DC name is the next DC name returned.
* The client can access the null-terminated Unicode domain name that corresponds to the referral response by adding the value in the SpecialNameOffset
* to the address of the referral entry.
* The client MUST add the list of DCs determined for a domain name to DCList of the DomainCache entry that corresponds to the domain name.
* If the DomainCache entry's DCList is not empty, the client MUST replace it with the DC list from the referral response and set DCHint to the
* first DC in the new DCList.
*/
public DomainCacheEntry(SMB2GetDFSReferralResponse response) {
if (response.getReferralEntries().size() != 1) {
throw new IllegalStateException("Expecting exactly 1 referral for a domain referral, found: " + response.getReferralEntries().size());
}
DFSReferral dfsReferral = response.getReferralEntries().get(0);
if (!EnumWithValue.EnumUtils.isSet(dfsReferral.getReferralEntryFlags(), DFSReferral.ReferralEntryFlags.NameListReferral)) {
throw new IllegalStateException("Referral Entry for '" + dfsReferral.getSpecialName() + "' does not have NameListReferral bit set.");
}
domainName = dfsReferral.getSpecialName();
DCHint = dfsReferral.getExpandedNames().get(0);
DCList = dfsReferral.getExpandedNames();
}
public String getDomainName() {
return domainName;
}
public String getDCHint() {
return DCHint;
}
public List getDCList() {
return DCList;
}
public String toString() {
return domainName + "->" + DCHint + ", " + DCList;
}
}
public DomainCacheEntry lookup(String domainName) {
return cache.get(domainName);
}
public void put(DomainCacheEntry domainCacheEntry) {
cache.put(domainCacheEntry.domainName, domainCacheEntry);
}
}