📄 sid.java
字号:
/* jcifs smb client library in Java
* Copyright (C) 2006 "Michael B. Allen" <jcifs at samba dot org>
* "Eric Glass" <jcifs at samba dot org>
*
* 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.util.*;
import java.io.IOException;
import jcifs.util.Hexdump;
import jcifs.dcerpc.*;
import jcifs.dcerpc.msrpc.*;
/**
* A Windows SID is a numeric identifier used to represent Windows
* accounts. SIDs are commonly represented using a textual format such as
* <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt> but they may
* also be resolved to yield the name of the associated Windows account
* such as <tt>Administrators</tt> or <tt>MYDOM\alice</tt>.
* <p>
* Consider the following output of <tt>examples/SidLookup.java</tt>:
* <pre>
* toString: S-1-5-21-4133388617-793952518-2001621813-512
* toDisplayString: WNET\Domain Admins
* getType: 2
* getTypeText: Domain group
* getDomainName: WNET
* getAccountName: Domain Admins
* </pre>
*/
public class SID extends rpc.sid_t {
public static final int SID_TYPE_USE_NONE = lsarpc.SID_NAME_USE_NONE;
public static final int SID_TYPE_USER = lsarpc.SID_NAME_USER;
public static final int SID_TYPE_DOM_GRP = lsarpc.SID_NAME_DOM_GRP;
public static final int SID_TYPE_DOMAIN = lsarpc.SID_NAME_DOMAIN;
public static final int SID_TYPE_ALIAS = lsarpc.SID_NAME_ALIAS;
public static final int SID_TYPE_WKN_GRP = lsarpc.SID_NAME_WKN_GRP;
public static final int SID_TYPE_DELETED = lsarpc.SID_NAME_DELETED;
public static final int SID_TYPE_INVALID = lsarpc.SID_NAME_INVALID;
public static final int SID_TYPE_UNKNOWN = lsarpc.SID_NAME_UNKNOWN;
static final String[] SID_TYPE_NAMES = {
"0",
"User",
"Domain group",
"Domain",
"Local group",
"Builtin group",
"Deleted",
"Invalid",
"Unknown"
};
public static final int SID_FLAG_RESOLVE_SIDS = 0x0001;
public static SID EVERYONE = null;
public static SID CREATOR_OWNER = null;
public static SID SYSTEM = null;
static {
try {
EVERYONE = new SID("S-1-1-0");
CREATOR_OWNER = new SID("S-1-3-0");
SYSTEM = new SID("S-1-5-18");
} catch (SmbException se) {
}
}
static Map sid_cache = Collections.synchronizedMap(new HashMap());
static void resolveSids(DcerpcHandle handle,
LsaPolicyHandle policyHandle,
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++) {
sids[si].type = rpc.names.names[si].sid_type;
sids[si].domainName = null;
switch (sids[si].type) {
case SID_TYPE_USER:
case SID_TYPE_DOM_GRP:
case SID_TYPE_DOMAIN:
case SID_TYPE_ALIAS:
case SID_TYPE_WKN_GRP:
int sid_index = rpc.names.names[si].sid_index;
rpc.unicode_string ustr = rpc.domains.domains[sid_index].name;
sids[si].domainName = (new UnicodeString(ustr, false)).toString();
break;
}
sids[si].acctName = (new UnicodeString(rpc.names.names[si].name, false)).toString();
sids[si].origin_server = null;
sids[si].origin_auth = null;
}
}
static void resolveSids0(String authorityServerName,
NtlmPasswordAuthentication auth,
SID[] sids) throws IOException {
DcerpcHandle handle = null;
LsaPolicyHandle policyHandle = null;
try {
handle = DcerpcHandle.getHandle("ncacn_np:" + authorityServerName +
"[\\PIPE\\lsarpc]", auth);
String server = authorityServerName;
int dot = server.indexOf('.');
if (dot > 0 && Character.isDigit(server.charAt(0)) == false)
server = server.substring(0, dot);
policyHandle = new LsaPolicyHandle(handle, "\\\\" + server, 0x00000800);
SID.resolveSids(handle, policyHandle, sids);
} finally {
if (handle != null) {
if (policyHandle != null) {
policyHandle.close();
}
handle.close();
}
}
}
static public void resolveSids(String authorityServerName,
NtlmPasswordAuthentication auth,
SID[] sids,
int offset,
int length) throws IOException {
ArrayList list = new ArrayList(sids.length);
int si;
for (si = 0; si < length; si++) {
SID sid = (SID)sid_cache.get(sids[offset + si]);
if (sid != null) {
sids[offset + si].type = sid.type;
sids[offset + si].domainName = sid.domainName;
sids[offset + si].acctName = sid.acctName;
} else {
list.add(sids[offset + si]);
}
}
if (list.size() > 0) {
sids = (SID[])list.toArray(new SID[0]);
SID.resolveSids0(authorityServerName, auth, sids);
for (si = 0; si < sids.length; si++) {
sid_cache.put(sids[si], sids[si]);
}
}
}
/**
* Resolve an array of SIDs using a cache and at most one MSRPC request.
* <p>
* 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 auth The credentials that should be used to communicate with the named server. As usual, <tt>null</tt> indicates that default credentials should be used.
* @param sids The SIDs that should be resolved. After this function is called, the names associated with the SIDs may be queried with the <tt>toDisplayString</tt>, <tt>getDomainName</tt>, and <tt>getAccountName</tt> methods.
*/
static public void resolveSids(String authorityServerName,
NtlmPasswordAuthentication auth,
SID[] sids) throws IOException {
ArrayList list = new ArrayList(sids.length);
int si;
for (si = 0; si < sids.length; si++) {
SID sid = (SID)sid_cache.get(sids[si]);
if (sid != null) {
sids[si].type = sid.type;
sids[si].domainName = sid.domainName;
sids[si].acctName = sid.acctName;
} else {
list.add(sids[si]);
}
}
if (list.size() > 0) {
sids = (SID[])list.toArray(new SID[0]);
SID.resolveSids0(authorityServerName, auth, sids);
for (si = 0; si < sids.length; si++) {
sid_cache.put(sids[si], sids[si]);
}
}
}
public static SID getServerSid(String server,
NtlmPasswordAuthentication auth) throws IOException {
DcerpcHandle handle = null;
LsaPolicyHandle policyHandle = null;
lsarpc.LsarDomainInfo info = new lsarpc.LsarDomainInfo();
MsrpcQueryInformationPolicy rpc;
try {
handle = DcerpcHandle.getHandle("ncacn_np:" + server +
"[\\PIPE\\lsarpc]", auth);
// NetApp doesn't like the 'generic' access mask values
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,
SID.SID_TYPE_DOMAIN,
(new UnicodeString(info.name, false)).toString(),
null,
false);
} finally {
if (handle != null) {
if (policyHandle != null) {
policyHandle.close();
}
handle.close();
}
}
}
public static byte[] toByteArray(rpc.sid_t sid) {
byte[] dst = new byte[1 + 1 + 6 + sid.sub_authority_count * 4];
int di = 0;
dst[di++] = sid.revision;
dst[di++] = sid.sub_authority_count;
System.arraycopy(sid.identifier_authority, 0, dst, di, 6);
di += 6;
for (int ii = 0; ii < sid.sub_authority_count; ii++) {
jcifs.util.Encdec.enc_uint32le(sid.sub_authority[ii], dst, di);
di += 4;
}
return dst;
}
int type;
String domainName = null;
String acctName = null;
String origin_server = null;
NtlmPasswordAuthentication origin_auth = null;
/*
* Construct a SID from it's binary representation.
*/
public SID(byte[] src, int si) {
revision = src[si++];
sub_authority_count = src[si++];
identifier_authority = new byte[6];
System.arraycopy(src, si, identifier_authority, 0, 6);
si += 6;
if (sub_authority_count > 100)
throw new RuntimeException( "Invalid SID sub_authority_count" );
sub_authority = new int[sub_authority_count];
for (int i = 0; i < sub_authority_count; i++) {
sub_authority[i] = ServerMessageBlock.readInt4( src, si );
si += 4;
}
}
/**
* Construct a SID from it's textual representation such as
* <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
*/
public SID(String textual) throws SmbException {
StringTokenizer st = new StringTokenizer(textual, "-");
if (st.countTokens() < 3 || !st.nextToken().equals("S"))
// need S-N-M
throw new SmbException("Bad textual SID format: " + textual);
this.revision = Byte.parseByte(st.nextToken());
String tmp = st.nextToken();
long id = 0;
if (tmp.startsWith("0x"))
id = Long.parseLong(tmp.substring(2), 16);
else
id = Long.parseLong(tmp);
this.identifier_authority = new byte[6];
for (int i = 5; id > 0; i--) {
this.identifier_authority[i] = (byte) (id % 256);
id >>= 8;
}
this.sub_authority_count = (byte) st.countTokens();
if (this.sub_authority_count > 0) {
this.sub_authority = new int[this.sub_authority_count];
for (int i = 0; i < this.sub_authority_count; i++)
this.sub_authority[i] = (int)(Long.parseLong(st.nextToken()) & 0xFFFFFFFFL);
}
}
/**
* Construct a SID from a domain SID and an RID
* (relative identifier). For example, a domain SID
* <tt>S-1-5-21-1496946806-2192648263-3843101252</tt> and RID <tt>1029</tt> would
* yield the SID <tt>S-1-5-21-1496946806-2192648263-3843101252-1029</tt>.
*/
public SID(SID domsid, int rid) {
this.revision = domsid.revision;
this.identifier_authority = domsid.identifier_authority;
this.sub_authority_count = (byte)(domsid.sub_authority_count + 1);
this.sub_authority = new int[this.sub_authority_count];
int i;
for (i = 0; i < domsid.sub_authority_count; i++) {
this.sub_authority[i] = domsid.sub_authority[i];
}
this.sub_authority[i] = rid;
}
public SID(rpc.sid_t sid,
int type,
String domainName,
String acctName,
boolean decrementAuthority) {
this.revision = sid.revision;
this.sub_authority_count = sid.sub_authority_count;
this.identifier_authority = sid.identifier_authority;
this.sub_authority = sid.sub_authority;
this.type = type;
this.domainName = domainName;
this.acctName = acctName;
if (decrementAuthority) {
this.sub_authority_count--;
this.sub_authority = new int[sub_authority_count];
for (int i = 0; i < this.sub_authority_count; i++) {
this.sub_authority[i] = sid.sub_authority[i];
}
}
}
public SID getDomainSid() {
return new SID(this,
SID_TYPE_DOMAIN,
this.domainName,
null,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -