1diff -ruNd --strip-trailing-cr jcifs_1.2.20c/src/jcifs/dcerpc/msrpc/MsrpcLookupNames.java jcifs_1.2.20c+LsaLookupNames/src/jcifs/dcerpc/msrpc/MsrpcLookupNames.java 2--- jcifs_1.2.20c/src/jcifs/dcerpc/msrpc/MsrpcLookupNames.java 1970-01-01 01:00:00.000000000 +0100 3+++ jcifs_1.2.20c+LsaLookupNames/src/jcifs/dcerpc/msrpc/MsrpcLookupNames.java 2008-04-21 23:54:24.000000000 +0200 4@@ -0,0 +1,16 @@ 5+package jcifs.dcerpc.msrpc; 6+ 7+ 8+public class MsrpcLookupNames extends lsarpc.LsarLookupNames { 9+ public MsrpcLookupNames(LsaPolicyHandle policyHandle, String names[]) { 10+ super( 11+ policyHandle, 12+ names, 13+ (short)1, 14+ 0 15+ ); 16+ 17+ ptype = 0; 18+ flags = DCERPC_FIRST_FRAG | DCERPC_LAST_FRAG; 19+ } 20+} 21diff -ruNd --strip-trailing-cr jcifs_1.2.20c/src/jcifs/dcerpc/msrpc/lsarpc.java jcifs_1.2.20c+LsaLookupNames/src/jcifs/dcerpc/msrpc/lsarpc.java 22--- jcifs_1.2.20c/src/jcifs/dcerpc/msrpc/lsarpc.java 2008-04-25 19:34:39.000000000 +0200 23+++ jcifs_1.2.20c+LsaLookupNames/src/jcifs/dcerpc/msrpc/lsarpc.java 2008-05-23 16:44:42.000000000 +0200 24@@ -1,5 +1,7 @@ 25 package jcifs.dcerpc.msrpc; 26 27+import java.nio.charset.Charset; 28+ 29 import jcifs.dcerpc.*; 30 import jcifs.dcerpc.ndr.*; 31 32@@ -848,6 +850,93 @@ 33 retval = (int)_src.dec_ndr_long(); 34 } 35 } 36+ public static class LsarLookupNames extends DcerpcMessage { 37+ protected static final Charset csULU = Charset.forName("UnicodeLittleUnmarked"); 38+ 39+ public int getOpnum() { return 0x0e; } 40+ 41+ public int retval; 42+ public rpc.policy_handle handle; 43+ public String names[]; 44+ public LsarRefDomainList domains; 45+ public LsarTransSidArray sids; 46+ public short level; 47+ public int count; 48+ 49+ public LsarLookupNames( 50+ rpc.policy_handle handle, 51+ String names[], 52+ short level, 53+ int count 54+ ) { 55+ this.handle = handle; 56+ this.names = names; 57+ this.level = level; 58+ this.count = count; 59+ } 60+ 61+ public void encode_in(NdrBuffer _dst) throws NdrException { 62+ handle.encode(_dst); 63+ 64+ _dst.align(4); 65+ 66+ _dst.enc_ndr_long(names.length); 67+ _dst.enc_ndr_long(names.length); 68+ 69+ for(int i = 0; i < names.length; ++i) { 70+ int wlen = 2 * names[i].length(); 71+ 72+ _dst.enc_ndr_short(wlen); 73+ _dst.enc_ndr_short(wlen); 74+ _dst.enc_ndr_long(1); 75+ } 76+ 77+ // Encode names 78+ for(int i = 0; i < names.length; ++i) { 79+ String name = names[i]; 80+ int len = name.length(); 81+ 82+ _dst.enc_ndr_long(len); 83+ _dst.enc_ndr_long(0); 84+ _dst.enc_ndr_long(len); 85+ 86+ System.arraycopy( 87+ name.getBytes(csULU), 0, 88+ _dst.buf, _dst.index, 89+ 2 * len 90+ ); 91+ _dst.advance(2 * len); 92+ 93+ _dst.align(4); 94+ } 95+ 96+ _dst.enc_ndr_long(0); // num_trans_entries 97+ _dst.enc_ndr_long(0); // ptr_trans_sids 98+ 99+ _dst.enc_ndr_short(level); // lookup_level 100+ _dst.align(4); 101+ 102+ _dst.enc_ndr_long(count); // mapped_count 103+ } 104+ 105+ public void decode_out(NdrBuffer _src) throws NdrException { 106+ _src.align(4); 107+ 108+ int _domainsp = _src.dec_ndr_long(); 109+ if(_domainsp != 0) { 110+ if(domains == null) /* YOYOYO */ 111+ domains = new LsarRefDomainList(); 112+ domains.decode(_src); 113+ } 114+ 115+ if(sids == null) 116+ sids = new LsarTransSidArray(); 117+ sids.decode(_src); 118+ 119+ count = (int)_src.dec_ndr_long(); 120+ retval = (int)_src.dec_ndr_long(); 121+ } 122+ } 123 public static class LsarOpenPolicy2 extends DcerpcMessage { 124 125 public int getOpnum() { return 0x2c; } 126diff -ruNd --strip-trailing-cr jcifs_1.2.20c/src/jcifs/smb/SID.java jcifs_1.2.20c+LsaLookupNames/src/jcifs/smb/SID.java 127--- jcifs_1.2.20c/src/jcifs/smb/SID.java 2008-04-25 19:34:39.000000000 +0200 128+++ jcifs_1.2.20c+LsaLookupNames/src/jcifs/smb/SID.java 2008-05-23 16:42:24.000000000 +0200 129@@ -696,5 +696,198 @@ 130 } 131 } 132 } 133-} 134 135+ /** 136+ * <p>This function maps the array of domain object names <b>names</b> to their 137+ * equivalent <b>SID</b>s.</p> 138+ * 139+ * <p>Note that the LsaPolicyHandle passed to this function must be created at least 140+ * with access 0x00000800 (POLICY_LOOKUP_NAMES), otherwise it will throw an 141+ * IOException.</p> 142+ * 143+ * <p>On success, the returned <b>SID</b>s are named according the content of the 144+ * <b>names</b> array. Thereby, the case of their <b>acctName</b> fields may 145+ * be incorrect since names are mapped ignoring their case. If you want to 146+ * obtain the <b>acctName</b> exactly as it is stored in the server, you need 147+ * to issue a <b>resolve()</b> call on the <b>SID</b>, or use one of the 148+ * various <b>resolveSids()</b> variants. However, the domain part of the names 149+ * is always correct, since the server communicates it in its response.</p> 150+ * 151+ * <p>Also note that any unresolved name will map to a null value in the related 152+ * entry in the returned SIDs array. No exception will be thrown.</p> 153+ * 154+ * @param handle The <b>DcerpcHandle</b> object to use to communicate with the 155+ * LSA service 156+ * @param policyHandle The <b>LsaPolicyHandle</b> to use in order to get 157+ * authorized by the LSA service. 158+ * @param names An array of strings containing the domain's object names to map. 159+ * @return An array of <b>SID</b>s one-to-one related with the given <b>names</b>. 160+ * @throws IOException if anything goes wrong 161+ * @author Giampaolo Tomassoni <giampaolo at tomassoni dot biz> 162+ */ 163+ public static SID[] getFromNames( 164+ DcerpcHandle handle, 165+ LsaPolicyHandle policyHandle, 166+ String names[] 167+ ) throws IOException { 168+ SID outputSids[] = new SID[names.length]; 169+ if(names.length > 0) { 170+ MsrpcLookupNames rpc = new MsrpcLookupNames(policyHandle, names); 171+ handle.sendrecv(rpc); 172+ switch (rpc.retval) { 173+ case 0: 174+ case NtStatus.NT_STATUS_NONE_MAPPED: 175+ case 0x00000107: // NT_STATUS_SOME_NOT_MAPPED 176+ break; 177+ 178+ default: 179+ throw new SmbException(rpc.retval, false); 180+ } 181+ 182+ SID domainSids[] = new SID[rpc.domains.count]; 183+ for(int i = 0; i < domainSids.length; ++i) { 184+ SID domainSid = new SID( 185+ rpc.domains.domains[i].sid, 186+ SID_TYPE_DOMAIN, 187+ (new UnicodeString(rpc.domains.domains[i].name, false)).toString(), 188+ null, 189+ false 190+ ); 191+ 192+ domainSids[i] = domainSid; 193+ } 194+ 195+ for(int i = 0; i < rpc.sids.count; ++i) { 196+ SID sid; 197+ switch(rpc.sids.sids[i].sid_type) { 198+ case SID_TYPE_DOMAIN: 199+ sid = domainSids[rpc.sids.sids[i].sid_index]; 200+ break; 201+ 202+ case SID_TYPE_INVALID: 203+ case SID_TYPE_UNKNOWN: 204+ // Probably the result of an attempt to resolve an 205+ // not existent or bad name 206+ sid = null; 207+ break; 208+ 209+ default: 210+ SID domainSid = domainSids[rpc.sids.sids[i].sid_index]; 211+ sid = new SID(domainSid, rpc.sids.sids[i].rid); 212+ sid.type = rpc.sids.sids[i].sid_type; 213+ sid.domainName = domainSid.domainName; 214+ 215+ // If the specified name includes domain data, this must be 216+ // removed from acctName. 217+ sid.acctName = names[i].substring(names[i].indexOf('\\') + 1); 218+ } 219+ 220+ outputSids[i] = sid; 221+ } 222+ } 223+ 224+ return(outputSids); 225+ } 226+ 227+ /** 228+ * <p>This function maps the array of domain object names <b>names</b> to their 229+ * equivalent <b>SID</b>s.</p> 230+ * 231+ * <p>On success, the returned <b>SID</b>s are named according the content of the 232+ * <b>names</b> array. Thereby, the case of their <b>acctName</b> fields may 233+ * be incorrect since names are mapped ignoring their case. If you want to 234+ * obtain the <b>acctName</b> exactly as it is stored in the server, you need 235+ * to issue a <b>resolve()</b> call on the <b>SID</b>, or use one of the 236+ * various <b>resolveSids()</b> variants. However, the domain part of the names 237+ * is always correct, since the server communicates it in its response.</p> 238+ * 239+ * <p>Also note that any unresolved name will map to a null value in the related 240+ * entry in the returned SIDs array. No exception will be thrown.</p> 241+ * 242+ * @param authorityServerName The name or address of the authority server to 243+ * contact to resolve the names. 244+ * @param auth The <b>NtlmPasswordAuthentication</b> to use in order to get 245+ * authorized by the server. 246+ * @param names An array of strings containing the domain's object names to map. 247+ * @return An array of <b>SID</b>s one-to-one related with the given <b>names</b>. 248+ * @throws IOException if anything goes wrong 249+ * @author Giampaolo Tomassoni <giampaolo at tomassoni dot biz> 250+ */ 251+ public static SID[] getFromNames( 252+ String authorityServerName, 253+ NtlmPasswordAuthentication auth, 254+ String names[] 255+ ) throws IOException { 256+ DcerpcHandle handle = DcerpcHandle.getHandle( 257+ "ncacn_np:" + authorityServerName + "[\\PIPE\\lsarpc]", 258+ auth 259+ ); 260+ try { 261+ int dot = authorityServerName.indexOf('.'); 262+ 263+ String serverName; 264+ if(dot > 0 && !Character.isDigit(authorityServerName.charAt(0))) 265+ serverName = authorityServerName.substring(0, dot); 266+ else 267+ serverName = authorityServerName; 268+ 269+ LsaPolicyHandle policyHandle = new LsaPolicyHandle( 270+ handle, 271+ "\\\\" + serverName, 272+ 0x00000800 // POLICY_LOOKUP_NAMES 273+ ); 274+ try { return(getFromNames(handle, policyHandle, names)); } 275+ finally { policyHandle.close(); } 276+ } finally { handle.close(); } 277+ } 278+ 279+ /** 280+ * <p>This function is like the <b>getFromNames()</b> one, except that it maps a 281+ * single name to its <b>SID</b> equivalent.</p> 282+ * 283+ * <p>If you have more than one name to map, <b>getFromNames()</b> is much more 284+ * efficient.</p> 285+ * 286+ * @param handle The <b>DcerpcHandle</b> object to use to communicate with the 287+ * LSA service 288+ * @param policyHandle The <b>LsaPolicyHandle</b> to use in order to get 289+ * authorized by the LSA service. 290+ * @param name A string containing the domain's object name to map. 291+ * @return The <b>SID</b>s mapped to the given <b>name</b>. 292+ * @throws IOException if anything goes wrong 293+ * @author Giampaolo Tomassoni <giampaolo at tomassoni dot biz> 294+ */ 295+ public static SID getFromName( 296+ DcerpcHandle handle, 297+ LsaPolicyHandle policyHandle, 298+ String name 299+ ) throws IOException { 300+ SID sids[] = getFromNames(handle, policyHandle, new String[] { name }); 301+ return(sids == null || sids.length == 0 ? null : sids[0]); 302+ } 303+ 304+ /** 305+ * <p>This function is like the <b>getFromNames()</b> one, except that it maps a 306+ * single name to its <b>SID</b> equivalent.</p> 307+ * 308+ * <p>If you have more than one name to map, <b>getFromNames()</b> is much more 309+ * efficient.</p> 310+ * 311+ * @param authorityServerName The name or address of the authority server to 312+ * contact to resolve the names. 313+ * @param auth The <b>NtlmPasswordAuthentication</b> to use in order to get 314+ * authorized by the server. 315+ * @param name A string containing the domain's object name to map. 316+ * @return The <b>SID</b>s mapped to the given <b>name</b>. 317+ * @throws IOException if anything goes wrong 318+ * @author Giampaolo Tomassoni <giampaolo at tomassoni dot biz> 319+ */ 320+ public static SID getFromName( 321+ String authorityServerName, 322+ NtlmPasswordAuthentication auth, 323+ String name 324+ ) throws IOException { 325+ SID sids[] = getFromNames(authorityServerName, auth, new String[] { name }); 326+ return(sids == null || sids.length == 0 ? null : sids[0]); 327+ } 328+} 329