Tuesday, September 20, 2011

LDAP/AD user password check

Simple algorithm.


  1. connect to ldap;
  2. auth with "super"-user (user1): special user with known DN and password;
  3. search another user (user2): user who must be tested, search him with some attribute (for example sAMAccountName);
  4. determine DN of user;
  5. open one more connection to ldap with just found DN and password of user2;
  6. no exception - ok, otherwise user2 has entered wrong password.
My code:

/**
 * Returns {@link Item} with addition information in case of user exists and authicated correctly, otherwise null
 * @param username username
 * @param password password
 * @return Item or null
 */
private Item checkWithLdap(String username, String password) {
    String ldap = CXConfiguration.getParameterAsString("LDAP_SERVER");
    if ((ldap != null) && !ldap.isEmpty()) {
        DirContext ctx = null;
        try {
            int port = CXConfiguration.getParameterAsInt("LDAP_SERVER");
            String ldapUrl = "ldap://" + ldap + ":" + port;
            Logger.info("checking with ldap [username: " +
                    username + ", password: ******, ldap: " +
                    ldapUrl + "]");
            Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, ldapUrl);
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(
                    Context.SECURITY_PRINCIPAL,
                    CXConfiguration.getParameterAsString("LDAP_AUTH_DN")
            );
            env.put(
                    Context.SECURITY_CREDENTIALS,
                    CXConfiguration.getParameterAsString("LDAP_AUTH_PASSWORD")
            );
            ctx = new InitialDirContext(env);
            String base = CXConfiguration.getParameterAsString("LDAP_BASE_DN");
            String[] attributeFilter = {
                    CXConfiguration.getParameterAsString("LDAP_USER_SEARCH_ATTR"),
                    "distinguishedName",
                    CXConfiguration.getParameterAsString("LDAP_EMAIL_ATTR")
            };
            SearchControls sc = new SearchControls();
            sc.setReturningAttributes(attributeFilter);
            sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String filter = "(" +
                    CXConfiguration.getParameterAsString("LDAP_USER_SEARCH_ATTR") +
                    "=" + username + ")";
            NamingEnumeration<SearchResult> results = ctx.search(base, filter, sc);
            if (results.hasMore()) {
                Properties env1 = new Properties();
                env1.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
                env1.put(Context.PROVIDER_URL, ldapUrl);
                SearchResult result = (SearchResult) results.next();
                Attributes attrs = result.getAttributes();
                Attribute dnAttr = attrs.get("distinguishedName");
                String dn = (String) dnAttr.get();
                Attribute emailAttr =
                        attrs.get(CXConfiguration.getParameterAsString("LDAP_EMAIL_ATTR"));
                String email = (emailAttr.get() != null) ? (String) emailAttr.get() : "";
                env1.put(Context.SECURITY_PRINCIPAL, dn);
                env1.put(Context.SECURITY_CREDENTIALS, password);
                new InitialDirContext(env1); // in case of problem exception will be threw
                Item i = new Item();
                i.setValue("email", email);
                Logger.info("checking with ldap - ok");
                return i;
            } else return null;
        } catch (Exception e) {
            Logger.error("checking with ldap - ldap error", e);
            return null;
        } finally {
            if (ctx != null)
                try {
                    ctx.close();
                } catch (NamingException e) {
                }
        }
    } else return null;
}

highlighted with: http://tohtml.com/

Хорошая статья "Безопастность в Java"

Хорошая статья на русском языке о безопастности в Java. В двух словах, доступно, просто и понятно. Отличная статья для старта обзора этой области.

 http://voituk.kiev.ua/2008/08/18/bezopastnost-v-java/

Tuesday, September 6, 2011

GSM 7bit (part of PDU) pack/encoding algorithm in Java

GSM 7bit (part of PDU) pack/encoding algorithm in Java. This can be used for SMS/USSD writing.


public static String stringTo7bit(String string) {
        String hex = "";
        byte[] bytes = string.getBytes();
        int f = 0;
        while (f < bytes.length - 1) {
            int t = (f % 8) + 1;
            if (t < 8) {
                byte b = (byte) (((bytes[f] >>> (t - 1)) |
                    (bytes[f + 1] << (8 - t))) & 0x000000FF);
                hex += intToHex(b & 0x000000FF).toUpperCase();
            }
            f++;
        }
        if ((f % 8) + 1 < 8)
            hex += intToHex((bytes[f] >>> (f % 8)) & 0x000000FF).toUpperCase();
        return hex;
    }
public static String intToHex(int i) {
        String hex = Integer.toHexString(i);
        if (hex.length() % 2 != 0) hex = 0 + hex;
        return hex;
    }

highlighted with: http://tohtml.com/

Tuesday, June 7, 2011

Взаимодействие между потоками в Java. Wait и notify. | Блог еще одного разработчика

Взаимодействие между потоками в Java. Wait и notify. | Блог еще одного разработчика
Отличная статья на русском языке.

К сожалению, исходная статья более не доступна по ссылке.
Привожу копию из архивов с ресурса archive-ru.com.

Исходная статья с сайта http://stremoukhov.ru.

Взаимодействие между потоками в Java. Wait и notify.

Представим ситуацию, что у нас многопотоковое приложение, написанное на Java. Есть некий класс, выполняющий какое-либо конкретное действие с данными, например, отправку их по почте, а сами данные подготавливаются в другом месте кода в другом потоке. Перед отправкой данных нам необходимо как-то связаться с потоком, подготавливающим данные, дабы поймать момент, когда они будут готовы.
Пример 1. Простой, но неправильный пример
public class DataManager {
    private static boolean ready = false;

    public void sendData() {
        while (!ready) {
            // waiting
            System.out.println("Waiting for data...");
        }

        // continue execution and sending data
        System.out.println("Sending data...");
    }

    public void prepareData() {
        System.out.println("Data prepared");
        ready = true;
    }
}
Допустим, что первый поток должен готовить данные, а второй отправлять. Из данного примера видно, что отправляющий поток будет ждать данные в цикле. Это, конечно, будет работать, особенно, если время ожидание мизерное. Но по сути, ожидая данных поток серьезно загрузит процессор, отнимая драгоценные ресурсы на подготовку данных. Правильнее будет каким-то образом приостановить второй поток, пока первый не подготовит данные.
Пример 2. Ожидание с помощью wait() и notifyAll()
public class DataManager {
    private static final Object monitor = new Object();

    public void sendData() {
        synchronized (monitor) {
            System.out.println("Waiting for data...");
            try {
                monitor.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // continue execution and sending data
            System.out.println("Sending data...");
        }
    }

    public void prepareData() {
        synchronized (monitor) {
            System.out.println("Data prepared");
            monitor.notifyAll();
        }
    }
}
Как видно из данного примера, отправляющий данные поток не циклиться, а вызывает метод wait() у нашего объекта-монитора. Напомню принцип работы синхронизации: как только первый поток попадает в блок synchronized, он становится владельцем объекта monitor и "блокирует" его. Никакой другой поток не сможет попасть в блок, т.е. стать владельцем этого объекта до тех пор, пока поток владелец не "отпустит" монитор, выйдя из блока синхронизации.
Важно! Методы wait(), notify() и notifyAll() должны обязательно находиться внутри блока synchronized, либо внутри synchronized-метода, иначе вы получите Exception. Но возникает вопрос, каким образом второй поток сможет попасть в блок синхронизации, чтобы вызвать notifyAll(), если первый в этот момент будет владельцем monitor'а и будет ждать notify() ? Все просто - как только поток достигает метода wait() он перестает быть владельцем монитора, блокировка снимается, а поток уходит в сон.
Потенциальные проблемы данного кода:
1. Возможна ситуация, когда первый поток подготовил данные раньше, чем второй начал ждать его. В этом случае notifyAll() никого не разбудит и соответственно, когда второй поток дойдет до wait(), процесс остановится навсегда.
2. Существуют в природе так называемые "ложные пробуждения", когда поток просыпается сам по себе, без всяких на то причин.
Чтобы избежать обе проблемы, усовершенствуем наш код.
Пример 3. Ожидание в цикле.
public class DataManager implements Runnable {
    private static final Object monitor = new Object();
    private static boolean ready = false;

    public void prepareData() {
        synchronized (monitor) {
            System.out.println("Data prepared");
            ready = true;
            monitor.notifyAll();
        }
    }

    public void sendData() {
        synchronized (monitor) {
            System.out.println("Waiting for data...");
            while (!ready) {
                try {
                    monitor.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // continue execution and sending data
            System.out.println("Sending data...");
        }
    }
}
Не смотря на цикл как в примере 1, здесь у нас не будет расхода ресурсов процессора, т.к. цикл повторится только в случае ложного пробуждения, или прерывания. Также, мы не попадем в цикл, а следовательно на метод wait() если данные уже готовы на момент исполнения sendData();

Thursday, April 14, 2011

an idea box

My exclusive resource is available for your on alpha-stage. Try to invent something and earn money.

http://scaleus.palettelabs.org