You are not logged in.

Unanswered posts



Important! This site has been replaced. All content here is read-only. Please visit our brand-new community at https://community.talend.com/. We look forward to hearing from you there!



#1 2010-08-06 13:08:34

ldapmadguy
Member
5 posts

ldapmadguy said:

[resolved] tLdapInput : decoding the objectSID Attribute

Hello,

I am using a tLdapInput to read Active Directory attributes. It gets perfectly String attributes  such as cn, distinguishedName, ...
However, I cannot handle Microsoft Active Directory objectSid which is a binary type.


When guessing metadata schema, Talend Open Studio detects a "String" type. I have forced the metadata to be byte[] but I have errors "cannot convert byte[] to string".

Following the article http://www.jroller.com/eyallupu/entry/j … to_convert I have developped two routines to handle the String and convert objectSid to S-1-IdentifierAuthority-SubAuthority1-SubAuthority2-...-SubAuthorityn

public static byte[] convertStringToByteArray(String objectSidAsString) {    
        byte[] theByteArray = objectSidAsString.getBytes();
        return theByteArray;
}

but it looks like when I used this method getSIDAsString  from http://www.jroller.com/eyallupu/entry/j … to_convert  I have an error.

Are there any tricks to implement such as base64 encoding ? If so how ?

Should I use an Object java type for objectSid and use some ByteArrayOutputStream to deal with the object ? I have tried the following routine, but the method getSIDAsString in the article http://www.jroller.com/eyallupu/entry/j … to_convert  does not work either.

public static byte[] getBytes(Object obj) throws java.io.IOException{
              ByteArrayOutputStream bos = new ByteArrayOutputStream();
              ObjectOutputStream oos = new ObjectOutputStream(bos);
                  
              oos.writeObject(obj);
              oos.flush();
              oos.close();
              bos.close();
              
              byte [] data = bos.toByteArray();
                      return data;

}

I bet it is an encoding issue but I do not understand what I should do.

Any idea ? Should I have to develop a tLdapInput component handling this case ?

Thanks. Olivier

Last edited by ldapmadguy (2010-08-06 13:11:53)

Offline

#2 2010-08-06 19:49:31

ldapmadguy
Member
5 posts

ldapmadguy said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

After investigation a bit,  I have written the following class:


public class objectSIDConv {

public static String getSIDAsString(String objectSid) {

    // Add the 'S' prefix
    String strSID = "";
    int version;
    long authority;
    int count;
    String rid = "";
    strSID = "S";
    byte[] SID = new byte[0];;
    byte[] defaultBytes;
    String roundTrip ="";

   
    SID =  objectSid.getBytes();

    // get version

    version = SID[0];
    strSID = strSID + "-" + Integer.toString(version);
        for (int i=2; i<=7; i++) {
            rid += byte2hex(SID[i]);
        }
       
       
        // get authority
        authority = Long.parseLong(rid);
        strSID = strSID + "-" + Long.toString(authority);
   
       
        //next byte is the count of sub-authorities
        count = SID[1]&0xFF;

        System.out.println("version + Authority + Sub-auth-nb = " +rid + strSID + count);
               
        //iterate all the sub-auths
        for (int i=0;i<count;i++) {
            rid = "";
            for (int j=11; j>7; j--) {
                rid += byte2hex(SID[j+(i*4)]);
               
                System.out.println("sub-auth = " + rid);
            }
            strSID = strSID + "-" + Long.parseLong(rid,16);
        }
        System.out.println("Final = " + strSID);
   
    // That's it - we have the SID
        return strSID;   

}
}



BUT I still have errors:

Exception in component tMap_1
java.lang.ArrayIndexOutOfBoundsException: 27
    at routines.objectSIDConv.getSIDAsString(objectSIDConv.java:283)
    at certfi.test_ad_pmad_0_1.test_AD_PMAD.tLDAPInput_1Process(test_AD_PMAD.java:1314)
    at certfi.test_ad_pmad_0_1.test_AD_PMAD.runJobInTOS(test_AD_PMAD.java:1869)
    at certfi.test_ad_pmad_0_1.test_AD_PMAD.main(test_AD_PMAD.java:1743)

It looks like that  SID =  objectSid.getBytes() returns corrupt chain byte[] type. Is there any encoding required such as base64 ???

Many thanks. Olivier

Offline

#3 2010-08-06 21:16:43

ldapmadguy
Member
5 posts

ldapmadguy said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

Actually I confirm even when the method getSIDAsString ends up without any errors, I have buggy results, objectSID computed with the method are incorrect (different from objectSid that I browse with other tool such as apache directory studio) .

There is an encoding issue ...
Please help !

Offline

#4 2010-08-09 21:25:03

ldapmadguy
Member
5 posts

ldapmadguy said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

Okay, finally I have fixed the problem.

objectSid is a byte[] asn.1 encoded. It is not possible to "get" it directly from LDAP in string and then use method such as public static String getSIDAsString(String objectSid). It cannot work.
You must use env.put("java.naming.ldap.attributes.binary","objectSid"); 

Next problem is : if you open an ldap request per objectSid you will quickly open too much connections. Ldap pool (establishing one session, and sharing this session to perform your ldap requests) is highly recommended.


In order to do so,  I have designed one routine and also the following design :

tLDAPInput ----> tJavaRow ---> tLogrow --> tFileOutpuExcel

tJavaRow's code is the following:

      output_row.cn = input_row.cn;
          output_row.SID = routines.UsePool.LdapPoolSid(input_row.cn);

Add int the output schema an "SID" row with String type.


Here is the code of the routine UsePool  (quick & dirty):


import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;

public class UsePool {

//     @SuppressWarnings("unchecked")
    public static String LdapPoolSid(String objectName) {
            // Set up environment for creating initial context
            Hashtable env = new Hashtable(11);
            env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
           
            String dirRoot = "/ou= People,DC=mycompany,DC=com";

                       String adminName = "cn=myadmin, ou=srvaccount, ou=it, DC=mycompany,DC=com";
                       String adminPassword ="itisasecret";
                       String ldapURL ="ldap://myserver:389";

        //set security credentials, note using simple cleartext authentication
            env.put(Context.SECURITY_AUTHENTICATION,"simple");
            env.put(Context.SECURITY_PRINCIPAL,adminName);
            env.put(Context.SECURITY_CREDENTIALS,adminPassword);
   
            //connect to my domain controller
            //env.put(Context.PROVIDER_URL, ldapURL);
           
            // Enable connection pooling
            env.put("com.sun.jndi.ldap.connect.pool", "true");

            //specify attributes to be returned in binary format
            env.put("java.naming.ldap.attributes.binary","objectSID");
   
            try {
                //connect to my domain controller
                env.put(Context.PROVIDER_URL, ldapURL);
               
                env.put("com.sun.jndi.ldap.netscape.schemaBugs", "true");
                                 // debug only
                //env.put("com.sun.jndi.ldap.trace.ber", System.out);
           

                // Create one initial context (Get connection from pool)
                DirContext ctx = new InitialDirContext(env);
               
               
                //Setup the search object. With this, we will pass in a base DN, and search all the child nodes
                //In the ldap
                SearchControls searchControls = new SearchControls();
                searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                
              //specify the LDAP search filter
               String searchFilter = "(&(objectClass=user)(cn=" + objectName +"))";
            
                
              //Specify the Base for the search
                String searchBase ="DC=fr,DC=ema,DC=ad,DC=pwcinternal,DC=com";

              //initialize counter to total the group members for debug ... not useful here
        int totalResults = 0;
    

                //Specify the attributes to return
                String returnedAtts[]={"cn","distinguishedName","objectSID"};
                searchControls.setReturningAttributes(returnedAtts);

                //Search for objects using the filter
                NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchControls);

                //Loop through the search results
                while (answer.hasMoreElements()) {
                    SearchResult sr = (SearchResult)answer.next();

                    Attributes attrs = sr.getAttributes();

                    if (attrs != null) {                        
                        try {
                            for (NamingEnumeration ae = attrs.getAll();ae.hasMore();) {
                                Attribute attr = (Attribute)ae.next();
    //                            System.out.println("Attribute: " + attr.getID());
                               
                                                               
                                System.out.println("XXXXXXXXXXX " +attrs.get("cn").get());
                               
                                byte[] SID = (byte[])attrs.get("objectSID").get();
                                String strSID = getSIDasStringOfBytes(SID);

                                System.out.println("YYYYYYYYYYYYYY " + strSID );
                                return strSID;
                            }
    
                        }    
                        catch (NamingException e)    {
                            System.err.println("Problem listing membership: " + e);
                            return "objectSID_ERROR";
                        }
                        ctx.close();
                    }
                }
                              
                } catch (NamingException ne) {
                ne.printStackTrace();
                System.out.println("Error: " + ne);
                return "objectSID_ERROR";
                }
                return "objectSID_ERROR";
     }
            public static String getSIDasStringOfBytes(byte[] sid) {
            String strSID = "";
            int version;
            long authority;
            int count;
            String rid = "";
            strSID = "S";
        
             // get version
            version = sid[0];
            strSID = strSID + "-" + Integer.toString(version);
            for (int i=6; i>0; i--) {
                rid += byte2hex(sid[i]);
            }
        
            // get authority
            authority = Long.parseLong(rid);
            strSID = strSID + "-" + Long.toString(authority);
    
            //next byte is the count of sub-authorities
            count = sid[7]&0xFF;
    
            //iterate all the sub-auths
            for (int i=0;i<count;i++) {
                rid = "";
                for (int j=11; j>7; j--) {
                    rid += byte2hex(sid[j+(i*4)]);
                }
                strSID = strSID + "-" + Long.parseLong(rid,16);
            }
            return strSID;   
        }
      
        public static String byte2hex(byte b) {
            String ret = Integer.toHexString((int)b&0xFF);
            if (ret.length()<2) ret = "0"+ret;
            return ret;
        }


Bye, Olivier

PS: I bet there is some cleanup to do in the code, any feedback is welcome !

Last edited by ldapmadguy (2010-08-09 21:25:33)

Offline

#5 2014-01-22 16:32:55

gorotman
Member
111 posts

gorotman said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

It works...thanks you saved me...I should be mad investigating about this....

Offline

#6 2014-01-24 10:52:58

jjzhou
Talend Team


jjzhou said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

Hi gorotman,

Maybe you need to tick "Binay" which you want to get in tLDAPInput advancedSetting.

jjzhou

Last edited by jjzhou (2014-01-24 11:01:59)

Offline

#7 2014-01-24 11:17:33

gorotman
Member
111 posts

gorotman said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

Hi jjzhou,
with your suggest now it works!

Thanks.

Offline

#8 2014-10-26 15:06:50

pfrrvgibe
Guest

pfrrvgibe said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

KGfAUH  <a href="">gerbjncaogxc</a>, cssuledokkaj, [link=]cejypflwsbci[/link],

#9 2016-09-15 21:46:50

Bharani.b
Guest

Bharani.b said:

Re: [resolved] tLdapInput : decoding the objectSID Attribute

If you are using tFileInputLDIF or tFileOutputLDIF, do the following if not done and check.
1. In Basic settings, for each of the attributes you require check the "Binary" and "Base64"
2. In Advanced Settings, make sure the Encoding format is "UTF-8"

நன்றி. முயற்சி உடையார் இகழ்ச்சி அடையார்.

Board footer

Talend Contributor Agreement - Talend Website Privacy Policy