diff -rupN old/Makefile.am new/Makefile.am
--- old/Makefile.am	2013-04-02 18:34:34.000000000 +0200
+++ new/Makefile.am	2013-04-22 03:07:27.837233188 +0200
@@ -89,7 +89,8 @@ sbin_PROGRAMS = \
     sss_groupshow \
     sss_cache \
     sss_debuglevel \
-    sss_seed
+    sss_seed \
+    sss_query
 
 sssdlibexec_PROGRAMS = \
     sssd_nss \
@@ -780,6 +781,16 @@ sss_cache_LDADD = \
 sss_cache_CFLAGS = $(AM_CFLAGS)
 sss_cache_LDFLAGS = \
     $(CLIENT_LIBS)
+    
+sss_query_SOURCES = \
+    src/tools/sss_query.c \
+    $(SSSD_LCL_TOOLS_OBJ)
+sss_query_LDADD = \
+    libsss_util.la \
+    $(TOOLS_LIBS)
+sss_query_CFLAGS = $(AM_CFLAGS)
+sss_query_LDFLAGS = \
+    $(CLIENT_LIBS)
 
 sss_debuglevel_SOURCES = \
     src/tools/sss_debuglevel.c \
diff -rupN old/src/man/Makefile.am new/src/man/Makefile.am
--- old/src/man/Makefile.am	2013-04-02 18:34:34.000000000 +0200
+++ new/src/man/Makefile.am	2013-04-22 03:04:28.005021372 +0200
@@ -42,7 +42,7 @@ man_MANS = \
     sssd.8 sssd.conf.5 sssd-ldap.5 \
     sssd-krb5.5 sssd-ipa.5 sssd-simple.5 sssd-ad.5 \
     sssd_krb5_locator_plugin.8 sss_groupshow.8 \
-    pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8
+    pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8 sss_query.8
 
 if BUILD_SSH
 man_MANS += sss_ssh_authorizedkeys.1 sss_ssh_knownhostsproxy.1
diff -rupN old/src/man/sss_query.8.xml new/src/man/sss_query.8.xml
--- old/src/man/sss_query.8.xml	1970-01-01 01:00:00.000000000 +0100
+++ new/src/man/sss_query.8.xml	2013-04-25 16:38:30.080005000 +0200
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<reference>
+<title>SSSD Manual pages</title>
+<refentry>
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" />
+
+    <refmeta>
+        <refentrytitle>sss_query</refentrytitle>
+        <manvolnum>8</manvolnum>
+    </refmeta>
+
+    <refnamediv id='name'>
+        <refname>sss_query</refname>
+        <refpurpose>perform query on SSSD database</refpurpose>
+    </refnamediv>
+
+    <refsynopsisdiv id='synopsis'>
+        <cmdsynopsis>
+            <command>sss_query</command>
+            <arg choice='req'>
+                <replaceable>options</replaceable>
+            </arg>
+            <arg choice='req'>
+                <replaceable>identifier</replaceable>
+            </arg>
+            <arg choice='opt'>
+                <replaceable>set of attributes</replaceable>
+            </arg>
+        </cmdsynopsis>
+    </refsynopsisdiv>
+
+    <refsect1 id='description'>
+        <title>DESCRIPTION</title>
+        <para>
+            <command>sss_query</command> allows user to query certain object or all object of the same class from SSSD database and displays results on the output.
+        </para>
+    </refsect1>
+
+    <refsect1 id='options'>
+        <title>OPTIONS</title>
+        <variablelist remap='IP'>
+            <varlistentry>
+                <term>
+                    <option>-u</option>,<option>--user</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on user(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>
+                    <option>-g</option>,<option>--group</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on group(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-n</option>,<option>--netgroup</option>
+                </term>
+                <listitem>
+                    <para>
+                       Query on netgroup(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-s</option>,<option>--service</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on service(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-m</option>,<option>--autofsmap</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on autofs map(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-b</option>,<option>--sshhost</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on ssh host(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-r</option>,<option>--sudorule</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on sudo rule(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-d</option>,<option>--domain</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on domain(s).
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-o</option>,<option>--subdomain</option>
+                </term>
+                <listitem>
+                    <para>
+                        Query on subdomains.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/param_help.xml" />
+        </variablelist>
+    </refsect1>
+    
+    <refsect1 id='identificator'>
+        <title>IDENTIFICATOR</title>
+        <variablelist remap='IP'>
+            <varlistentry>
+                <term>
+                    <option>-N</option>,<option>--name</option>
+                    <replaceable>name</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Object name. Tool also supports FQ names.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-U</option>,<option>--uid</option>
+                    <replaceable>UID</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Object UID.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-G</option>,<option>--gid</option>
+                    <replaceable>GID</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Object GID.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-P</option>,<option>--port</option>
+                    <replaceable>port</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Service port.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-I</option>,<option>--ident</option>
+                    <replaceable>identificator=value</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Searches based on identificator (one of previous options) and value.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+            <varlistentry>
+                <term>
+                    <option>-A</option>,<option>--all</option>
+                </term>
+                <listitem>
+                    <para>
+                        Search for all objects of the same class.
+                    </para>
+                </listitem>
+            </varlistentry>
+            
+        </variablelist>
+    </refsect1>
+    
+    <refsect1 id='attr_list'>
+        <title>ATTRIBUTE_LIST</title>
+        <variablelist remap='IP'>
+            <varlistentry>
+                <term>
+                    <option>-S</option>,<option>--show</option>
+                    <replaceable>attribute_name,...</replaceable>
+                </term>
+                <listitem>
+                    <para>
+                        Defines which attributes will be printed out.
+                    </para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </refsect1>
+
+    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/seealso.xml" />
+
+</refentry>
+</reference>
diff -rupN old/src/tools/sss_query.c new/src/tools/sss_query.c
--- old/src/tools/sss_query.c	1970-01-01 01:00:00.000000000 +0100
+++ new/src/tools/sss_query.c	2013-04-29 15:43:58.398237000 +0200
@@ -0,0 +1,938 @@
+/*
+   SSSD
+
+   sss_query
+
+   Copyright (C) David Bambusek <xbambu02@stud.fit.vutbr.cz>        2013
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <talloc.h>
+#include <popt.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include "dhash.h"
+
+#include "db/sysdb.h"
+#include "db/sysdb_private.h"
+#include "tools/tools_util.h"
+#include "tools/sss_sync_ops.h"
+#include "util/util.h"
+#include "db/sysdb_services.h"
+#include "db/sysdb_autofs.h"
+#include "db/sysdb_ssh.h"
+#include "db/sysdb_sudo.h"
+
+#define SYSDB_AUTOFSC "objectclass="SYSDB_AUTOFS_MAP_OC
+#define SYSDB_SSHC "objectclass="SYSDB_SSH_HOST_OC
+#define SYSDB_SUDOC "objectclass="SYSDB_SUDO_CACHE_OC
+
+#define ALL_SHIFT 9
+
+enum sss_entry_type {
+    TYPE_NONE = 0,
+    TYPE_USER,
+    TYPE_GROUP,
+    TYPE_NETGROUP,
+    TYPE_SERVICE,
+    TYPE_AUTOFSMAP,
+    TYPE_SUDORULE,
+    TYPE_SSHHOST,
+    TYPE_SUBDOMAIN,
+    TYPE_DOMAIN,
+    TYPE_USER_ALL,
+    TYPE_GROUP_ALL,
+    TYPE_NETGROUP_ALL,
+    TYPE_SERVICE_ALL,
+    TYPE_AUTOFSMAP_ALL,
+    TYPE_SUDORULE_ALL,
+    TYPE_SSHHOST_ALL,
+    TYPE_SUBDOMAIN_ALL,
+    TYPE_DOMAIN_ALL
+};
+
+enum search_typex{
+    SEARCH_BY_ERR = 0,
+    SEARCH_BY_NAME,
+    SEARCH_BY_UID,
+    SEARCH_BY_GID,
+    SEARCH_BY_PORT,
+    SEARCH_BY_ALL
+};
+
+struct attribute_list{
+    const char *name;
+    const char *value;
+    int search_by_type;
+};
+
+struct query_tool_ctx{
+    struct confdb_ctx *confdb;
+    struct sss_domain_info *domains;
+    struct sysdb_ctx_list *sysdb_list;
+    struct sss_names_ctx *nctx;
+
+    struct attribute_list *search_by;
+    const char **user_attrib;
+    int user_attrib_num;
+};
+
+struct object_attr {
+    char *key;
+    char *value;
+};
+
+/* Setup hashed attributes */
+void setup_hash(hash_table_t *table)
+{
+
+    const char *sysdb_attrs[] = {SYSDB_NAME, SYSDB_PWD, SYSDB_SHELL,
+                                SYSDB_UIDNUM, SYSDB_GIDNUM, SYSDB_HOMEDIR,
+                                SYSDB_MEMBER, SYSDB_ORIG_NETGROUP_MEMBER,
+                                SYSDB_NETGROUP_TRIPLE, SYSDB_UUID,
+                                SYSDB_SVC_PORT, SYSDB_SVC_PROTO, SYSDB_USN,
+                                SYSDB_AUTOFS_ENTRY_KEY,
+                                SYSDB_AUTOFS_ENTRY_VALUE,
+                                SYSDB_SUDO_CACHE_AT_CN,
+                                SYSDB_SUDO_CACHE_AT_HOST,
+                                SYSDB_SUDO_CACHE_AT_COMMAND,
+                                SYSDB_SUDO_CACHE_AT_OPTION,
+                                SYSDB_SUDO_CACHE_AT_RUNASUSER,
+                                SYSDB_SUDO_CACHE_AT_RUNASGROUP,
+                                SYSDB_SUDO_CACHE_AT_NOTBEFORE,
+                                SYSDB_SUDO_CACHE_AT_ORDER,
+                                SYSDB_SSH_KNOWN_HOSTS_EXPIRE,
+                                SYSDB_SSH_PUBKEY,
+                                NULL};
+                                
+    const char *human_readable[]={"Name", "Password", "Shell", "UID number",
+                                  "GID number", "Home directory", "Member",
+                                  "Netgroup member", "Unique ID", "Service port",
+                                  "Service protocol", "USN", "Autofs entry key",
+                                  "Autofs entry value", "Name", "Host", "Command",
+                                  "Option","Run as user", "Run as group", "Not before",
+                                  "Not after", "Order", "Host expire", "Public key", NULL};
+                                  
+    const char **sysdb_attr = NULL;
+    const char **human_attr = NULL;
+    human_attr = human_readable;
+    errno_t ret = EOK;
+    
+    hash_key_t h_key;
+    hash_value_t h_value;
+    for (sysdb_attr = sysdb_attrs; *sysdb_attr; ++sysdb_attr) {
+        h_key.type = HASH_KEY_STRING;
+        h_key.str = strdup(*sysdb_attr);
+        h_value.type = HASH_VALUE_PTR;
+        h_value.ptr = strdup(*human_attr);
+        
+        if ((ret = hash_enter(table, &h_key, &h_value)) != HASH_SUCCESS) {
+            ERROR("Cannot add entry to hash table\n");
+            break;
+        }
+        ++human_attr;
+    }
+}
+
+void print_object(TALLOC_CTX *mem_ctx,
+               struct ldb_message *msg,
+               const char **user_attrs,
+               hash_table_t *att_table)
+{ 
+    const char **att_iter = NULL;
+    errno_t ret = EOK;
+    hash_key_t h_key;
+    hash_value_t h_value;
+    for (att_iter = user_attrs; *att_iter; ++att_iter){
+        char *ret_value = NULL;
+        bool valid = true;
+        h_key.type = HASH_KEY_STRING;
+        h_key.str = strdup(*att_iter);
+        if ((ret = hash_lookup(att_table, &h_key, &h_value)) != HASH_SUCCESS) {
+            valid=false;
+        }
+        
+        ret_value = talloc_strdup(mem_ctx,ldb_msg_find_attr_as_string(msg, *att_iter, NULL));
+        if (valid && ret_value) {
+            PRINT("%s(%s): \t %s\n", (char*) h_value.ptr, *att_iter, ret_value);
+        }
+    }
+    free(h_key.str);
+}
+
+void print_domain_info(struct query_tool_ctx *tctx,
+                       const char *domain,
+                       int entry_type)
+{
+    struct sss_domain_info *dinfo;
+    struct sss_domain_info *sdinfo;
+    bool found = false;
+    int domain_counter = 0;
+
+    for (dinfo = tctx->domains; dinfo; dinfo = get_next_domain(dinfo, false)) {
+        if (domain && (strcmp(domain, dinfo->name)!=0)) {
+                continue;
+        }
+        found = true;
+        
+        switch(entry_type){
+        case TYPE_DOMAIN:
+            PRINT("Domain name: %s\n", dinfo->name);
+            PRINT("Domain provider: %s\n", dinfo->provider);
+            PRINT("Domain version: %s\n", SYSDB_VERSION);
+ 
+            sdinfo = dinfo->subdomains;
+            if (sdinfo) {
+                PRINT("Domain's subdomains:\n");
+                for (sdinfo = dinfo->subdomains; sdinfo;
+                    sdinfo = get_next_domain(sdinfo, false)) {
+                    PRINT("\t - %s\n", sdinfo->name);
+                }
+            }
+        break;
+
+        case TYPE_DOMAIN_ALL:
+            PRINT("=== Domain %i === \n", domain_counter);
+            PRINT("Domain name: %s\n", dinfo->name);
+            PRINT("Domain provider: %s\n", dinfo->provider);
+            PRINT("Domain version: %s\n", SYSDB_VERSION);
+
+            sdinfo = dinfo->subdomains;
+            if (sdinfo) {
+                PRINT("Domain's subdomains:\n");
+                for (sdinfo = dinfo->subdomains; sdinfo;
+                    sdinfo = get_next_domain(sdinfo, false)) {
+                    PRINT("\t - %s\n", sdinfo->name);
+                }
+            }
+            domain_counter++;
+            break;
+
+        case TYPE_SUBDOMAIN:
+            for (sdinfo = dinfo->subdomains; sdinfo;
+                sdinfo = get_next_domain(sdinfo, false)) {
+                PRINT("=== Domain %s === Entry: %d ===\n",dinfo->name, domain_counter);
+                PRINT("Subomain name: %s\n", sdinfo->name);
+                PRINT("Submain provider: %s\n", sdinfo->provider);
+                PRINT("Subdomain version: %s\n", SYSDB_VERSION);
+                domain_counter++;
+            }
+            if(!sdinfo){
+                PRINT("=== There are no subdomains in domain %s ===\n", dinfo->name);
+            }
+            break;
+        }
+    }
+    if (!found) {
+        PRINT("=== There is no domain %s ===", domain);
+    }
+    
+}
+
+errno_t search_object(struct query_tool_ctx *tctx,
+                       hash_table_t *att_table,
+                       TALLOC_CTX *mem_ctx,
+                       int type,
+                       int search_by,
+                       const char *proto,
+                       const char *ident,
+                       const char **user_attrs,
+                       bool all,
+                       const char *domain)
+{
+    struct ldb_message *msg = NULL;
+    struct ldb_message **msgs = NULL;
+    errno_t ret = EOK;
+    bool found = false;
+    bool dom_info = false;
+    bool dom_exists = false;
+    struct ldb_result *res = NULL;
+    char *sanitized_proto = NULL;
+    struct ldb_dn *basedn;
+
+    struct sysdb_ctx *sysdb;
+    struct sss_domain_info *dinfo;
+
+    for (dinfo = tctx->domains; dinfo; dinfo = get_next_domain(dinfo, false)) {
+        if (domain && (strcmp(domain, dinfo->name)!=0)) {
+                continue;
+        }
+        dom_exists = true;
+
+        if (found){
+            break;
+        }
+        sysdb = dinfo->sysdb;
+
+        switch (search_by){
+
+            case TYPE_USER:
+                if (type == SEARCH_BY_NAME) {
+                    ret = sysdb_search_user_by_name(mem_ctx, sysdb, dinfo,
+                                                    ident, user_attrs, &msg);
+                } else if (type == SEARCH_BY_UID) {
+                    unsigned long int uid;
+                    uid = strtoul(ident,NULL,0);
+                    ret = sysdb_search_user_by_uid(mem_ctx, sysdb, dinfo, uid,
+                                                   user_attrs, &msg);
+                } else {
+                    ret = EINVAL;
+                }
+                break;
+
+            case TYPE_GROUP:
+                if (type == SEARCH_BY_NAME) {
+                ret = sysdb_search_group_by_name(mem_ctx, sysdb, dinfo, ident,
+                                                 user_attrs, &msg);
+                } else if (type == SEARCH_BY_GID) {
+                    unsigned long int gid;
+                    gid = strtoul(ident,NULL,0);
+                    ret = sysdb_search_group_by_gid(mem_ctx, sysdb, dinfo, gid,
+                                                    user_attrs, &msg);
+                } else {
+                    ret = EINVAL;
+                }
+                break;
+
+            case TYPE_NETGROUP:
+                ret = sysdb_search_netgroup_by_name(mem_ctx, sysdb, dinfo,
+                                                    ident, user_attrs, &msg);
+                break;
+
+            case TYPE_SERVICE:
+                if (proto) {
+                    ret = sss_filter_sanitize(mem_ctx, proto, &sanitized_proto);
+                    if (ret != EOK) {
+                        goto error;
+                    }
+                }
+                if (type == SEARCH_BY_NAME){
+                    ret = sysdb_getservbyname(mem_ctx, sysdb, dinfo, ident,
+                                              sanitized_proto, &res);
+                    msg = res->msgs[0];
+                } else if (type == SEARCH_BY_PORT) {
+                    unsigned long int port;
+                    port = strtoul(ident,NULL,0);
+                    ret = sysdb_getservbyport(mem_ctx, sysdb, dinfo, port,
+                                              sanitized_proto, &res);
+                    msg = res->msgs[0];
+                } else {
+                    ret = EINVAL;
+                }
+                break;
+
+            case TYPE_AUTOFSMAP:
+                if (type == SEARCH_BY_NAME){
+                    ret = sysdb_get_map_byname(mem_ctx, sysdb, dinfo, ident, &msg);
+                } else {
+                    ret = EINVAL;
+                }
+                break;
+
+            case TYPE_SUDORULE:
+                basedn = sysdb_domain_dn(sysdb, mem_ctx, dinfo);
+                if (!basedn) {
+                    ret = ENOMEM;
+                    goto error;
+                }
+
+                ret = ldb_search(sysdb->ldb, mem_ctx, &res, basedn,
+                                 LDB_SCOPE_SUBTREE, user_attrs, "(&(%s)(%s=%s))",
+                                 SYSDB_SUDOC, SYSDB_NAME, ident);
+                msg = res->msgs[0];
+                break;
+
+            case TYPE_SSHHOST:
+                if (type == SEARCH_BY_NAME){
+                    ret = sysdb_get_ssh_host(mem_ctx, sysdb, dinfo, ident,
+                                             user_attrs, &msg);
+                } else {
+                    ret = EINVAL;
+                }
+                break;
+        }
+
+        if (ret) {
+            if (ret == EINVAL){
+                ERROR("Can not search user by inserted attribute\n");
+                goto error;
+            } else {
+                continue;
+            }
+        }
+
+        if (!all && !dom_info) {
+            found = true;
+            PRINT("=== Showing requested object ===\n");
+            print_object(mem_ctx, msg, user_attrs, att_table);
+
+        } else if (!dom_info) {
+            for (int x=0; x < (res->count); x++){
+                PRINT("\n=== entry: %d === domain: %s ===\n", x, dinfo->name);
+                print_object(mem_ctx, msgs[x], user_attrs, att_table);
+            }
+        }
+    }
+
+    if (domain && !dom_exists) {
+       PRINT("=== There is no domain %s ===\n", domain);
+       goto error;
+    }
+
+    if (!found) {
+        PRINT("=== Object not found! ===\n");
+        goto error;
+    }
+error:
+    return ret;
+}
+
+errno_t search_object_all(struct query_tool_ctx *tctx,
+                       hash_table_t *att_table,
+                       TALLOC_CTX *mem_ctx,
+                       int type,
+                       int search_by,
+                       const char **user_attrs,
+                       const char *domain)
+{
+    struct ldb_message **msgs = NULL;
+    errno_t ret = EOK;
+    bool dom_exists = false;
+    struct ldb_result *res = NULL;
+    struct ldb_dn *basedn;
+    const char *sysdb_class[] = { NULL, SYSDB_UC, SYSDB_GC, SYSDB_NC,
+                                  SYSDB_SC, SYSDB_AUTOFSC, SYSDB_SUDOC,
+                                  SYSDB_SSHC, NULL };
+
+    struct sysdb_ctx *sysdb;
+    struct sss_domain_info *dinfo;
+
+    for (dinfo = tctx->domains; dinfo; dinfo = get_next_domain(dinfo, false)) {
+        if (domain && (strcmp(domain, dinfo->name)!=0)) {
+                continue;
+        }
+        dom_exists = true;
+
+        sysdb = dinfo->sysdb;
+
+        
+        basedn = sysdb_domain_dn(sysdb, mem_ctx, dinfo);
+        if (!basedn) {
+            ret = ENOMEM;
+            goto error;
+        }
+
+        ret = ldb_search(sysdb->ldb, mem_ctx, &res, basedn,
+                             LDB_SCOPE_SUBTREE, user_attrs, "%s", 
+                             sysdb_class[search_by-ALL_SHIFT]);
+        if (ret) {
+            return sysdb_error_to_errno(ret);
+            goto error;
+        }
+
+        msgs = talloc_steal(mem_ctx, res->msgs);
+    
+
+        switch (search_by){
+
+            case TYPE_USER_ALL:
+                if ((res->count)>0) {
+                    PRINT("=== Showing all users in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No user in domain %s ! === \n", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_GROUP_ALL:
+                if((res->count)>0) {
+                    PRINT("=== Showing all groups in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No group in domain %s ! ===\n", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_NETGROUP_ALL:
+                msgs = talloc_steal(mem_ctx, res->msgs);
+
+                if ((res->count)>0) {
+                    PRINT("=== Showing all netgroups in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No netgroup in domain %s ! ===\n", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_SERVICE_ALL:
+                if ((res->count)>0) {
+                    PRINT("=== Showing all services in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No service in domain %s! ===\n", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_AUTOFSMAP_ALL:
+                if ((res->count)>0) {
+                    PRINT("=== Showing all autofs maps in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No autofs map in domain %s!\n ===", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_SUDORULE_ALL:
+                if((res->count)>0){
+                    PRINT("=== Showing all sudo rules in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No sudo rule in domain %s ! ===\n", dinfo->name);
+                    continue;
+                }
+                break;
+
+            case TYPE_SSHHOST_ALL:
+                if ((res->count)>0) {
+                    PRINT("=== Showing all ssh hosts in domain %s ===\n", dinfo->name);
+                } else {
+                    PRINT("=== No ssh hosts in domain %s ! ===\n", dinfo->name);
+                }
+                break; 
+        }
+
+      
+
+        for (int x=0; x < (res->count); x++){
+            PRINT("\n=== entry: %d === domain: %s ===\n", x, dinfo->name);
+            print_object(mem_ctx, msgs[x], user_attrs, att_table);
+        }
+        
+    }
+
+    if (domain && !dom_exists) {
+       PRINT("=== There is no domain \"%s\"! ===\n", domain);
+       goto error;
+    }
+
+error:
+    return ret;
+}
+
+
+void delete_callback(hash_entry_t *entry, hash_destroy_enum type, void *pvt)
+{
+    if (entry->value.type == HASH_VALUE_PTR) free(entry->value.ptr);
+}
+
+errno_t parse_attributes(char * restrict list,
+                         char * restrict show,
+                         struct query_tool_ctx **tctx,
+                         int search_by)
+{
+    errno_t ret = EOK;
+    struct query_tool_ctx *ctx;
+
+    ctx = talloc(NULL, struct query_tool_ctx);
+    ctx->search_by = talloc(ctx, struct attribute_list);
+    ctx->user_attrib = talloc_array(ctx,const char*,100);
+
+    struct attribute_list *parsed;
+    char *buffer;
+    if (list != NULL) {
+        buffer = strtok(list,"=");
+
+        parsed = talloc(ctx, struct attribute_list);
+        parsed->name = talloc_strdup(parsed, buffer);
+        buffer = strtok(NULL,",=");
+        if (buffer == NULL){
+            ERROR("Please insert valid pair of attributes: name=value\n");
+            ret = EINVAL;
+            goto error;
+        }
+        parsed->value = talloc_strdup(parsed, buffer);
+
+        ctx->search_by = parsed;
+    }
+
+    if (show != NULL) {
+        buffer = strtok(show,",");
+
+        int counter = 0;
+        while (buffer != NULL){
+        if (counter >= 7) {
+            ERROR("Too many attributes to show\n");
+            ret = E2BIG;
+            goto error;
+        }
+        ctx->user_attrib[counter] = talloc_strdup(ctx, buffer);
+        buffer = strtok(NULL,",");
+        counter++;
+        }
+        ctx->user_attrib_num = counter;
+    }
+
+
+    if (search_by==SEARCH_BY_ERR) {
+        if (strcmp(ctx->search_by->name, SYSDB_NAME) == 0) {
+            ctx->search_by->search_by_type = SEARCH_BY_NAME;
+        } else if (strcmp(ctx->search_by->name, SYSDB_UIDNUM) == 0) {
+            ctx->search_by->search_by_type = SEARCH_BY_UID;
+        } else if (strcmp(ctx->search_by->name, SYSDB_GIDNUM) == 0) {
+            ctx->search_by->search_by_type = SEARCH_BY_GID;
+        } else if (strcmp(ctx->search_by->name, SYSDB_SVC_PORT) == 0){
+            ctx->search_by->search_by_type = SEARCH_BY_PORT;
+        }else {
+            ERROR("Invalid identification type\n");
+            ret = EINVAL;
+            goto error;
+        }
+    } else {
+        ctx->search_by->search_by_type = search_by;
+    }
+
+error:
+    if (ret != EOK){
+        talloc_free(ctx);
+    } else {
+        *tctx=ctx;
+    }
+
+    return ret;
+}
+
+errno_t init_domains(struct query_tool_ctx *ctx)
+{
+    char *confdb_path;
+    int ret;
+
+    confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
+    if (confdb_path == NULL) {
+        return ENOMEM;
+    }
+
+    /* Connect to the conf db */
+    ret = confdb_init(ctx, &ctx->confdb, confdb_path);
+    talloc_free(confdb_path);
+    if (ret != EOK) {
+        DEBUG(1, ("Could not initialize connection to the confdb\n"));
+        return ret;
+    }
+
+    ret = confdb_get_domains(ctx->confdb, &ctx->domains);
+    if (ret != EOK) {
+        DEBUG(1, ("Could not initialize domains\n"));
+        return ret;
+    }
+
+    ret = sysdb_init(ctx, ctx->domains, false);
+    SYSDB_VERSION_ERROR(ret);
+    if (ret != EOK) {
+        DEBUG(1, ("Could not initialize connection to the sysdb\n"));
+        return ret;
+    }
+
+    return EOK;
+}
+
+
+int main (int argc, const char *argv[])
+{
+    const char *USER_SHOW_ATTRS[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM, SYSDB_HOMEDIR, SYSDB_SHELL,  NULL };
+    const char *GROUP_SHOW_ATTRS[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
+    const char *NETGROUP_SHOW_ATTRS[] = { SYSDB_NAME, SYSDB_UUID, NULL };
+    const char *SERVICE_SHOW_ATTRS[] = { SYSDB_NAME, SYSDB_USN, SYSDB_SVC_PORT, SYSDB_SVC_PROTO, NULL };
+    const char *AUTOFSM_SHOW_ATTRS[] = { SYSDB_AUTOFS_ENTRY_KEY, SYSDB_AUTOFS_ENTRY_VALUE, NULL};
+    const char *SUDO_SHOW_ATTRS[] = { SYSDB_SUDO_CACHE_AT_CN, SYSDB_SUDO_CACHE_AT_USER, SYSDB_SUDO_CACHE_AT_HOST, SYSDB_SUDO_CACHE_AT_OPTION, NULL };
+    const char *SSHHOST_SHOW_ATTRS[] = { SYSDB_NAME, SYSDB_SSH_KNOWN_HOSTS_EXPIRE, SYSDB_SSH_PUBKEY, NULL};
+
+    //check if user is root
+    uid_t user_uid;
+    errno_t ret = EOK;
+    user_uid = getuid();
+    if(user_uid != 0){
+        ERROR("You must be root in order to run this tool!\n");
+        return ret;
+    }
+    
+    struct query_tool_ctx *tctx = NULL;
+    tctx = talloc(NULL, struct query_tool_ctx);
+    tctx->search_by = talloc(tctx, struct attribute_list);
+    
+    static hash_table_t *hashed_attrs = NULL;
+    ret = sss_hash_create(tctx, 10, &hashed_attrs);
+
+    int entry_type=TYPE_NONE;
+    bool all = false;
+    const char *name = NULL;
+    const char *uid = NULL;
+    const char *gid = NULL;
+    const char *port = NULL;
+    const char *protocol = NULL;
+    const char *domain = NULL;
+    char * search_by = NULL;
+    char * show = NULL;
+    const char *search = NULL;
+    poptContext pc = NULL;
+    struct poptOption po[]={
+        POPT_AUTOHELP
+        { "user", 'u', POPT_ARG_NONE, NULL, 'u', _("Search for user"), NULL },
+        { "group", 'g', POPT_ARG_NONE, NULL, 'g', _("Search for group"), NULL },
+        { "netgroup", 'n', POPT_ARG_NONE, NULL, 'n', _("Searche for netgroup"), NULL },
+        { "service", 's', POPT_ARG_NONE, NULL, 's', _("Search for service"), NULL },
+        { "sshhost", 'b', POPT_ARG_NONE, NULL, 'b', _("Search for ssh hosts"), NULL },
+        { "sudorule", 'r', POPT_ARG_NONE, NULL, 'r', _("Search for sudorules"), NULL },
+        { "autofsmap", 'm', POPT_ARG_NONE, NULL, 'm', _("Search for autofsmap"), NULL },
+        { "domain", 'd', POPT_ARG_NONE, NULL, 'd', _("Search for domain"), NULL },
+        { "subdomain", 'o', POPT_ARG_NONE, NULL, 'o', _("Search for subdomain"), NULL },
+        { "ident", 'I', POPT_ARG_STRING, &search_by, 'I', _("Attributes to be searched"), NULL },
+        { "show", 'S', POPT_ARG_STRING, &show, 'S', _("Attributes to be printed"), NULL },
+        { "name", 'N', POPT_ARG_STRING, &name, 'N', _("Name of searched object"), NULL },
+        { "uid", 'U', POPT_ARG_STRING, &uid, 'U', _("UID of searched object"), NULL },
+        { "gid", 'G', POPT_ARG_STRING, &gid, 'G', _("GID of searched object"), NULL },
+        { "port", 'P', POPT_ARG_STRING, &port, 'P', _("Service port"), NULL },
+        { "all", 'A', POPT_ARG_NONE, NULL, 'A', _("Select all objects"), NULL },
+        POPT_TABLEEND
+    };
+
+    ret = set_locale();
+    if (ret != EOK) {
+        DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret)));
+        ERROR("Error setting the locale\n");
+        ret = EXIT_FAILURE;
+        goto error;
+    }
+
+    int entry_count = 0;
+    int ident_count = 0;
+    pc = poptGetContext(NULL, argc, (const char **)argv, po, 0);
+    while ((ret = poptGetNextOpt(pc)) > 0) {
+        switch(ret) {
+        case 'u':
+            entry_type = TYPE_USER;
+            entry_count++;
+            break;
+        case 'g':
+            entry_type = TYPE_GROUP;
+            entry_count++;
+            break;
+        case 'n':
+            entry_type = TYPE_NETGROUP;
+            entry_count++;
+            break;
+        case 's':
+            entry_type = TYPE_SERVICE;
+            entry_count++;
+            break;
+        case 'm':
+            entry_type = TYPE_AUTOFSMAP;
+            entry_count++;
+            break;
+        case 'b':
+            entry_type = TYPE_SSHHOST;
+            entry_count++;
+            break;
+        case 'r':
+            entry_type = TYPE_SUDORULE;
+            entry_count++;
+            break;
+        case 'd':
+            entry_type = TYPE_DOMAIN;
+            entry_count++;
+            break;
+        case 'o':
+            entry_type = TYPE_SUBDOMAIN;
+            entry_count++;
+            break;
+        case 'I':
+            ident_count++;
+            break;
+        case 'N':
+            tctx->search_by->search_by_type = SEARCH_BY_NAME;
+            search = name;
+            ident_count++;
+            break;
+        case 'U':
+            tctx->search_by->search_by_type = SEARCH_BY_UID;
+            search = uid;
+            ident_count++;
+            break;
+        case 'G':
+            tctx->search_by->search_by_type = SEARCH_BY_GID;
+            search = gid;
+            ident_count++;
+            break;
+        case 'P':
+            tctx->search_by->search_by_type = SEARCH_BY_PORT;
+            search = port;
+            ident_count++;
+            break;
+        case 'A':
+            tctx->search_by->search_by_type = SEARCH_BY_ALL;
+            all = true;
+            break;
+        }
+    }
+    
+    ret = EOK;
+
+    if ((search_by != NULL) || (show != NULL)) {
+        ret = parse_attributes(search_by, show, &tctx, tctx->search_by->search_by_type);
+        if (ret != EOK) {
+            goto error;
+        }
+    }
+    
+    if (all && (name!=NULL || search_by!=NULL)) {
+        ERROR("Please chose to search either for one object or for all, not both\n");
+        goto error;
+    }
+    if (entry_count != 1){
+        ERROR("Please chose one type of object\n");
+        goto error;
+    }
+    if (ident_count != 1){
+        ERROR("Please use one type of identification\n");
+        goto error;
+    }
+
+    if (!all && (entry_type != TYPE_SUBDOMAIN)) {
+        if (name == NULL && uid==NULL && gid==NULL && port==NULL && search_by==NULL) {
+            ERROR("Please enter identification of object you want to find\n");
+            goto error;
+        }
+
+        if ((name != NULL || uid!=NULL || gid!=NULL || port!=NULL) && search_by!=NULL) {
+            ERROR("Please chose just -N/-U/...(--name/--uid/...) or -I(--ident) option\n");
+            goto error;
+        }
+    }
+
+    int object_type = tctx->search_by->search_by_type;
+    switch (object_type) {
+    case SEARCH_BY_GID:
+        if (entry_type!=TYPE_GROUP) {
+            ERROR("You can use GID just for identifying groups!\n");
+            goto error;
+        }
+        break;
+    case SEARCH_BY_UID:
+        if (entry_type!=TYPE_USER) {
+            ERROR("You can use UID just for identifying users!\n");
+            goto error;
+        }
+        break;
+    case SEARCH_BY_PORT:
+        if (entry_type!=TYPE_SERVICE) {
+            ERROR("You can use port number just for identifying services!\n");
+            goto error;
+        }
+        break;
+    }
+
+    if (search == NULL) {
+        search = tctx->search_by->value;
+    }
+
+    ret = init_domains(tctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Initialization of sysdb connections failed\n"));
+        goto error;
+    }
+
+    if (tctx->search_by->search_by_type == SEARCH_BY_NAME) {
+        char *parsed_domain = NULL;
+        char *parsed_name = NULL;
+
+        ret = sss_names_init(tctx, tctx->confdb, tctx->domains->name, &tctx->nctx);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("sss_names_init() failed\n"));
+            return ret;
+        }
+
+        ret = sss_parse_name(tctx, tctx->nctx, search,
+                                 &parsed_domain, &parsed_name);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("sss_parse_name failed\n"));
+            goto error;
+        }
+        search = parsed_name;
+        domain = parsed_domain;
+
+    }
+
+    if (all) {
+        entry_type += ALL_SHIFT;
+    }
+    const char **attribs = NULL;
+    if (entry_type == TYPE_SUBDOMAIN_ALL) {
+        entry_type -= ALL_SHIFT;
+    }
+
+    if (show == NULL) {
+        int tmp_entry_type;
+        tmp_entry_type = entry_type;
+        if (tmp_entry_type > ALL_SHIFT) {
+            tmp_entry_type -= ALL_SHIFT;
+        }
+
+        switch (tmp_entry_type) {
+            case TYPE_USER:
+                    attribs = USER_SHOW_ATTRS;
+                    break;
+            case TYPE_GROUP:
+                    attribs = GROUP_SHOW_ATTRS;
+                    break;
+            case TYPE_NETGROUP:
+                    attribs = NETGROUP_SHOW_ATTRS;
+                    break;
+            case TYPE_SERVICE:
+                    attribs = SERVICE_SHOW_ATTRS;
+                    break;
+            case TYPE_AUTOFSMAP:
+                    attribs = AUTOFSM_SHOW_ATTRS;
+                    break;
+            case TYPE_SSHHOST:
+                    attribs = SSHHOST_SHOW_ATTRS;
+                    break;
+            case TYPE_SUDORULE:
+                    attribs = SUDO_SHOW_ATTRS;
+                    break;
+        }
+    } else {
+        attribs = tctx->user_attrib;
+    }
+
+    setup_hash(hashed_attrs);
+    
+    if ( (entry_type == TYPE_DOMAIN) || (entry_type == TYPE_DOMAIN_ALL) || (entry_type == TYPE_SUBDOMAIN)) {
+        print_domain_info(tctx, search, entry_type);   
+    } else if (!all) {
+        search_object(tctx, hashed_attrs, tctx, object_type, entry_type, protocol,
+                      search, attribs, all, domain);
+    } else {
+        search_object_all(tctx, hashed_attrs, tctx, object_type, entry_type, attribs, domain);
+    }
+                          
+                          
+error:
+    talloc_free(tctx);
+    poptFreeContext(pc);
+    return ret;
+}
