Results 1 to 3 of 3

Thread: How do I Authenticate with LDAP through SOAP from .NET?

  1. #1
    iastor is offline Sugar Community Member
    Join Date
    Jan 2008
    Posts
    15

    Default How do I Authenticate with LDAP through SOAP from .NET?

    Hey all,

    I've been stuck on this for the past couple of days and am so close I can taste it. Using the examples from the wiki:

    https://www.sugarcrm.com/wiki/index....P_through_SOAP

    and this thread

    http://www.sugarcrm.com/forums/showthread.php?t=28292

    I've managed to crank out the following C# code that atttempts to perform an LDAP login via the SugarCRM web services. I think that my problem is that in the php code, the mcrypt library takes a 96 bit key and that .NET will only accept a 128 bit key.

    In the C# code, I've tried the following:
    1. truncating the key (which throws a key not long enough exception)
    2. truncating and padding the key with zeros on either end
    3. using ASCII encoding on all strings instead of UTF-8 (always get the same values)
    4. changing the des.Padding mode to None and Zeros.

    Here's an example of the php code that works:

    PHP Code:
    $user_name 'user3';
     
    $user_password 'passw0rd';
     
    $app_name 'testing123';

     
    $key '123456';  // LDAP Key as entered in Sugar
     
    $key substr(md5($key),0,24);
     print 
    'ldap key = ' $key;

     
    $iv 'password';  // note that this is the word password, not the user's password or hash...

     
    $ldap_hash bin2hex(mcrypt_cbc(MCRYPT_3DES$key$user_passwordMCRYPT_ENCRYPT$iv));

     print 
    'ldap hash = ' $ldap_hash;

     
    $result $soap_client->call('login',array('user_auth'=>array('user_name'=>$user_name'password'=>$ldap_hash,'version'=>'.1'), 'application_name'=>$app_name));

     print 
    'sessionId = ' $result['id']; 
    The Output looks like:
    Code:
    ldap key = e10adc3949ba59abbe56e057
    ldap hash = 1a64c8c3791697bc
    sessionId = akfc078matu38dtm7uosj1i6q7
    The C# code looks like:
    Code:
                string username = "user3";
                string userpass = "passw0rd";
                string ldapKey = "123456";
                string iv = "password";
    
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] ldapKeyEncryptedBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(ldapKey));
                StringBuilder ldapKeyEnc = new StringBuilder();
                foreach (byte b in ldapKeyEncryptedBytes) {
                    ldapKeyEnc.Append(b.ToString("x2", System.Globalization.CultureInfo.InvariantCulture));
                }
                Console.Out.WriteLine("ldapKeyEnc = " + ldapKeyEnc.ToString());
    
                TripleDES des = new TripleDESCryptoServiceProvider();
                des.Mode = CipherMode.CBC;
                des.Key = ldapKeyEncryptedBytes;
                des.IV = Encoding.UTF8.GetBytes(iv);
                des.Padding = PaddingMode.Zeros;
                ICryptoTransform encryptor = des.CreateEncryptor();
    
                byte[] encryptedBytes = encryptor.TransformFinalBlock(
                    Encoding.UTF8.GetBytes(userpass), 
                    0, 
                    Encoding.UTF8.GetByteCount(userpass)
                    );
    
                StringBuilder userpassEnc = new StringBuilder();
                foreach (byte b in encryptedBytes) {
                    userpassEnc.Append(b.ToString("x2", System.Globalization.CultureInfo.InvariantCulture));
                }
                Console.Out.WriteLine("userpassEnc = " + userpassEnc.ToString());
    
                user_auth userAuth = new user_auth();
                userAuth.user_name = username;
                userAuth.password = userpassEnc.ToString();
    
                set_entry_result rv = ws.login(userAuth, "LDAP Example");
                if ( 0 != Int32.Parse( rv.error.number )) {
                    Console.Out.WriteLine("Error logging in: " + rv.error.name + " [" + rv.error.number + "] - " + rv.error.description);
                }
                Console.Out.WriteLine("SessionId = " + rv.id);
    And it's output is:
    Code:
    ldapKeyEnc = e10adc3949ba59abbe56e057f20f883e
    userpassEnc = 31f547c4f24ea37a
    Error logging in: Invalid Login [10] - Login attempt failed please check the username and password
    SessionId = -1
    What am I missing here? Has anyone else been able to get it to work sucessfully?

    Thank you for any help you can give!

    Joe

  2. #2
    iastor is offline Sugar Community Member
    Join Date
    Jan 2008
    Posts
    15

    Default Re: How do I Authenticate with LDAP through SOAP from .NET?

    Okay, I'll answer my own question. What looks like a 96-bit key being passed into the mcrypt_cbc() call is really the full 192-bit key. The reason this is true is because the developers are passing it in as a string value - not as a byte array. It woud probably be worthy to add this hint to the Wiki page, btw.

    So, to prevent hair loss for anyone developing .NET applications that need to perform LDAP authentication with the SugarCRM web services, here's an example that should work for you:

    Code:
                string username = "user3";
                string userpass = "passw0rd";
                string ldapKey = "123456";
                string iv = "password";
    
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] ldapKeyEncryptedBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(ldapKey));
                StringBuilder ldapKeyEnc = new StringBuilder();
                foreach (byte b in ldapKeyEncryptedBytes) {
                    ldapKeyEnc.Append(b.ToString("x2", System.Globalization.CultureInfo.InvariantCulture)  );
                }
                Console.Out.WriteLine("ldapKeyEnc = " + ldapKeyEnc.ToString());
    
                TripleDES des = new TripleDESCryptoServiceProvider();
                des.Mode = CipherMode.CBC;
                // Notice that we're using a byte array of the first
                // 24 hex characters, not the first 12 bytes.
                des.Key = Encoding.UTF8.GetBytes(ldapKeyEnc.ToString(0, 24));
                des.IV = Encoding.UTF8.GetBytes(iv);
                des.Padding = PaddingMode.Zeros;
                ICryptoTransform encryptor = des.CreateEncryptor();
    
                byte[] encryptedBytes = encryptor.TransformFinalBlock(
                    Encoding.UTF8.GetBytes(userpass), 
                    0, 
                    Encoding.UTF8.GetByteCount(userpass)
                    );
    
                StringBuilder userpassEnc = new StringBuilder();
                foreach (byte b in encryptedBytes) {
                    userpassEnc.Append(b.ToString("x2", System.Globalization.CultureInfo.InvariantCulture)  );
                }
                Console.Out.WriteLine("userpassEnc = " + userpassEnc.ToString());
    
                user_auth userAuth = new user_auth();
                userAuth.user_name = username;
                userAuth.password = userpassEnc.ToString();
    
                set_entry_result rv = ws.login(userAuth, "LDAP Example");
                if ( 0 != Int32.Parse( rv.error.number )) {
                    Console.Out.WriteLine("Error logging in: " + rv.error.name + " [" + rv.error.number + "] - " + rv.error.description);
                }
                Console.Out.WriteLine("SessionId = " + rv.id);
    Which gives the expected output:
    Code:
    ldapKeyEnc = e10adc3949ba59abbe56e057f20f883e
    userpassEnc = 1a64c8c3791697bc
    SessionId = 61vs1bh8dbdp60o3tt1vvsup97
    Enjoy!

  3. #3
    pgradwo is offline Junior Member
    Join Date
    Jun 2009
    Posts
    3

    Default Re: How do I Authenticate with LDAP through SOAP from .NET?

    Here is my solution for Java. Don't ask me why it works, it just does^^.
    Hope this helps someone.
    Code:
       /**
         * Performs a trippleDes encryption using the given password with given encryption key.
         * @param password to encrypt
         * @param encryptionKey to use
         * @return encrypted password
         */
        public static String encryptPassword(String password, String encryptionKey) {
            String strReturn = null;
            try {
                final MessageDigest md = MessageDigest.getInstance("md5");
                final byte[] digestOfPassword = md.digest(encryptionKey.getBytes("UTF-8"));
    
                final byte[] keyBytes = new byte[24];
                for (int i = 0; i < digestOfPassword.length && i < 24; i++) {
                    keyBytes[i] = digestOfPassword[i];
                }
                //create hex-string to use
                String ldapHashKeyString = binToHex(keyBytes).substring(0, 24);
                final SecretKey key = new SecretKeySpec(ldapHashKeyString.getBytes("UTF-8"), "DESede");
                final IvParameterSpec iv = new IvParameterSpec("password".getBytes("UTF-8"));
                //not DESede/CBC/PKCS5Padding
                final Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
                cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    
                byte[] pwBytes = password.getBytes("UTF-8");
                // create a multiple of 8 for password byte array
                final int steps = 8;
                int len = pwBytes.length / steps;
                final int rest = pwBytes.length % steps;
                if (0 != rest) {
                    len++;
                }
                len *= steps;
                final byte[] allPwBytes = new byte[len];
                for (int i = 0; i < len && i < pwBytes.length; i++) {
                    allPwBytes[i] = pwBytes[i];
                }
                final byte[] pwEncoded = cipher.doFinal(allPwBytes, 0, allPwBytes.length);
    
                strReturn = binToHex(pwEncoded);
            } catch (IllegalStateException e) {
    			throw new RuntimeException(e);
            } catch (GeneralSecurityException e) {
    			throw new RuntimeException(e);
            } catch (UnsupportedEncodingException e) {
    			throw new RuntimeException(e);
            }
            return strReturn;
        }
        /**
         * Converts the binary array to a hex string.
         * @param bin to convert
         * @return converted string
         */
        private static String binToHex(byte[] bin) {
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < bin.length; i++) {
                buffer.append(Integer.toString( ( bin[i] & 0xff ) + 0x100, 16).substring( 1));
            }
            return buffer.toString();
        }
    Regards,
    Peter

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. SOAP login with LDAP issue
    By derekvincent in forum Developer Help
    Replies: 3
    Last Post: 2011-01-07, 06:58 PM
  2. SugarCRM's SOAP and .NET
    By robopak in forum Developer Help
    Replies: 1
    Last Post: 2010-04-15, 12:00 PM
  3. Soap Ldap Login Problem
    By jherington in forum Help
    Replies: 10
    Last Post: 2007-12-17, 11:33 PM
  4. Sugar SOAP and MS .Net Framework errors
    By neilmcguigan in forum Developer Help
    Replies: 0
    Last Post: 2005-03-27, 11:53 PM
  5. Using SOAP Interface with .net
    By coowboy in forum Help
    Replies: 1
    Last Post: 2005-03-02, 12:07 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •