From 4ddda868b793714c3cb9760b276ce753869dee46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Tue, 26 Jul 2011 14:32:41 +0200
Subject: [PATCH 1/2] New DEBUG facility.

https://fedorahosted.org/sssd/ticket/925

There are several new macros in util/util.h:

- SSSDBG_* to reflect a debug level (same names as in the ticket) - please,
  don't use magic numbers anymore

- DEBUG_MSG(level, function, message) which will format the debug message
  like "(time) [prg_name] [function] (level): message\n"

- DEBUG_IS_SET(level) that you should use to check if the level is allowed
  to be logged
  You can use it like: if (DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {...}
---
 Makefile.am                         |   11 +
 src/man/include/debug_levels.xml    |   60 +++
 src/man/sssd.8.xml                  |    8 +-
 src/man/sssd.conf.5.xml             |   11 +-
 src/monitor/monitor.c               |    5 +-
 src/monitor/monitor_sbus.c          |    1 +
 src/providers/child_common.c        |    2 +-
 src/providers/data_provider.h       |    2 +-
 src/providers/data_provider_be.c    |    2 +
 src/providers/data_provider_fo.c    |    8 +-
 src/providers/krb5/krb5_child.c     |    2 +
 src/providers/ldap/ldap_child.c     |    2 +
 src/providers/ldap/sdap_async.c     |    4 +-
 src/providers/ldap/sdap_fd_events.c |    4 +-
 src/providers/proxy/proxy_auth.c    |    2 +-
 src/providers/proxy/proxy_child.c   |    1 +
 src/providers/proxy/proxy_id.c      |    2 +-
 src/responder/nss/nsssrv.c          |    2 +
 src/responder/pam/pamsrv.c          |    2 +
 src/sbus/sssd_dbus_common.c         |    4 +-
 src/tests/auth-tests.c              |    2 +
 src/tests/crypto-tests.c            |    2 +-
 src/tests/debug-tests.c             |  711 +++++++++++++++++++++++++++++++++++
 src/tests/fail_over-tests.c         |    2 +-
 src/tests/files-tests.c             |    2 +-
 src/tests/find_uid-tests.c          |    2 +-
 src/tests/krb5_utils-tests.c        |    1 +
 src/tests/refcount-tests.c          |    2 +-
 src/tests/resolv-tests.c            |    2 +-
 src/tests/simple_access-tests.c     |    1 +
 src/tests/strtonum-tests.c          |    2 +
 src/tests/sysdb-tests.c             |    2 +
 src/tests/util-tests.c              |    2 +
 src/tools/selinux.c                 |   14 +-
 src/tools/sss_cache.c               |    2 +-
 src/tools/sss_groupadd.c            |    2 +-
 src/tools/sss_groupdel.c            |    2 +-
 src/tools/sss_groupmod.c            |    2 +-
 src/tools/sss_groupshow.c           |    2 +-
 src/tools/sss_useradd.c             |    2 +-
 src/tools/sss_userdel.c             |    2 +-
 src/tools/sss_usermod.c             |    2 +-
 src/util/debug.c                    |   95 ++++-
 src/util/server.c                   |    2 +
 src/util/util.h                     |   68 +++-
 45 files changed, 977 insertions(+), 86 deletions(-)
 create mode 100644 src/man/include/debug_levels.xml
 create mode 100644 src/tests/debug-tests.c

diff --git a/Makefile.am b/Makefile.am
index 1df6d98..9d9de4f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -84,6 +84,7 @@ if HAVE_CHECK
         simple_access-tests \
         crypto-tests \
         util-tests \
+        debug-tests \
         ipa_hbac-tests
 endif
 
@@ -715,6 +716,16 @@ util_tests_LDADD = \
     $(CHECK_LIBS) \
     libsss_util.la \
     libsss_test_common.la
+    
+debug_tests_SOURCES = \
+    src/tests/debug-tests.c
+debug_tests_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(CHECK_CFLAGS)
+debug_tests_LDADD = \
+    $(SSSD_LIBS) \
+    $(CHECK_LIBS) \
+    libsss_util.la
 
 crypto_tests_SOURCES = \
     $(SSS_CRYPT_SOURCES) \
diff --git a/src/man/include/debug_levels.xml b/src/man/include/debug_levels.xml
new file mode 100644
index 0000000..6af3d66
--- /dev/null
+++ b/src/man/include/debug_levels.xml
@@ -0,0 +1,60 @@
+<listitem>
+    <para>
+        Bit mask that indicates which debug levels will be visible. 0x0010 is the default value as well
+        as the lowest allowed value, 0xFFF0 is the most verbose mode. This setting
+        overrides the settings from config file.
+    </para>
+    <para>
+        Currently supported debug levels:
+    </para>
+    <para>
+         <emphasis>0x0010</emphasis>: 
+         Fatal failures. Anything that would prevent SSSD from starting up or causes it to cease running.
+    </para>
+    <para>
+         <emphasis>0x0020</emphasis>:
+         Critical failures. An error that doesn't kill the SSSD, but one that indicates
+         that at least one major feature is not going to work properly.
+    </para>
+    <para>
+         <emphasis>0x0040</emphasis>: Serious failures. An error announcing that a particular request or
+         operation has failed.
+    </para>
+    <para>
+         <emphasis>0x0080</emphasis>: Minor failures. These are the errors that would percolate down to
+         cause the operation failure of 2.
+    </para>
+    <para>
+         <emphasis>0x0100</emphasis>: Configuration settings.
+    </para>
+    <para>
+         <emphasis>0x0200</emphasis>: Function data.
+    </para>
+    <para>
+         <emphasis>0x0400</emphasis>: Trace messages for operation functions.
+    </para>
+    <para>
+         <emphasis>0x1000</emphasis>: Trace messages for internal control functions.
+    </para>
+    <para>
+         <emphasis>0x2000</emphasis>: Contents of function-internal variables that may be interesting.
+    </para>
+    <para>
+         <emphasis>0x4000</emphasis>: Extremely low-level tracing information.
+    </para>
+    <para>
+        To log required debug levels, simply add their numbers together as shown in following examples:
+    </para>
+    <para>
+        <emphasis>Example</emphasis>: To log fatal failures, critical failures,
+        serious failures and function data use 0x0270.
+    </para>
+    <para>
+        <emphasis>Example</emphasis>: To log fatal failures, configuration settings, function data,
+        trace messages for internal control functions use 0x1310.
+    </para>
+    <para>
+        <emphasis>Note</emphasis>: This is new format of debug levels introduced in 1.7.0.
+        Older format (numbers from 0-10) is compatible but deprecated.
+    </para>
+</listitem>
\ No newline at end of file
diff --git a/src/man/sssd.8.xml b/src/man/sssd.8.xml
index 1856719..e4d972c 100644
--- a/src/man/sssd.8.xml
+++ b/src/man/sssd.8.xml
@@ -46,13 +46,7 @@
                     <option>-d</option>,<option>--debug-level</option>
                     <replaceable>LEVEL</replaceable>
                 </term>
-                <listitem>
-                    <para>
-                        Debug level to run the daemon with. 0 is the default as well
-                        as the lowest allowed value, 10 is the most verbose mode. This setting
-                        overrides the settings from config file. This parameter implies <option>-i</option>.
-                    </para>
-                </listitem>
+                <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/debug_levels.xml" />
             </varlistentry>
             <varlistentry>
                 <term>
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index e038055..6f85dda 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -208,16 +208,7 @@
             <variablelist>
                 <varlistentry>
                     <term>debug_level (integer)</term>
-                    <listitem>
-                        <para>
-                            Sets the debug level for the service. The
-                            value can be in range from 0 (only critical
-                            messages) to 10 (very verbose).
-                        </para>
-                        <para>
-                            Default: 0
-                        </para>
-                    </listitem>
+                    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/debug_levels.xml" />
                 </varlistentry>
                 <varlistentry>
                     <term>debug_timestamps (bool)</term>
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 8326f38..ae429f8 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -956,7 +956,7 @@ static int get_service_config(struct mt_ctx *ctx, const char *name,
              * make sure to pass it into the children, overriding the
              * config file.
              */
-            svc->command = talloc_asprintf(svc, "%s/sssd_%s -d %d%s%s",
+            svc->command = talloc_asprintf(svc, "%s/sssd_%s -d 0x%.4x%s%s",
                                            SSSD_LIBEXEC_PATH,
                                            svc->name,
                                            cmdline_debug_level,
@@ -1099,7 +1099,7 @@ static int get_provider_config(struct mt_ctx *ctx, const char *name,
                                 debug_to_file ? " --debug-to-files" : "");
         } else {
             svc->command = talloc_asprintf(svc,
-                                "%s/sssd_be --domain %s -d %d%s%s ",
+                                "%s/sssd_be --domain %s -d 0x%.4x%s%s ",
                                 SSSD_LIBEXEC_PATH,
                                 svc->name,
                                 cmdline_debug_level,
@@ -2331,6 +2331,7 @@ int main(int argc, const char *argv[])
             return 1;
         }
     }
+    debug_level = debug_convert_old_level(debug_level);
 
     /* If the level was passed at the command-line, we want
      * to save it and pass it to the children later.
diff --git a/src/monitor/monitor_sbus.c b/src/monitor/monitor_sbus.c
index 632de49..9e20671 100644
--- a/src/monitor/monitor_sbus.c
+++ b/src/monitor/monitor_sbus.c
@@ -205,6 +205,7 @@ errno_t monitor_common_rotate_logs(struct confdb_ctx *confdb,
 
     if (debug_level != old_debug_level) {
         DEBUG(0, ("Debug level changed to %d\n", debug_level));
+        debug_level = debug_convert_old_level(debug_level);
     }
 
     return EOK;
diff --git a/src/providers/child_common.c b/src/providers/child_common.c
index 16618c7..74cfee6 100644
--- a/src/providers/child_common.c
+++ b/src/providers/child_common.c
@@ -400,7 +400,7 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
 
     argv[--argc] = NULL;
 
-    argv[--argc] = talloc_asprintf(argv, "--debug-level=%d",
+    argv[--argc] = talloc_asprintf(argv, "--debug-level=0x%.4x",
                               debug_level);
     if (argv[argc] == NULL) {
         ret = ENOMEM;
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index e699e08..e75cd22 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -140,7 +140,7 @@
 /* AUTH related common data and functions */
 
 #define DEBUG_PAM_DATA(level, pd) do { \
-    if (level <= debug_level) pam_print_data(level, pd); \
+    if (DEBUG_IS_SET(level)) pam_print_data(level, pd); \
 } while(0);
 
 
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 380e6cd..7df82f4 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -1216,6 +1216,8 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
 
     /* set up things like debug , signals, daemonization, etc... */
     debug_log_file = talloc_asprintf(NULL, "sssd_%s", be_domain);
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index b5c4173..0b991a9 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -432,7 +432,7 @@ static void be_resolve_server_done(struct tevent_req *subreq)
 
     /* all fine we got the server */
 
-    if (debug_level >= 4 && fo_get_server_name(state->srv)) {
+    if (DEBUG_IS_SET(SSSDBG_CONF_SETTINGS) && fo_get_server_name(state->srv)) {
         struct resolv_hostent *srvaddr;
         char ipaddr[128];
         srvaddr = fo_get_server_hostent(state->srv);
@@ -446,9 +446,9 @@ static void be_resolve_server_done(struct tevent_req *subreq)
         inet_ntop(srvaddr->family, srvaddr->addr_list[0]->ipaddr,
                   ipaddr, 128);
 
-        DEBUG(4, ("Found address for server %s: [%s] TTL %d\n",
-                  fo_get_server_str_name(state->srv), ipaddr,
-                  srvaddr->addr_list[0]->ttl));
+        DEBUG(SSSDBG_CONF_SETTINGS, ("Found address for server %s: [%s] TTL %d\n",
+                fo_get_server_str_name(state->srv), ipaddr,
+                srvaddr->addr_list[0]->ttl));
     }
 
     srv_status_change = fo_get_server_hostname_last_change(state->srv);
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index ffc6c79..48442de 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -1573,6 +1573,8 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     DEBUG(7, ("krb5_child started.\n"));
 
     pd = talloc_zero(NULL, struct pam_data);
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index fb8dd80..8a1dc49 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -378,6 +378,8 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     DEBUG(7, ("ldap_child started.\n"));
 
     main_ctx = talloc_new(NULL);
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 5594dd5..1fa4fa3 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -981,12 +981,12 @@ static errno_t sdap_get_generic_ext_step(struct tevent_req *req)
 
     DEBUG(6, ("calling ldap_search_ext with [%s][%s].\n", state->filter,
                                                           state->search_base));
-    if (debug_level >= 7) {
+    if (DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {
         int i;
 
         if (state->attrs) {
             for (i = 0; state->attrs[i]; i++) {
-                DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i]));
+                DEBUG(SSSDBG_TRACE_LIBS, ("Requesting attrs: [%s]\n", state->attrs[i]));
             }
         }
     }
diff --git a/src/providers/ldap/sdap_fd_events.c b/src/providers/ldap/sdap_fd_events.c
index 4fb67b8..0a51622 100644
--- a/src/providers/ldap/sdap_fd_events.c
+++ b/src/providers/ldap/sdap_fd_events.c
@@ -104,9 +104,9 @@ static int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb,
         return EINVAL;
     }
 
-    if (debug_level >= 7) {
+    if (DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {
         char *uri = ldap_url_desc2str(srv);
-        DEBUG(7, ("New LDAP connection to [%s] with fd [%d].\n",
+        DEBUG(SSSDBG_TRACE_LIBS, ("New LDAP connection to [%s] with fd [%d].\n",
                   uri, ber_fd));
         free(uri);
     }
diff --git a/src/providers/proxy/proxy_auth.c b/src/providers/proxy/proxy_auth.c
index b3b878c..25e781b 100644
--- a/src/providers/proxy/proxy_auth.c
+++ b/src/providers/proxy/proxy_auth.c
@@ -240,7 +240,7 @@ static struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
     state->child_ctx = child_ctx;
 
     state->command = talloc_asprintf(req,
-            "%s/proxy_child -d %d%s%s --domain %s --id %d",
+            "%s/proxy_child -d 0x%.4x%s%s --domain %s --id %d",
             SSSD_LIBEXEC_PATH, debug_level,
             (debug_timestamps ? "" : " --debug-timestamps=0"),
             (debug_to_file ? " --debug-to-files" : ""),
diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
index 0f58849..d19cc74 100644
--- a/src/providers/proxy/proxy_child.c
+++ b/src/providers/proxy/proxy_child.c
@@ -507,6 +507,7 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
 
     /* set up things like debug , signals, daemonization, etc... */
     debug_log_file = talloc_asprintf(NULL, "proxy_child_%s", domain);
diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index 5ce9095..ec13c93 100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -395,7 +395,7 @@ done:
 
 #define DEBUG_GR_MEM(level, grp) \
     do { \
-        if (debug_level >= level) { \
+        if (DEBUG_IS_SET(level)) { \
             if (!grp->gr_mem || !grp->gr_mem[0]) { \
                 DEBUG(level, ("Group %s has no members!\n", \
                               grp->gr_name)); \
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index ec2f0ca..9fa0cd5 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -358,6 +358,8 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
    /* set up things like debug, signals, daemonization, etc... */
     debug_log_file = "sssd_nss";
 
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index 86283ea..2308288 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -209,6 +209,8 @@ int main(int argc, const char *argv[])
 
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     /* set up things like debug, signals, daemonization, etc... */
     debug_log_file = "sssd_pam";
 
diff --git a/src/sbus/sssd_dbus_common.c b/src/sbus/sssd_dbus_common.c
index d446632..502bd29 100644
--- a/src/sbus/sssd_dbus_common.c
+++ b/src/sbus/sssd_dbus_common.c
@@ -226,14 +226,14 @@ void sbus_toggle_watch(DBusWatch *dbus_watch, void *data)
         }
     }
 
-    if (debug_level >= 8) {
+    if (DEBUG_IS_SET(SSSDBG_TRACE_INTERNAL)) {
 #ifdef HAVE_DBUS_WATCH_GET_UNIX_FD
         fd = dbus_watch_get_unix_fd(dbus_watch);
 #else
         fd = dbus_watch_get_fd(dbus_watch);
 #endif
     }
-    DEBUG(8, ("%p/%p (%d), %s/%s (%s)\n",
+    DEBUG(SSSDBG_TRACE_INTERNAL, ("%p/%p (%d), %s/%s (%s)\n",
               watch, dbus_watch, fd,
               ((flags & DBUS_WATCH_READABLE)?"R":"-"),
               ((flags & DBUS_WATCH_WRITABLE)?"W":"-"),
diff --git a/src/tests/auth-tests.c b/src/tests/auth-tests.c
index abdc874..54d5b29 100644
--- a/src/tests/auth-tests.c
+++ b/src/tests/auth-tests.c
@@ -320,6 +320,8 @@ int main(int argc, const char *argv[])
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     tests_set_cwd();
 
     ret = clean_db_dir();
diff --git a/src/tests/crypto-tests.c b/src/tests/crypto-tests.c
index 286bc23..0f6f2fe 100644
--- a/src/tests/crypto-tests.c
+++ b/src/tests/crypto-tests.c
@@ -135,7 +135,7 @@ int main(int argc, const char *argv[])
     }
     poptFreeContext(pc);
 
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
     tests_set_cwd();
 
     Suite *s = crypto_suite();
diff --git a/src/tests/debug-tests.c b/src/tests/debug-tests.c
new file mode 100644
index 0000000..38e6add
--- /dev/null
+++ b/src/tests/debug-tests.c
@@ -0,0 +1,711 @@
+/*
+    SSSD
+
+    debug-tests.c
+
+    Authors:
+        Pavel Březina <pbrezina@redhat.com>
+
+    Copyright (C) 2011 Red Hat
+
+    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 <check.h>
+#include <stdio.h>
+#include <talloc.h>
+#include <errno.h>
+#include <string.h>
+#include "util/util.h"
+
+#define DEBUG_TEST_NOK      -1
+#define DEBUG_TEST_NOK_TS   -2
+
+START_TEST(test_debug_convert_old_level_old_format)
+{
+    int expected_level = 0x0000;
+    int old_level;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+
+    fail_unless(
+        debug_convert_old_level(SSS_UNRESOLVED_DEBUG_LEVEL) == SSSDBG_UNRESOLVED,
+        "Invalid conversion of SSS_UNRESOLVED_DEBUG_LEVEL"
+    );
+
+    for (old_level = 0; old_level <= 9; old_level++) {
+        expected_level |= levels[old_level];
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Invalid conversion of %d", old_level);
+        fail_unless(debug_convert_old_level(old_level) == expected_level, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_convert_old_level_new_format)
+{
+    fail_unless(
+        debug_convert_old_level(SSSDBG_UNRESOLVED) == SSSDBG_UNRESOLVED,
+        "Invalid conversion of SSSDBG_UNRESOLVED"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_FATAL_FAILURE) == SSSDBG_FATAL_FAILURE,
+        "Invalid conversion of SSSDBG_FATAL_FAILURE"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_CRIT_FAILURE) == SSSDBG_CRIT_FAILURE,
+        "Invalid conversion of SSSDBG_CRIT_FAILURE"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_OP_FAILURE) == SSSDBG_OP_FAILURE,
+        "Invalid conversion of SSSDBG_OP_FAILURE"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_MINOR_FAILURE) == SSSDBG_MINOR_FAILURE,
+        "Invalid conversion of SSSDBG_MINOR_FAILURE"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_CONF_SETTINGS) == SSSDBG_CONF_SETTINGS,
+        "Invalid conversion of SSSDBG_CONF_SETTINGS"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_FUNC_DATA) == SSSDBG_FUNC_DATA,
+        "Invalid conversion of SSSDBG_FUNC_DATA"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_TRACE_FUNC) == SSSDBG_TRACE_FUNC,
+        "Invalid conversion of SSSDBG_TRACE_FUNC"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_TRACE_LIBS) == SSSDBG_TRACE_LIBS,
+        "Invalid conversion of SSSDBG_TRACE_LIBS"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_TRACE_INTERNAL) == SSSDBG_TRACE_INTERNAL,
+        "Invalid conversion of SSSDBG_TRACE_INTERNAL"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_TRACE_ALL) == SSSDBG_TRACE_ALL,
+        "Invalid conversion of SSSDBG_TRACE_ALL"
+    );
+    fail_unless(
+        debug_convert_old_level(SSSDBG_MASK_ALL) == SSSDBG_MASK_ALL,
+        "Invalid conversion of SSSDBG_MASK_ALL"
+    );
+}
+END_TEST
+
+START_TEST(test_debug_get_level_old_format)
+{
+    fail_unless(debug_get_level(SSS_UNRESOLVED_DEBUG_LEVEL) == SSSDBG_UNRESOLVED, "Invalid conversion of -1");
+    fail_unless(debug_get_level(0) == SSSDBG_FATAL_FAILURE, "Invalid conversion of 0");
+    fail_unless(debug_get_level(1) == SSSDBG_CRIT_FAILURE, "Invalid conversion of 1");
+    fail_unless(debug_get_level(2) == SSSDBG_OP_FAILURE, "Invalid conversion of 2");
+    fail_unless(debug_get_level(3) == SSSDBG_MINOR_FAILURE, "Invalid conversion of 3");
+    fail_unless(debug_get_level(4) == SSSDBG_CONF_SETTINGS, "Invalid conversion of 4");
+    fail_unless(debug_get_level(5) == SSSDBG_FUNC_DATA, "Invalid conversion of 5");
+    fail_unless(debug_get_level(6) == SSSDBG_TRACE_FUNC, "Invalid conversion of 6");
+    fail_unless(debug_get_level(7) == SSSDBG_TRACE_LIBS, "Invalid conversion of 7");
+    fail_unless(debug_get_level(8) == SSSDBG_TRACE_INTERNAL, "Invalid conversion of 8");
+    fail_unless(debug_get_level(9) == SSSDBG_TRACE_ALL, "Invalid conversion of 9");
+}
+END_TEST
+
+START_TEST(test_debug_get_level_new_format)
+{
+    fail_unless(
+        debug_get_level(SSSDBG_UNRESOLVED) == SSSDBG_UNRESOLVED,
+        "Invalid conversion of SSSDBG_UNRESOLVED"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_FATAL_FAILURE) == SSSDBG_FATAL_FAILURE,
+        "Invalid conversion of SSSDBG_FATAL_FAILURE"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_CRIT_FAILURE) == SSSDBG_CRIT_FAILURE,
+        "Invalid conversion of SSSDBG_CRIT_FAILURE"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_OP_FAILURE) == SSSDBG_OP_FAILURE,
+        "Invalid conversion of SSSDBG_OP_FAILURE"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_MINOR_FAILURE) == SSSDBG_MINOR_FAILURE,
+        "Invalid conversion of SSSDBG_MINOR_FAILURE"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_CONF_SETTINGS) == SSSDBG_CONF_SETTINGS,
+        "Invalid conversion of SSSDBG_CONF_SETTINGS"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_FUNC_DATA) == SSSDBG_FUNC_DATA,
+        "Invalid conversion of SSSDBG_FUNC_DATA"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_TRACE_FUNC) == SSSDBG_TRACE_FUNC,
+        "Invalid conversion of SSSDBG_TRACE_FUNC"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_TRACE_LIBS) == SSSDBG_TRACE_LIBS,
+        "Invalid conversion of SSSDBG_TRACE_LIBS"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_TRACE_INTERNAL) == SSSDBG_TRACE_INTERNAL,
+        "Invalid conversion of SSSDBG_TRACE_INTERNAL"
+    );
+    fail_unless(
+        debug_get_level(SSSDBG_TRACE_ALL) == SSSDBG_TRACE_ALL,
+        "Invalid conversion of SSSDBG_TRACE_ALL"
+    );
+}
+END_TEST
+
+int test_helper_debug_check_message(int level, int msgmode)
+{
+    TALLOC_CTX *ctx = talloc_new(NULL);
+    char filename[24] = {'\0'};
+    char *msg = NULL;
+    char *compare_to = NULL;
+    const char *function = __FUNCTION__;
+    const char *body = "some error\n";
+    int filesize;
+    int fd;
+    int set_fd_result;
+    int ret;
+    FILE *file = NULL;
+
+    strncpy(filename, "sssd_debug_tests.XXXXXX", 24);
+    fd = mkstemp(filename);
+    if (fd == -1) {
+        ret = errno;
+        talloc_free(ctx);
+        return errno;
+    }
+
+    file = fdopen(fd, "r");
+    if (file == NULL) {
+        ret = errno;
+        goto done;
+    }
+
+    set_fd_result = set_debug_file_from_fd(fd);
+    if (set_fd_result != EOK) {
+        ret = set_fd_result;
+        goto done;
+    }
+
+    if (msgmode == 0) {
+        DEBUG(level, (body));
+    } else {
+        DEBUG_MSG(level, __FUNCTION__, "some error");
+    }
+
+    fseek(file, 0, SEEK_END);
+    filesize = ftell(file);
+
+    rewind(file);
+    msg = talloc_array(ctx, char, filesize);
+    if (msg == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+    fread(msg, sizeof(char), filesize, file);
+
+    compare_to = talloc_array(ctx, char, filesize);
+    if (compare_to == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    if (debug_timestamps == 1) {
+        char time_day[4] = {'\0'};
+        char time_month[4] = {'\0'};
+        int time_day_num;
+        int time_hour;
+        int time_min;
+        int time_sec;
+        int time_year;
+        if (sscanf(msg, "(%s %s %d %d:%d:%d %d)", time_day, time_month,
+            &time_day_num, &time_hour, &time_min, &time_sec, &time_year) != 7) {
+            ret = DEBUG_TEST_NOK_TS;
+            goto done;
+        }
+        sprintf(compare_to, "(%s %s %2d %.2d:%.2d:%.2d %.4d) [%s] [%s] (0x%.4x): %s",
+                time_day, time_month, time_day_num, time_hour, time_min, time_sec, time_year,
+                debug_prg_name, function, level, body);
+    } else {
+        sprintf(compare_to, "[%s] [%s] (0x%.4x): %s", debug_prg_name, function, level, body);
+    }
+    ret = strncmp(msg, compare_to, filesize) == 0 ? EOK : DEBUG_TEST_NOK;
+
+done:
+    talloc_free(ctx);
+    fclose(file);
+    remove(filename);
+    return ret;
+}
+
+int test_helper_debug_is_empty_message(int level, int msgmode)
+{
+    char filename[24] = {'\0'};
+    int fd;
+    int filesize;
+    int set_fd_result;
+    int ret;
+    FILE *file;
+
+    strncpy(filename, "sssd_debug_tests.XXXXXX", 24);
+    fd = mkstemp(filename);
+    if (fd == -1)
+        return errno;
+
+    file = fdopen(fd, "r");
+    if (file == NULL) {
+        ret = errno;
+        goto done;
+    }
+
+    set_fd_result = set_debug_file_from_fd(fd);
+    if (set_fd_result != EOK) {
+        ret = set_fd_result;
+        goto done;
+    }
+
+    if (msgmode == 0) {
+        DEBUG(level, ("some error\n"));
+    } else {
+        DEBUG_MSG(level, __FUNCTION__, "some error");
+    }
+    fseek(file, 0, SEEK_END);
+    filesize = ftell(file);
+
+    ret = filesize == 0 ? EOK : DEBUG_TEST_NOK;
+
+done:
+    fclose(file);
+    remove(filename);
+    return ret;
+}
+
+START_TEST(test_debug_is_set_single_no_timestamp)
+{
+    int i;
+    int result;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = levels[i];
+        result = test_helper_debug_check_message(levels[i], 0);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message don't match", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_is_set_single_timestamp)
+{
+    int i;
+    int result;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 1;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = levels[i];
+        result = test_helper_debug_check_message(levels[i], 0);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+
+        sprintf(msg, "Test of level 0x%.4x failed - invalid timestamp", levels[i]);
+        fail_if(result == DEBUG_TEST_NOK_TS, msg);
+
+        sprintf(msg, "Test of level 0x%.4x failed - message don't match", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_is_notset_no_timestamp)
+{
+    int i;
+    int result;
+    int all_set = SSSDBG_MASK_ALL;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = all_set & ~levels[i];
+        result = test_helper_debug_is_empty_message(levels[i], 0);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message has been written", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_is_notset_timestamp)
+{
+    int i;
+    int result;
+    int all_set = SSSDBG_MASK_ALL;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = all_set & ~levels[i];
+        result = test_helper_debug_is_empty_message(levels[i], 0);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message has been written", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_msg_is_set_single_no_timestamp)
+{
+    int i;
+    int result;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = levels[i];
+        result = test_helper_debug_check_message(levels[i], 1);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message don't match", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_msg_is_set_single_timestamp)
+{
+    int i;
+    int result;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 1;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = levels[i];
+        result = test_helper_debug_check_message(levels[i], 1);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+
+        sprintf(msg, "Test of level 0x%.4x failed - invalid timestamp", levels[i]);
+        fail_if(result == DEBUG_TEST_NOK_TS, msg);
+
+        sprintf(msg, "Test of level 0x%.4x failed - message don't match", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_msg_is_notset_no_timestamp)
+{
+    int i;
+    int result;
+    int all_set = SSSDBG_MASK_ALL;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = all_set & ~levels[i];
+        result = test_helper_debug_is_empty_message(levels[i], 1);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message has been written", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_msg_is_notset_timestamp)
+{
+    int i;
+    int result;
+    int all_set = SSSDBG_MASK_ALL;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+    char *error_msg;
+
+    debug_timestamps = 0;
+    debug_to_file = 1;
+    debug_prg_name = "sssd";
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = all_set & ~levels[i];
+        result = test_helper_debug_is_empty_message(levels[i], 1);
+
+        error_msg = strerror(result);
+        fail_unless(result == EOK || result == DEBUG_TEST_NOK || result == DEBUG_TEST_NOK_TS, error_msg);
+
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - message has been written", levels[i]);
+        fail_unless(result == EOK, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_is_set_true)
+{
+    int i;
+    int result;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+
+    debug_level = SSSDBG_MASK_ALL;
+
+    for (i = 0; i <= 9; i++) {
+        result = DEBUG_IS_SET(levels[i]);
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - result is 0x%.4x", levels[i], result);
+        fail_unless(result > 0, msg);
+    }
+}
+END_TEST
+
+START_TEST(test_debug_is_set_false)
+{
+    int i;
+    int result;
+    int all_set = SSSDBG_MASK_ALL;
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL
+    };
+
+    for (i = 0; i <= 9; i++) {
+        debug_level = all_set & ~levels[i];
+
+        result = DEBUG_IS_SET(levels[i]);
+        char msg[50] = {'\0'};
+        sprintf(msg, "Test of level 0x%.4x failed - result is 0x%.4x", levels[i], result);
+        fail_unless(result == 0, msg);
+    }
+}
+END_TEST
+
+Suite *debug_suite(void)
+{
+    Suite *s = suite_create("debug");
+
+    TCase *tc_debug = tcase_create("debug");
+
+    tcase_add_test(tc_debug, test_debug_convert_old_level_old_format);
+    tcase_add_test(tc_debug, test_debug_convert_old_level_new_format);
+    tcase_add_test(tc_debug, test_debug_get_level_old_format);
+    tcase_add_test(tc_debug, test_debug_get_level_new_format);
+    tcase_add_test(tc_debug, test_debug_is_set_single_no_timestamp);
+    tcase_add_test(tc_debug, test_debug_is_set_single_timestamp);
+    tcase_add_test(tc_debug, test_debug_is_notset_no_timestamp);
+    tcase_add_test(tc_debug, test_debug_is_notset_timestamp);
+    tcase_add_test(tc_debug, test_debug_msg_is_set_single_no_timestamp);
+    tcase_add_test(tc_debug, test_debug_msg_is_set_single_timestamp);
+    tcase_add_test(tc_debug, test_debug_msg_is_notset_no_timestamp);
+    tcase_add_test(tc_debug, test_debug_msg_is_notset_timestamp);
+    tcase_add_test(tc_debug, test_debug_is_set_true);
+    tcase_add_test(tc_debug, test_debug_is_set_false);
+    tcase_set_timeout(tc_debug, 60);
+
+    suite_add_tcase(s, tc_debug);
+
+    return s;
+}
+
+int main(int argc, const char *argv[])
+{
+    int number_failed;
+
+    Suite *s = debug_suite();
+    SRunner *sr = srunner_create(s);
+
+    srunner_run_all(sr, CK_NORMAL);
+    number_failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+
+    if (number_failed == 0)
+        return EXIT_SUCCESS;
+
+    return EXIT_FAILURE;
+}
diff --git a/src/tests/fail_over-tests.c b/src/tests/fail_over-tests.c
index 8beaa8a..439e5cf 100644
--- a/src/tests/fail_over-tests.c
+++ b/src/tests/fail_over-tests.c
@@ -307,7 +307,7 @@ main(int argc, const char *argv[])
         }
     }
     poptFreeContext(pc);
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
 
     tests_set_cwd();
 
diff --git a/src/tests/files-tests.c b/src/tests/files-tests.c
index 7f6b41e..15d34c8 100644
--- a/src/tests/files-tests.c
+++ b/src/tests/files-tests.c
@@ -318,7 +318,7 @@ int main(int argc, const char *argv[])
         return 1;
     }
     poptFreeContext(pc);
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
 
     tests_set_cwd();
 
diff --git a/src/tests/find_uid-tests.c b/src/tests/find_uid-tests.c
index 8d1362f..a8f7405 100644
--- a/src/tests/find_uid-tests.c
+++ b/src/tests/find_uid-tests.c
@@ -114,7 +114,7 @@ Suite *find_uid_suite (void)
 
 int main(void)
 {
-    debug_level = 255;
+    debug_level = SSSDBG_MASK_ALL;
     int number_failed;
 
     tests_set_cwd();
diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
index d5d1f09..65e4319 100644
--- a/src/tests/krb5_utils-tests.c
+++ b/src/tests/krb5_utils-tests.c
@@ -654,6 +654,7 @@ int main(int argc, const char *argv[])
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
 
     ret = mkdir(TESTS_PATH, 0775);
     if (ret != EOK) {
diff --git a/src/tests/refcount-tests.c b/src/tests/refcount-tests.c
index 5e85b6f..99eedd9 100644
--- a/src/tests/refcount-tests.c
+++ b/src/tests/refcount-tests.c
@@ -218,7 +218,7 @@ int main(int argc, const char *argv[])
         }
     }
     poptFreeContext(pc);
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
 
     tests_set_cwd();
 
diff --git a/src/tests/resolv-tests.c b/src/tests/resolv-tests.c
index 5c1a487..3768fc9 100644
--- a/src/tests/resolv-tests.c
+++ b/src/tests/resolv-tests.c
@@ -790,7 +790,7 @@ int main(int argc, const char *argv[])
         }
     }
     poptFreeContext(pc);
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
 
     if (!use_net_test) {
         printf("Network tests disabled. Rerun with the \"-n\" "
diff --git a/src/tests/simple_access-tests.c b/src/tests/simple_access-tests.c
index fbbc836..6ae2356 100644
--- a/src/tests/simple_access-tests.c
+++ b/src/tests/simple_access-tests.c
@@ -162,6 +162,7 @@ int main(int argc, const char *argv[])
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
 
     Suite *s = access_simple_suite();
     SRunner *sr = srunner_create(s);
diff --git a/src/tests/strtonum-tests.c b/src/tests/strtonum-tests.c
index 2b91d48..8e86c11 100644
--- a/src/tests/strtonum-tests.c
+++ b/src/tests/strtonum-tests.c
@@ -446,6 +446,8 @@ int main(int argc, const char *argv[]) {
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     tests_set_cwd();
 
     strtonum_suite = create_strtonum_suite();
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index d0f7ab4..274c7fa 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -3173,6 +3173,8 @@ int main(int argc, const char *argv[]) {
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     tests_set_cwd();
 
     ret = unlink(TESTS_PATH"/"LOCAL_SYSDB_FILE);
diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c
index e6d099b..b347aa7 100644
--- a/src/tests/util-tests.c
+++ b/src/tests/util-tests.c
@@ -355,6 +355,8 @@ int main(int argc, const char *argv[])
     }
     poptFreeContext(pc);
 
+    debug_level = debug_convert_old_level(debug_level);
+
     tests_set_cwd();
 
     srunner_run_all(sr, CK_ENV);
diff --git a/src/tools/selinux.c b/src/tools/selinux.c
index 45672d1..8eb19a2 100644
--- a/src/tools/selinux.c
+++ b/src/tools/selinux.c
@@ -121,19 +121,7 @@ static void sss_semanage_error_callback(void *varg,
         return;
     }
 
-    if (level <= debug_level) {
-        if (debug_timestamps) {
-            time_t rightnow = time(NULL);
-            char stamp[25];
-            memcpy(stamp, ctime(&rightnow), 24);
-            stamp[24] = '\0';
-            debug_fn("(%s) [%s] [libsemanage] (%d): %s\n",
-                     stamp, debug_prg_name, level, message);
-        } else {
-            debug_fn("[%s] [libsemanage] (%d): %s\n",
-                     debug_prg_name, level, message);
-        }
-    }
+    DEBUG_MSG(level, "libsemanage", message);
     free(message);
 }
 
diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c
index 0b08652..b0771b9 100644
--- a/src/tools/sss_cache.c
+++ b/src/tools/sss_cache.c
@@ -300,7 +300,7 @@ errno_t init_context(int argc, const char *argv[], struct cache_tool_ctx **tctx)
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
     }
 
-    debug_level = debug;
+    debug_level = debug_convert_old_level(debug);
     debug_prg_name = argv[0];
     CHECK_ROOT(ret, debug_prg_name);
 
diff --git a/src/tools/sss_groupadd.c b/src/tools/sss_groupadd.c
index 8817625..90b1d08 100644
--- a/src/tools/sss_groupadd.c
+++ b/src/tools/sss_groupadd.c
@@ -65,7 +65,7 @@ int main(int argc, const char **argv)
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     /* groupname is an argument, not option */
     pc_groupname = poptGetArg(pc);
diff --git a/src/tools/sss_groupdel.c b/src/tools/sss_groupdel.c
index 99b6908..b3e741e 100644
--- a/src/tools/sss_groupdel.c
+++ b/src/tools/sss_groupdel.c
@@ -61,7 +61,7 @@ int main(int argc, const char **argv)
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     pc_groupname = poptGetArg(pc);
     if (pc_groupname == NULL) {
diff --git a/src/tools/sss_groupmod.c b/src/tools/sss_groupmod.c
index 59ec10b..96189ab 100644
--- a/src/tools/sss_groupmod.c
+++ b/src/tools/sss_groupmod.c
@@ -98,7 +98,7 @@ int main(int argc, const char **argv)
         BAD_POPT_PARAMS(pc, _("Specify group to modify\n"), ret, fini);
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     CHECK_ROOT(ret, debug_prg_name);
 
diff --git a/src/tools/sss_groupshow.c b/src/tools/sss_groupshow.c
index 1532485..69063fc 100644
--- a/src/tools/sss_groupshow.c
+++ b/src/tools/sss_groupshow.c
@@ -644,7 +644,7 @@ int main(int argc, const char **argv)
         }
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     if (ret != -1) {
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
diff --git a/src/tools/sss_useradd.c b/src/tools/sss_useradd.c
index edff6e1..0d3a34d 100644
--- a/src/tools/sss_useradd.c
+++ b/src/tools/sss_useradd.c
@@ -96,7 +96,7 @@ int main(int argc, const char **argv)
         }
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     if (ret != -1) {
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
diff --git a/src/tools/sss_userdel.c b/src/tools/sss_userdel.c
index 1d0cb12..29ecfba 100644
--- a/src/tools/sss_userdel.c
+++ b/src/tools/sss_userdel.c
@@ -173,7 +173,7 @@ int main(int argc, const char **argv)
         }
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     if (ret != -1) {
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
diff --git a/src/tools/sss_usermod.c b/src/tools/sss_usermod.c
index bcf2b3a..d2b6782 100644
--- a/src/tools/sss_usermod.c
+++ b/src/tools/sss_usermod.c
@@ -109,7 +109,7 @@ int main(int argc, const char **argv)
         BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
     }
 
-    debug_level = pc_debug;
+    debug_level = debug_convert_old_level(pc_debug);
 
     /* username is an argument without --option */
     pc_username = poptGetArg(pc);
diff --git a/src/util/debug.c b/src/util/debug.c
index e9ed8ae..cf2a7d6 100644
--- a/src/util/debug.c
+++ b/src/util/debug.c
@@ -55,6 +55,49 @@ errno_t set_debug_file_from_fd(const int fd)
     return EOK;
 }
 
+int debug_convert_old_level(int old_level)
+{
+    if ((old_level != 0) && !(old_level & 0x000F))
+        return old_level;
+
+    if( old_level == SSS_UNRESOLVED_DEBUG_LEVEL )
+        return SSSDBG_UNRESOLVED;
+
+    int new_level = SSSDBG_FATAL_FAILURE;
+
+    if (old_level == 0)
+        return new_level;
+
+    if (old_level >= 1)
+        new_level |= SSSDBG_CRIT_FAILURE;
+
+    if (old_level >= 2)
+        new_level |= SSSDBG_OP_FAILURE;
+
+    if (old_level >= 3)
+        new_level |= SSSDBG_MINOR_FAILURE;
+
+    if (old_level >= 4)
+        new_level |= SSSDBG_CONF_SETTINGS;
+
+    if (old_level >= 5)
+        new_level |= SSSDBG_FUNC_DATA;
+
+    if (old_level >= 6)
+        new_level |= SSSDBG_TRACE_FUNC;
+
+    if (old_level >= 7)
+        new_level |= SSSDBG_TRACE_LIBS;
+
+    if (old_level >= 8)
+        new_level |= SSSDBG_TRACE_INTERNAL;
+
+    if (old_level >= 9)
+        new_level |= SSSDBG_TRACE_ALL;
+
+    return new_level;
+}
+
 void debug_fn(const char *format, ...)
 {
     va_list ap;
@@ -67,25 +110,52 @@ void debug_fn(const char *format, ...)
     va_end(ap);
 }
 
+int debug_get_level(int old_level)
+{
+    if ((old_level != 0) && !(old_level & 0x000F))
+        return old_level;
+
+    if( old_level == SSS_UNRESOLVED_DEBUG_LEVEL )
+        return SSSDBG_UNRESOLVED;
+
+    if ((old_level > 9) || (old_level < 0))
+        return SSSDBG_FATAL_FAILURE;
+
+    int levels[] = {
+        SSSDBG_FATAL_FAILURE,   /* 0 */
+        SSSDBG_CRIT_FAILURE,
+        SSSDBG_OP_FAILURE,
+        SSSDBG_MINOR_FAILURE,
+        SSSDBG_CONF_SETTINGS,
+        SSSDBG_FUNC_DATA,
+        SSSDBG_TRACE_FUNC,
+        SSSDBG_TRACE_LIBS,
+        SSSDBG_TRACE_INTERNAL,
+        SSSDBG_TRACE_ALL        /* 9 */
+    };
+
+    return levels[old_level];
+}
+
 void ldb_debug_messages(void *context, enum ldb_debug_level level,
                         const char *fmt, va_list ap)
 {
-    int loglevel = -1;
+    int loglevel = SSSDBG_UNRESOLVED;
     int ret;
     char * message = NULL;
 
     switch(level) {
     case LDB_DEBUG_FATAL:
-        loglevel = 0;
+        loglevel = SSSDBG_FATAL_FAILURE;
         break;
     case LDB_DEBUG_ERROR:
-        loglevel = 1;
+        loglevel = SSSDBG_CRIT_FAILURE;
         break;
     case LDB_DEBUG_WARNING:
-        loglevel = 6;
+        loglevel = SSSDBG_TRACE_FUNC;
         break;
     case LDB_DEBUG_TRACE:
-        loglevel = 9;
+        loglevel = SSSDBG_TRACE_ALL;
         break;
     }
 
@@ -95,19 +165,8 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level,
         return;
     }
 
-    if (loglevel <= debug_level) {
-        if (debug_timestamps) {
-            time_t rightnow = time(NULL);
-            char stamp[25];
-            memcpy(stamp, ctime(&rightnow), 24);
-            stamp[24] = '\0';
-            debug_fn("(%s) [%s] [ldb] (%d): %s\n",
-                     stamp, debug_prg_name, loglevel, message);
-        } else {
-            debug_fn("[%s] [ldb] (%d): %s\n",
-                     debug_prg_name, loglevel, message);
-        }
-    }
+    DEBUG_MSG(loglevel, "ldb", message);
+
     free(message);
 }
 
diff --git a/src/util/server.c b/src/util/server.c
index 7d16d04..1d48d84 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -470,6 +470,8 @@ int server_setup(const char *name, int flags,
                       ret, strerror(ret)));
             return ret;
         }
+
+        debug_level = debug_convert_old_level(debug_level);
     }
 
     /* same for debug timestamps */
diff --git a/src/util/util.h b/src/util/util.h
index 3ff5f62..defc579 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -57,10 +57,27 @@ extern int debug_timestamps;
 extern int debug_to_file;
 extern const char *debug_log_file;
 void debug_fn(const char *format, ...);
+int debug_get_level(int old_level);
+int debug_convert_old_level(int old_level);
 errno_t set_debug_file_from_fd(const int fd);
 
-#define SSS_DEFAULT_DEBUG_LEVEL 0
-#define SSS_UNRESOLVED_DEBUG_LEVEL -1
+#define SSS_DEFAULT_DEBUG_LEVEL SSSDBG_DEFAULT
+#define SSS_UNRESOLVED_DEBUG_LEVEL SSSDBG_UNRESOLVED
+
+#define SSSDBG_FATAL_FAILURE  0x0010   /* level 0 */
+#define SSSDBG_CRIT_FAILURE   0x0020   /* level 1 */
+#define SSSDBG_OP_FAILURE     0x0040   /* level 2 */
+#define SSSDBG_MINOR_FAILURE  0x0080   /* level 3 */
+#define SSSDBG_CONF_SETTINGS  0x0100   /* level 4 */
+#define SSSDBG_FUNC_DATA      0x0200   /* level 5 */
+#define SSSDBG_TRACE_FUNC     0x0400   /* level 6 */
+#define SSSDBG_TRACE_LIBS     0x1000   /* level 7 */
+#define SSSDBG_TRACE_INTERNAL 0x2000   /* level 8 */
+#define SSSDBG_TRACE_ALL      0x4000   /* level 9 */
+
+#define SSSDBG_UNRESOLVED     -1
+#define SSSDBG_MASK_ALL       0xFFF0   /* enable all debug levels */
+#define SSSDBG_DEFAULT        SSSDBG_FATAL_FAILURE
 
 #define SSSDBG_TIMESTAMP_UNRESOLVED   -1
 #define SSSDBG_TIMESTAMP_DEFAULT       1
@@ -76,7 +93,8 @@ errno_t set_debug_file_from_fd(const int fd);
 /** \def DEBUG(level, body)
     \brief macro to generate debug messages
 
-    \param level the debug level, please respect the following guidelines:
+    \param level the debug level, please use one of the SSSDBG_* macros
+      Old format:
       - 1 is for critical errors users may find it difficult to understand but
         are still quite clear
       - 2-4 is for stuff developers are interested in in general, but
@@ -88,22 +106,56 @@ errno_t set_debug_file_from_fd(const int fd);
     \param body the debug message you want to send, should end with \n
 */
 #define DEBUG(level, body) do { \
-    if (level <= debug_level) { \
+    int __debug_macro_newlevel = debug_get_level(level); \
+    if ((debug_level > 0) && (__debug_macro_newlevel & debug_level)) { \
         if (debug_timestamps) { \
             time_t rightnow = time(NULL); \
             char stamp[25]; \
             memcpy(stamp, ctime(&rightnow), 24); \
             stamp[24] = '\0'; \
-            debug_fn("(%s) [%s] [%s] (%d): ", \
-                     stamp, debug_prg_name, __FUNCTION__, level); \
+            debug_fn("(%s) [%s] [%s] (0x%.4x): ", \
+                     stamp, debug_prg_name, __FUNCTION__, __debug_macro_newlevel); \
         } else { \
-            debug_fn("[%s] [%s] (%d): ", \
-                     debug_prg_name, __FUNCTION__, level); \
+            debug_fn("[%s] [%s] (0x%.4x): ", \
+                     debug_prg_name, __FUNCTION__, __debug_macro_newlevel); \
         } \
         debug_fn body; \
     } \
 } while(0);
 
+/** \def DEBUG(level, body)
+    \brief macro to generate debug messages with message from variable
+
+    \param level the debug level, please use one of the SSSDBG_* macros
+
+    \param function name of the function where DEBUG_MSG is called
+
+    \param message message to be send (should not end with \n)
+*/
+#define DEBUG_MSG(level, function, message) do { \
+    int __debug_macro_newlevel = debug_get_level(level); \
+    if ((debug_level > 0) && (__debug_macro_newlevel & debug_level)) { \
+        if (debug_timestamps) { \
+            time_t rightnow = time(NULL); \
+            char stamp[25]; \
+            memcpy(stamp, ctime(&rightnow), 24); \
+            stamp[24] = '\0'; \
+            debug_fn("(%s) [%s] [%s] (0x%.4x): %s\n", \
+                     stamp, debug_prg_name, function, __debug_macro_newlevel, message); \
+        } else { \
+            debug_fn("[%s] [%s] (0x%.4x): %s\n", \
+                     debug_prg_name, function, __debug_macro_newlevel, message); \
+        } \
+    } \
+} while(0);
+
+/** \def DEBUG_IS_SET(level)
+    \brief checks whether level is set in debug_level
+
+    \param level the debug level, please use one of the SSSDBG*_ macros
+*/
+#define DEBUG_IS_SET(level) ((debug_level > 0) && (debug_level & (debug_get_level(level))))
+
 #define PRINT(fmt, ...) fprintf(stdout, gettext(fmt), ##__VA_ARGS__)
 #define ERROR(fmt, ...) fprintf(stderr, gettext(fmt), ##__VA_ARGS__)
 
-- 
1.7.6

