Winbind cleanup.
authorAndrew Bartlett <abartlet@samba.org>
Fri, 15 Feb 2002 13:28:59 +0000 (13:28 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 15 Feb 2002 13:28:59 +0000 (13:28 +0000)
This patch fixes the segfaults I introduced in the previous conneciton caching
patch.  It cleans up the connection cache a *lot* - in particular it adds
significant robustness to the operation.

If a the DC goes down, we no longer fail the next operation - the code checks
if the connection died during one of its own operations on the socket, and
restarts the conneciton as required.

There is still a memory leak in here somewhere - but this code also cleans up a
number of these.

Also added is the abilty to sepecify the domain of the 'get around restrict anonymous'
user that winbind uses.

Andrew Bartlett
(This used to be commit 92cbefdf2783bf9dbbb2179c1b2f7cdb802d84a9)

source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_pam.c

index f39381e507412e8ade1456178b5b5587497025bc..bc05f9cebb9ed6869df13843becd0b78a92a4576 100644 (file)
@@ -43,14 +43,16 @@ static char get_winbind_separator(void)
        if (winbindd_request(WINBINDD_INFO, NULL, &response) !=
            NSS_STATUS_SUCCESS) {
                printf("could not obtain winbind seperator!\n");
-               exit(1);
+               /* HACK: (this module should not call lp_ funtions) */
+               return *lp_winbind_separator();
        }
 
        winbind_separator = response.data.info.winbind_separator;
 
        if (!winbind_separator) {
                printf("winbind separator was NULL!\n");
-               exit(1);
+               /* HACK: (this module should not call lp_ funtions) */
+               return *lp_winbind_separator();
        }
        
        return winbind_separator;
@@ -69,7 +71,9 @@ static char *get_winbind_domain(void)
        if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
            NSS_STATUS_SUCCESS) {
                printf("could not obtain winbind domain name!\n");
-               exit(1);
+               
+               /* HACK: (this module should not call lp_ funtions) */
+               return lp_workgroup();
        }
 
        fstrcpy(winbind_domain, response.data.domain_name);
@@ -514,10 +518,13 @@ static BOOL print_domain_groups(void)
 static BOOL wbinfo_set_auth_user(char *username)
 {
        char *password;
+       fstring user, domain;
 
        /* Separate into user and password */
 
-       password = strchr(username, '%');
+       parse_wbinfo_domain_user(username, domain, user);
+
+       password = strchr(user, '%');
 
        if (password) {
                *password = 0;
@@ -528,7 +535,8 @@ static BOOL wbinfo_set_auth_user(char *username)
        /* Store in secrets.tdb */
 
        if (!secrets_store(SECRETS_AUTH_USER, username, strlen(username) + 1) ||
-           !secrets_store(SECRETS_AUTH_PASSWORD, password, strlen(password) + 1)) {
+           !secrets_store(SECRETS_AUTH_DOMAIN, domain, strlen(domain) + 1) ||
+               !secrets_store(SECRETS_AUTH_PASSWORD, password, strlen(password) + 1)) {
                fprintf(stderr, "error storing authenticated user info\n");
                return False;
        }
index 064c3160ae097b703e9b9ec25c00b442f7d3f6df..5b63d236ba144d15fbfa2f7bb99cd2d1f968ed79 100644 (file)
@@ -206,6 +206,7 @@ typedef struct {
 /* Authenticated user info is stored in secrets.tdb under these keys */
 
 #define SECRETS_AUTH_USER      "SECRETS/AUTH_USER"
+#define SECRETS_AUTH_DOMAIN      "SECRETS/AUTH_DOMAIN"
 #define SECRETS_AUTH_PASSWORD  "SECRETS/AUTH_PASSWORD"
 
 #endif /* _WINBINDD_H */
index 4b23327ffe8c3800b8dbd86092be15210334f017..3aaaf6b67096f8e88b09255303f39b6bfcd60571 100644 (file)
@@ -86,7 +86,7 @@ struct get_dc_name_cache {
        struct get_dc_name_cache *prev, *next;
 };
 
-static BOOL cm_get_dc_name(char *domain, fstring srv_name)
+static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
 {
        static struct get_dc_name_cache *get_dc_name_cache;
        struct get_dc_name_cache *dcc;
@@ -204,61 +204,94 @@ static BOOL cm_get_dc_name(char *domain, fstring srv_name)
        DEBUG(3, ("Returning DC %s (%s) for domain %s\n", srv_name,
                  inet_ntoa(dc_ip), domain));
 
+       *ip_out = dc_ip;
+
+       SAFE_FREE(ip_list);
+
        return True;
 }
 
 /* Choose between anonymous or authenticated connections.  We need to use
    an authenticated connection if DCs have the RestrictAnonymous registry
    entry set > 0, or the "Additional restrictions for anonymous
-   connections" set in the win2k Local Security Policy. */
+   connections" set in the win2k Local Security Policy. 
+   
+   Caller to free() result in domain, username, password
+*/
 
-void cm_init_creds(struct ntuser_creds *creds)
+static void cm_get_ipc_userpass(char **username, char **domain, char **password)
 {
-       char *username, *password;
-
-       ZERO_STRUCTP(creds);
-
-       creds->pwd.null_pwd = True; /* anonymoose */
-
-       username = secrets_fetch(SECRETS_AUTH_USER, NULL);
-       password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
-
-       if (username && *username) {
-               pwd_set_cleartext(&creds->pwd, password);
-
-               fstrcpy(creds->user_name, username);
-               fstrcpy(creds->domain, lp_workgroup());
-
-               DEBUG(3, ("IPC$ connections done %s\\%s\n", creds->domain,
-                         creds->user_name));
-       } else 
+       *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
+       *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+       *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+       
+       if (*username && **username) {
+               if (!*domain || !**domain) {
+                       *domain = smb_xstrdup(lp_workgroup());
+               }
+               
+               DEBUG(3, ("IPC$ connections done by user %s\\%s\n", *domain, *username));
+       } else {
                DEBUG(3, ("IPC$ connections done anonymously\n"));
+               *username = smb_xstrdup("");
+               *domain = smb_xstrdup("");
+               *password = smb_xstrdup("");
+       }
 }
 
 /* Open a new smb pipe connection to a DC on a given domain.  Cache
    negative creation attempts so we don't try and connect to broken
    machines too often. */
 
-#define OPEN_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
+#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
 
-struct open_connection_cache {
+struct failed_connection_cache {
        fstring domain_name;
        fstring controller;
        time_t lookup_time;
-       struct open_connection_cache *prev, *next;
+       NTSTATUS nt_status;
+       struct failed_connection_cache *prev, *next;
 };
 
-static BOOL cm_open_connection(char *domain, char *pipe_name,
+static struct failed_connection_cache *failed_connection_cache;
+
+/* Add an entry to the failed conneciton cache */
+
+static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, NTSTATUS result) {
+       struct failed_connection_cache *fcc;
+
+       SMB_ASSERT(!NT_STATUS_IS_OK(result));
+
+       /* Create negative lookup cache entry for this domain and controller */
+
+       if (!(fcc = (struct failed_connection_cache *)
+             malloc(sizeof(struct failed_connection_cache)))) {
+               DEBUG(0, ("malloc failed in add_failed_connection_entry!\n"));
+               return;
+       }
+       
+       ZERO_STRUCTP(fcc);
+       
+       fstrcpy(fcc->domain_name, new_conn->domain);
+       fstrcpy(fcc->controller, new_conn->controller);
+       fcc->lookup_time = time(NULL);
+       fcc->nt_status = result;
+       
+       DLIST_ADD(failed_connection_cache, fcc);
+}
+       
+/* Open a connction to the remote server, cache failures for 30 seconds */
+
+static NTSTATUS cm_open_connection(const char *domain,const char *pipe_name,
                               struct winbindd_cm_conn *new_conn)
 {
-       static struct open_connection_cache *open_connection_cache;
-       struct open_connection_cache *occ;
-       struct nmb_name calling, called;
+       struct failed_connection_cache *fcc;
        extern pstring global_myname;
-       fstring dest_host;
-       struct in_addr dest_ip;
-       BOOL result = False;
-       struct ntuser_creds creds;
+       NTSTATUS result;
+       char *ipc_username, *ipc_domain, *ipc_password;
+       struct in_addr dc_ip;
+
+       ZERO_STRUCT(dc_ip);
 
        fstrcpy(new_conn->domain, domain);
        fstrcpy(new_conn->pipe_name, pipe_name);
@@ -267,27 +300,30 @@ static BOOL cm_open_connection(char *domain, char *pipe_name,
           are cached so don't bother applying the caching for this
           function just yet.  */
 
-       if (!cm_get_dc_name(domain, new_conn->controller))
-               goto done;
-
+       if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
+               result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+               add_failed_connection_entry(new_conn, result);
+               return result;
+       }
+               
        /* Return false if we have tried to look up this domain and netbios
           name before and failed. */
 
-       for (occ = open_connection_cache; occ; occ = occ->next) {
+       for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
                
-               if (!(strequal(domain, occ->domain_name) &&
-                     strequal(new_conn->controller, occ->controller)))
+               if (!(strequal(domain, fcc->domain_name) &&
+                     strequal(new_conn->controller, fcc->controller)))
                        continue; /* Not our domain */
 
-               if ((time(NULL) - occ->lookup_time) > 
-                   OPEN_CONNECTION_CACHE_TIMEOUT) {
+               if ((time(NULL) - fcc->lookup_time) > 
+                   FAILED_CONNECTION_CACHE_TIMEOUT) {
 
                        /* Cache entry has expired, delete it */
 
                        DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller));
 
-                       DLIST_REMOVE(open_connection_cache, occ);
-                       free(occ);
+                       DLIST_REMOVE(failed_connection_cache, fcc);
+                       free(fcc);
 
                        break;
                }
@@ -296,63 +332,52 @@ static BOOL cm_open_connection(char *domain, char *pipe_name,
 
                DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller));
 
-               goto done;
+               result = fcc->nt_status;
+               SMB_ASSERT(!NT_STATUS_IS_OK(result));
+               return result;
        }
 
        /* Initialise SMB connection */
 
-       if (!(new_conn->cli = cli_initialise(NULL)))
-               goto done;
+       cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
 
-       if (!resolve_srv_name(new_conn->controller, dest_host, &dest_ip))
-               goto done;
+       DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", 
+             new_conn->controller, global_myname, ipc_domain, ipc_username));
 
-       make_nmb_name(&called, dns_to_netbios_name(new_conn->controller), 0x20);
-       make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
+       result = cli_full_connection(&(new_conn->cli), global_myname, new_conn->controller, 
+                                    &dc_ip, 0, "IPC$", 
+                                    "IPC", ipc_username, ipc_domain, 
+                                    ipc_password, strlen(ipc_password));
 
-       cm_init_creds(&creds);
-
-       cli_init_creds(new_conn->cli, &creds);
-
-       if (!cli_establish_connection(new_conn->cli, new_conn->controller, 
-                                     &dest_ip, &calling, &called, "IPC$", 
-                                     "IPC", False, True))
-               goto done;
-
-       if (!cli_nt_session_open (new_conn->cli, pipe_name))
-               goto done;
-
-       result = True;
-
- done:
-
-       /* Create negative lookup cache entry for this domain and controller */
-
-       if (!result) {
-               if (!(occ = (struct open_connection_cache *)
-                     malloc(sizeof(struct open_connection_cache))))
-                       return False;
+       SAFE_FREE(ipc_username);
+       SAFE_FREE(ipc_domain);
+       SAFE_FREE(ipc_password);
 
-               ZERO_STRUCTP(occ);
-
-               fstrcpy(occ->domain_name, domain);
-               fstrcpy(occ->controller, new_conn->controller);
-               occ->lookup_time = time(NULL);
-               
-               DLIST_ADD(open_connection_cache, occ);
+       if (!NT_STATUS_IS_OK(result)) {
+               add_failed_connection_entry(new_conn, result);
+               return result;
        }
-
-       if (!result && new_conn->cli)
+       
+       if (!cli_nt_session_open (new_conn->cli, pipe_name)) {
+               result = NT_STATUS_PIPE_NOT_AVAILABLE;
+               add_failed_connection_entry(new_conn, result);
                cli_shutdown(new_conn->cli);
+               return result;
+       }
 
-       return result;
+       return NT_STATUS_OK;
 }
 
 /* Return true if a connection is still alive */
 
 static BOOL connection_ok(struct winbindd_cm_conn *conn)
 {
-       if (!conn->cli->initialised) {
+       if (!conn) {
+               smb_panic("Invalid paramater passed to conneciton_ok():  conn was NULL!\n");
+               return False;
+       }
+
+       if (!conn->cli || !conn->cli->initialised) {
                DEBUG(3, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", 
                          conn->controller, conn->domain, conn->pipe_name));
                return False;
@@ -367,54 +392,86 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn)
        return True;
 }
 
-/* Return a LSA policy handle on a domain */
+/* Get a connection to the remote DC and open the pipe.  If there is already a connection, use that */
 
-CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
+static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, struct winbindd_cm_conn **conn_out) 
 {
-       struct winbindd_cm_conn *conn;
-       uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       struct winbindd_cm_conn *conn, conn_temp;
        NTSTATUS result;
-       static CLI_POLICY_HND hnd;
-
-       /* Look for existing connections */
 
        for (conn = cm_conns; conn; conn = conn->next) {
                if (strequal(conn->domain, domain) && 
-                   strequal(conn->pipe_name, PIPE_LSARPC)) {
-
+                   strequal(conn->pipe_name, pipe_name)) {
                        if (!connection_ok(conn)) {
-                               cli_shutdown(conn->cli);
+                               if (conn->cli) {
+                                       cli_shutdown(conn->cli);
+                               }
+                               conn_temp.next = conn->next;
                                DLIST_REMOVE(cm_conns, conn);
                                SAFE_FREE(conn);
+                               conn = &conn_temp;  /* Just to keep the loop moving */
+                       } else {
+                               break;
                        }
-
-                       goto ok;
                }
        }
+       
+       if (!conn) {
+               if (!(conn = (struct winbindd_cm_conn *) malloc(sizeof(struct winbindd_cm_conn))))
+                       return NT_STATUS_NO_MEMORY;
+               
+               ZERO_STRUCTP(conn);
+               
+               if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, pipe_name, conn))) {
+                       DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", 
+                                 domain, pipe_name, get_nt_error_msg(result)));
+                       SAFE_FREE(conn);
+                       return result;
+               }
+               DLIST_ADD(cm_conns, conn);              
+       }
+       
+       *conn_out = conn;
+       return NT_STATUS_OK;
+}
 
-       /* Create a new one */
+/* Return a LSA policy handle on a domain */
 
-       if (!(conn = (struct winbindd_cm_conn *) malloc(sizeof(struct winbindd_cm_conn))))
-               return NULL;
+CLI_POLICY_HND *cm_get_lsa_handle(char *domain)
+{
+       struct winbindd_cm_conn *conn;
+       uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
+       NTSTATUS result;
+       static CLI_POLICY_HND hnd;
 
-       ZERO_STRUCTP(conn);
+       /* Look for existing connections */
 
-       if (!cm_open_connection(domain, PIPE_LSARPC, conn)) {
-               DEBUG(3, ("Could not connect to a dc for domain %s\n", domain));
+       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
                return NULL;
        }
-
+       
        result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 
                                     des_access, &conn->pol);
 
-       if (!NT_STATUS_IS_OK(result))
-               return NULL;
+       if (!NT_STATUS_IS_OK(result)) {
+               /* Hit the cache code again.  This cleans out the old connection and gets a new one */
+               if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
+                       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) {
+                               return NULL;
+                       }
 
-       /* Add to list */
+                       result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, 
+                                                    des_access, &conn->pol);
+               }
 
-       DLIST_ADD(cm_conns, conn);
+               if (!NT_STATUS_IS_OK(result)) {
+                       cli_shutdown(conn->cli);
+                       DLIST_REMOVE(cm_conns, conn);
+                       SAFE_FREE(conn);
+                       return NULL;
+               }
+       }       
 
- ok:
        hnd.pol = conn->pol;
        hnd.cli = conn->cli;
 
@@ -432,50 +489,39 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain)
 
        /* Look for existing connections */
 
-       for (conn = cm_conns; conn; conn = conn->next) {
-               if (strequal(conn->domain, domain) && strequal(conn->pipe_name, PIPE_SAMR)) {
-
-                       if (!connection_ok(conn)) {
-                               cli_shutdown(conn->cli);
-                               DLIST_REMOVE(cm_conns, conn);
-                               SAFE_FREE(conn);
-                       }
-
-                       goto ok;
-               }
-       }
-
-       /* Create a new one */
-
-       if (!(conn = (struct winbindd_cm_conn *) 
-             malloc(sizeof(struct winbindd_cm_conn))))
-               return NULL;
-
-       ZERO_STRUCTP(conn);
-
-       if (!cm_open_connection(domain, PIPE_SAMR, conn)) {
-               DEBUG(3, ("Could not connect to a dc for domain %s\n", domain));
+       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
                return NULL;
        }
-
+       
        result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
                                  des_access, &conn->pol);
 
-       if (!NT_STATUS_IS_OK(result))
-               return NULL;
+       if (!NT_STATUS_IS_OK(result)) {
+               /* Hit the cache code again.  This cleans out the old connection and gets a new one */
+               if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */
+                       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) {
+                               return NULL;
+                       }
 
-       /* Add to list */
+                       result = cli_samr_connect(conn->cli, conn->cli->mem_ctx,
+                                                 des_access, &conn->pol);
+               }
 
-       DLIST_ADD(cm_conns, conn);
+               if (!NT_STATUS_IS_OK(result)) {
+                       cli_shutdown(conn->cli);
+                       DLIST_REMOVE(cm_conns, conn);
+                       SAFE_FREE(conn);
+                       return NULL;
+               }
+       }       
 
- ok:
        hnd.pol = conn->pol;
        hnd.cli = conn->cli;
 
-       return &hnd;        
+       return &hnd;
 }
 
-#if 0
+#if 0  /* This code now *well* out of date */
 
 /* Return a SAM domain policy handle on a domain */
 
@@ -708,59 +754,44 @@ CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid,
 NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
                             struct cli_state **cli)
 {
-       struct winbindd_cm_conn *conn;
        NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-       BOOL new_conn = False; /* Is this a new connection, to add to the list? */
-
-       /* Open an initial conection */
+       struct winbindd_cm_conn *conn;
 
-       for (conn = cm_conns; conn; conn = conn->next) {
-               if (strequal(conn->domain, domain) && 
-                   strequal(conn->pipe_name, PIPE_NETLOGON)) {
-                       if (!connection_ok(conn)) {
-                               cli_shutdown(conn->cli);
-                               DLIST_REMOVE(cm_conns, conn);
-                               SAFE_FREE(conn);
-                       } else {
-                               break;
-                       }
-               }
+       if (!cli) {
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!conn) {
-               if (!(conn = (struct winbindd_cm_conn *) malloc(sizeof(struct winbindd_cm_conn))))
-                       return NT_STATUS_NO_MEMORY;
+       /* Open an initial conection */
 
-               ZERO_STRUCTP(conn);
-               
-               if (!cm_open_connection(domain, PIPE_NETLOGON, conn)) {
-                       DEBUG(3, ("Could not open a connection to %s\n", domain));
-                       free(conn);
-                       return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-               }
-               
-               new_conn = True;
+       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
+               return result;
        }
        
        result = new_cli_nt_setup_creds(conn->cli, trust_passwd);
 
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0, ("error connecting to domain password server: %s\n",
-                       get_nt_error_msg(result)));
+                         get_nt_error_msg(result)));
+               
+               /* Hit the cache code again.  This cleans out the old connection and gets a new one */
+               if (conn->cli->fd == -1) {
+                       if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) {
+                               return result;
+                       }
+                       
+                       /* Try again */
+                       result = new_cli_nt_setup_creds(conn->cli, trust_passwd);
+               }
+               
+               if (!NT_STATUS_IS_OK(result)) {
                        cli_shutdown(conn->cli);
                        DLIST_REMOVE(cm_conns, conn);
                        SAFE_FREE(conn);
                        return result;
+               }
        }
 
-       /* Add to list */
-
-       if (new_conn) {
-               DLIST_ADD(cm_conns, conn);
-       }
-
-       if (cli)
-               *cli = conn->cli;
+       *cli = conn->cli;
 
        return result;
 }
index 5e3cb149dd06633032d10b1ec12660d2a42a689e..9f6cf2d2eac06655d104e9ad692340746ec2d2c9 100644 (file)
@@ -116,7 +116,7 @@ done:
        fstrcpy(state->response.data.auth.error_string, get_nt_error_msg(result));
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
-       DEBUG(3, ("Plain-text authenticaion for user %s returned %s (PAM: %d)\n", 
+       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authenticaion for user %s returned %s (PAM: %d)\n", 
              state->request.data.auth.user, 
              state->response.data.auth.nt_status_string,
              state->response.data.auth.pam_error));          
@@ -210,7 +210,7 @@ done:
        fstrcpy(state->response.data.auth.error_string, get_nt_error_msg(result));
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
-       DEBUG(3, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n", 
+       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n", 
              state->request.data.auth_crap.domain, 
              state->request.data.auth_crap.user, 
              state->response.data.auth.nt_status_string,