All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jcifs.smb.SIDCacheImpl Maven / Gradle / Ivy

There is a newer version: 2.1.10
Show newest version
/*
 * © 2016 AgNO3 Gmbh & Co. KG
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package jcifs.smb;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jcifs.CIFSContext;
import jcifs.CIFSException;
import jcifs.SidResolver;
import jcifs.dcerpc.DcerpcHandle;
import jcifs.dcerpc.UnicodeString;
import jcifs.dcerpc.rpc;
import jcifs.dcerpc.rpc.sid_t;
import jcifs.dcerpc.msrpc.LsaPolicyHandle;
import jcifs.dcerpc.msrpc.MsrpcEnumerateAliasesInDomain;
import jcifs.dcerpc.msrpc.MsrpcGetMembersInAlias;
import jcifs.dcerpc.msrpc.MsrpcLookupSids;
import jcifs.dcerpc.msrpc.MsrpcQueryInformationPolicy;
import jcifs.dcerpc.msrpc.SamrAliasHandle;
import jcifs.dcerpc.msrpc.SamrDomainHandle;
import jcifs.dcerpc.msrpc.SamrPolicyHandle;
import jcifs.dcerpc.msrpc.lsarpc;
import jcifs.dcerpc.msrpc.lsarpc.LsarTranslatedName;
import jcifs.dcerpc.msrpc.samr;


/**
 * Internal use only: SID resolver cache
 * 
 * @author mbechler
 * @internal
 */
public class SIDCacheImpl implements SidResolver {

    private Map sidCache = new HashMap<>();


    /**
     * @param baseContext
     */
    public SIDCacheImpl ( CIFSContext baseContext ) {}


    void resolveSids ( DcerpcHandle handle, LsaPolicyHandle policyHandle, jcifs.SID[] sids ) throws IOException {
        MsrpcLookupSids rpc = new MsrpcLookupSids(policyHandle, sids);
        handle.sendrecv(rpc);
        switch ( rpc.retval ) {
        case 0:
        case NtStatus.NT_STATUS_NONE_MAPPED:
        case 0x00000107: // NT_STATUS_SOME_NOT_MAPPED
            break;
        default:
            throw new SmbException(rpc.retval, false);
        }

        for ( int si = 0; si < sids.length; si++ ) {
            SID out = sids[ si ].unwrap(SID.class);
            LsarTranslatedName resp = rpc.names.names[ si ];
            out.domainName = null;
            switch ( resp.sid_type ) {
            case jcifs.SID.SID_TYPE_USER:
            case jcifs.SID.SID_TYPE_DOM_GRP:
            case jcifs.SID.SID_TYPE_DOMAIN:
            case jcifs.SID.SID_TYPE_ALIAS:
            case jcifs.SID.SID_TYPE_WKN_GRP:
                rpc.unicode_string ustr = rpc.domains.domains[ resp.sid_index ].name;
                out.domainName = ( new UnicodeString(ustr, false) ).toString();
                break;
            }

            UnicodeString ucstr = new UnicodeString(resp.name, false);
            out.acctName = ucstr.toString();
            out.type = resp.sid_type;
            out.origin_server = null;
            out.origin_ctx = null;
        }
    }


    void resolveSids0 ( String authorityServerName, CIFSContext tc, jcifs.SID[] sids ) throws CIFSException {
        synchronized ( this.sidCache ) {
            try ( DcerpcHandle handle = DcerpcHandle.getHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\lsarpc]", tc) ) {
                String server = authorityServerName;
                int dot = server.indexOf('.');
                if ( dot > 0 && Character.isDigit(server.charAt(0)) == false )
                    server = server.substring(0, dot);
                try ( LsaPolicyHandle policyHandle = new LsaPolicyHandle(handle, "\\\\" + server, 0x00000800) ) {
                    resolveSids(handle, policyHandle, sids);
                }
            }
            catch ( IOException e ) {
                throw new CIFSException("Failed to resolve SIDs", e);
            }
        }
    }


    @Override
    public void resolveSids ( CIFSContext tc, String authorityServerName, jcifs.SID[] sids, int offset, int length ) throws CIFSException {
        ArrayList list = new ArrayList<>(sids.length);
        int si;

        synchronized ( this.sidCache ) {
            for ( si = 0; si < length; si++ ) {
                SID s = sids[ offset + si ].unwrap(SID.class);
                SID sid = this.sidCache.get(s);
                if ( sid != null ) {
                    s.type = sid.type;
                    s.domainName = sid.domainName;
                    s.acctName = sid.acctName;
                }
                else {
                    list.add(s);
                }
            }

            if ( list.size() > 0 ) {
                SID[] resolved = list.toArray(new SID[list.size()]);
                resolveSids0(authorityServerName, tc, resolved);
                for ( si = 0; si < resolved.length; si++ ) {
                    this.sidCache.put(resolved[ si ], resolved[ si ]);
                }
            }
        }
    }


    /**
     * Resolve an array of SIDs using a cache and at most one MSRPC request.
     * 

* This method will attempt * to resolve SIDs using a cache and cache the results of any SIDs that * required resolving with the authority. SID cache entries are currently not * expired because under normal circumstances SID information never changes. * * @param authorityServerName * The hostname of the server that should be queried. For maximum efficiency this should be the hostname * of a domain controller however a member server will work as well and a domain controller may not * return names for SIDs corresponding to local accounts for which the domain controller is not an * authority. * @param tc * The context that should be used to communicate with the named server. * @param sids * The SIDs that should be resolved. After this function is called, the names associated with the SIDs * may be queried with the toDisplayString, getDomainName, and getAccountName * methods. */ @Override public void resolveSids ( CIFSContext tc, String authorityServerName, jcifs.SID[] sids ) throws CIFSException { ArrayList list = new ArrayList<>(sids.length); int si; synchronized ( this.sidCache ) { for ( si = 0; si < sids.length; si++ ) { SID s = sids[ si ].unwrap(SID.class); SID sid = this.sidCache.get(s); if ( sid != null ) { s.type = sid.type; s.domainName = sid.domainName; s.acctName = sid.acctName; } else { list.add(s); } } if ( list.size() > 0 ) { SID[] resolved = list.toArray(new SID[list.size()]); resolveSids0(authorityServerName, tc, resolved); for ( si = 0; si < resolved.length; si++ ) { this.sidCache.put(resolved[ si ], resolved[ si ]); } } } } @Override public SID getServerSid ( CIFSContext tc, String server ) throws CIFSException { lsarpc.LsarDomainInfo info = new lsarpc.LsarDomainInfo(); MsrpcQueryInformationPolicy rpc; synchronized ( this.sidCache ) { try ( DcerpcHandle handle = DcerpcHandle.getHandle("ncacn_np:" + server + "[\\PIPE\\lsarpc]", tc) ) { // NetApp doesn't like the 'generic' access mask values try ( LsaPolicyHandle policyHandle = new LsaPolicyHandle(handle, null, 0x00000001) ) { rpc = new MsrpcQueryInformationPolicy(policyHandle, (short) lsarpc.POLICY_INFO_ACCOUNT_DOMAIN, info); handle.sendrecv(rpc); if ( rpc.retval != 0 ) throw new SmbException(rpc.retval, false); } return new SID(info.sid, jcifs.SID.SID_TYPE_DOMAIN, ( new UnicodeString(info.name, false) ).toString(), null, false); } catch ( IOException e ) { throw new CIFSException("Failed to get SID from server", e); } } } @Override public SID[] getGroupMemberSids ( CIFSContext tc, String authorityServerName, jcifs.SID domsid, int rid, int flags ) throws CIFSException { lsarpc.LsarSidArray sidarray = new lsarpc.LsarSidArray(); MsrpcGetMembersInAlias rpc = null; synchronized ( this.sidCache ) { try ( DcerpcHandle handle = DcerpcHandle.getHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]", tc) ) { SamrPolicyHandle policyHandle = new SamrPolicyHandle(handle, authorityServerName, 0x00000030); SamrDomainHandle domainHandle = new SamrDomainHandle(handle, policyHandle, 0x00000200, domsid.unwrap(sid_t.class)); try ( SamrAliasHandle aliasHandle = new SamrAliasHandle(handle, domainHandle, 0x0002000c, rid) ) { rpc = new MsrpcGetMembersInAlias(aliasHandle, sidarray); handle.sendrecv(rpc); if ( rpc.retval != 0 ) throw new SmbException(rpc.retval, false); SID[] sids = new SID[rpc.sids.num_sids]; String origin_server = handle.getServer(); CIFSContext origin_ctx = handle.getTransportContext(); for ( int i = 0; i < sids.length; i++ ) { sids[ i ] = new SID(rpc.sids.sids[ i ].sid, 0, null, null, false); sids[ i ].origin_server = origin_server; sids[ i ].origin_ctx = origin_ctx; } if ( sids.length > 0 && ( flags & SID.SID_FLAG_RESOLVE_SIDS ) != 0 ) { resolveSids(origin_ctx, origin_server, sids); } return sids; } } catch ( IOException e ) { throw new CIFSException("Failed to get group member SIDs", e); } } } /** * * {@inheritDoc} * * @see jcifs.SidResolver#getLocalGroupsMap(jcifs.CIFSContext, java.lang.String, int) */ @Override public Map> getLocalGroupsMap ( CIFSContext tc, String authorityServerName, int flags ) throws CIFSException { SID domSid = getServerSid(tc, authorityServerName); synchronized ( this.sidCache ) { try ( DcerpcHandle handle = DcerpcHandle.getHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]", tc) ) { samr.SamrSamArray sam = new samr.SamrSamArray(); try ( SamrPolicyHandle policyHandle = new SamrPolicyHandle(handle, authorityServerName, 0x02000000); SamrDomainHandle domainHandle = new SamrDomainHandle(handle, policyHandle, 0x02000000, domSid) ) { MsrpcEnumerateAliasesInDomain rpc = new MsrpcEnumerateAliasesInDomain(domainHandle, 0xFFFF, sam); handle.sendrecv(rpc); if ( rpc.retval != 0 ) { throw new SmbException(rpc.retval, false); } Map> map = new HashMap<>(); for ( int ei = 0; ei < rpc.sam.count; ei++ ) { samr.SamrSamEntry entry = rpc.sam.entries[ ei ]; SID[] mems = getGroupMemberSids(tc, authorityServerName, domSid, entry.idx, flags); SID groupSid = new SID(domSid, entry.idx); groupSid.type = jcifs.SID.SID_TYPE_ALIAS; groupSid.domainName = domSid.getDomainName(); groupSid.acctName = ( new UnicodeString(entry.name, false) ).toString(); for ( int mi = 0; mi < mems.length; mi++ ) { List groups = map.get(mems[ mi ]); if ( groups == null ) { groups = new ArrayList<>(); map.put(mems[ mi ], groups); } if ( !groups.contains(groupSid) ) groups.add(groupSid); } } return map; } } catch ( IOException e ) { throw new CIFSException("Failed to resolve groups", e); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy