* rename samstrict auth method to sam
authorGerald Carter <jerry@samba.org>
Mon, 30 Jun 2003 17:24:59 +0000 (17:24 +0000)
committerGerald Carter <jerry@samba.org>
Mon, 30 Jun 2003 17:24:59 +0000 (17:24 +0000)
* rename original sam auth method to sam_ignoredomain
* remove samstrict_dc auth method (now covered by 'sam')
* fix wbinfo -a '...' and getent passwd bugs when running
  winbindd on a samba PDC (reported by Volker)
(This used to be commit 52166faee793d337e045d64f7cb27ea7ac895f60)

source3/auth/auth_sam.c
source3/auth/auth_util.c
source3/include/smb_macros.h
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_user.c

index 161376616b14dc8361f7848ccf5e8e8fc3a9d78c..1690e4d5e12af27bf4e84c4ae726d0b6bf2d7a37 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) Andrew Tridgell              1992-2000
    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Copyright (C) Andrew Bartlett              2001
+   Copyright (C) Gerald Carter                2003
    
    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
@@ -470,14 +471,14 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 }
 
 /* module initialisation */
-static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
+static NTSTATUS auth_init_sam_ignoredomain(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
 {
        if (!make_auth_methods(auth_context, auth_method)) {
                return NT_STATUS_NO_MEMORY;
        }
 
        (*auth_method)->auth = check_sam_security;      
-       (*auth_method)->name = "sam";
+       (*auth_method)->name = "sam_ignoredomain";
        return NT_STATUS_OK;
 }
 
@@ -492,83 +493,55 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
                                         const auth_usersupplied_info *user_info, 
                                         auth_serversupplied_info **server_info)
 {
+       BOOL is_local_name, is_my_domain;
 
        if (!user_info || !auth_context) {
                return NT_STATUS_LOGON_FAILURE;
        }
 
-       /* If we are a domain member, we must not 
-          attempt to check the password locally,
-          unless it is one of our aliases. */
+       is_local_name = is_myname(user_info->domain.str);
+       is_my_domain  = strequal(user_info->domain.str, lp_workgroup());
+
+       /* check whether or not we service this domain/workgroup name */
        
-       if (!is_myname(user_info->domain.str)) {
-               DEBUG(7,("The requested user domain is not the local server name. [%s]\\[%s]\n",
-                       user_info->domain.str,user_info->internal_username.str));
-               return NT_STATUS_NO_SUCH_USER;
+       switch ( lp_server_role() ) {
+               case ROLE_STANDALONE:
+               case ROLE_DOMAIN_MEMBER:
+                       if ( !is_local_name ) {
+                               DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n",
+                                       user_info->domain.str, (lp_server_role() == ROLE_DOMAIN_MEMBER 
+                                       ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
+                               return NT_STATUS_NOT_IMPLEMENTED;
+                       }
+               case ROLE_DOMAIN_PDC:
+               case ROLE_DOMAIN_BDC:
+                       if ( !is_local_name && !is_my_domain ) {
+                               DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
+                                       user_info->domain.str));
+                               return NT_STATUS_NOT_IMPLEMENTED;
+                       }
+               default: /* name is ok */
+                       break;
        }
        
        return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info);
 }
 
 /* module initialisation */
-static NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
+static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
 {
        if (!make_auth_methods(auth_context, auth_method)) {
                return NT_STATUS_NO_MEMORY;
        }
 
        (*auth_method)->auth = check_samstrict_security;
-       (*auth_method)->name = "samstrict";
-       return NT_STATUS_OK;
-}
-
-/****************************************************************************
-Check SAM security (above) but with a few extra checks if we're a DC.
-****************************************************************************/
-
-static NTSTATUS check_samstrict_dc_security(const struct auth_context *auth_context,
-                                        void *my_private_data, 
-                                        TALLOC_CTX *mem_ctx,
-                                        const auth_usersupplied_info *user_info, 
-                                        auth_serversupplied_info **server_info)
-{
-
-       if (!user_info || !auth_context) {
-               return NT_STATUS_LOGON_FAILURE;
-       }
-
-       /* If we are a PDC we must not check the password here 
-          unless it is one of our aliases, empty
-          or equal to our domain name.  Other names may be
-          Trusted domains.
-       */
-
-       if ((!is_myworkgroup(user_info->domain.str))&&
-               (!is_myname(user_info->domain.str))) {
-               DEBUG(7,("The requested user domain is not the local server name or our domain. [%s]\\[%s]\n",
-                       user_info->domain.str,user_info->internal_username.str));
-               return NT_STATUS_NO_SUCH_USER;
-       }               
-
-       return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info);
-}
-
-/* module initialisation */
-static NTSTATUS auth_init_samstrict_dc(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 
-{
-       if (!make_auth_methods(auth_context, auth_method)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       (*auth_method)->auth = check_samstrict_dc_security;
-       (*auth_method)->name = "samstrict_dc";
+       (*auth_method)->name = "sam";
        return NT_STATUS_OK;
 }
 
 NTSTATUS auth_sam_init(void)
 {
-       smb_register_auth(AUTH_INTERFACE_VERSION, "samstrict_dc", auth_init_samstrict_dc);
-       smb_register_auth(AUTH_INTERFACE_VERSION, "samstrict", auth_init_samstrict);
        smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam);
+       smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain);
        return NT_STATUS_OK;
 }
index 71fdb0050be31ef564bf306bfa060043dee32417..1538fc50a1b721280b04a9143b34088326ba769b 100644 (file)
@@ -216,8 +216,8 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
        /* do what win2k does.  Always map unknown domains to our own
           and let the "passdb backend" handle unknown users */
 
-       if ( !is_trusted_domain(domain) )
-               domain = lp_workgroup();
+       if ( !is_trusted_domain(domain) ) 
+               domain = get_global_sam_name();
        
        /* we know that it is a trusted domain (and we are allowing them) or it is our domain */
        
index 7fcf872b605e0bbeca183fc3dfbd199f46951849..40b114a6b9e86cde7bfcff9e165521bb09c1ea74 100644 (file)
@@ -248,4 +248,11 @@ copy an IP address from one buffer to another
 
 #define dos_format(fname) string_replace(fname,'/','\\')
 
+/*****************************************************************************
+ Check to see if we are a DO for this domain
+*****************************************************************************/
+
+#define IS_DC_FOR_DOMAIN(x) ( (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC) \
+                               && strequal((x), lp_workgroup()) )
+
 #endif /* _SMB_MACROS_H */
index 265297ca083aa94320349b45e9e13f564b8ba694..70c8de6ee9332caf0a714760fd570a1443ae8963 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) Tim Potter 2000
    Copyright (C) Jeremy Allison 2001.
+   Copyright (C) Gerald (Jerry) Carter 2003.
    
    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
@@ -216,9 +217,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
        /* don't handle our own domain if we are a DC.  This code handles cases where
           the account doesn't exist anywhere and gets passed on down the NSS layer */
 
-       if ( ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role()==ROLE_DOMAIN_BDC)) &&
-               strequal(name_domain, lp_workgroup()) ) 
-       {
+       if ( IS_DC_FOR_DOMAIN(domain->name) ) {
                DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n", 
                        name_domain, name_group));
                return WINBINDD_ERROR;
@@ -370,6 +369,12 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
        for (domain = domain_list(); domain != NULL; domain = domain->next) {
                struct getent_state *domain_state;
                
+               
+               /* don't add our domaina if we are a PDC */
+               
+               if ( IS_DC_FOR_DOMAIN(domain->name) )
+                       continue;
+                                               
                /* Create a state record for this domain */
                
                if ((domain_state = (struct getent_state *)
index a3b08497219cb4f2ac2fe929ddc1b7dcf16307ba..3099944301f1ecc7e9d7229fcd22caa289b65b0f 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    Winbind daemon - pam auth funcions
@@ -53,7 +53,61 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-/* Return a password structure from a username.  */
+/*******************************************************************
+ wrapper around retreiving the trsut account password 
+*******************************************************************/
+
+static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
+                          time_t *pass_last_set_time, uint32 *channel)
+{
+       DOM_SID sid;
+       char *pwd;
+
+       if ( lp_server_role()==ROLE_DOMAIN_MEMBER || strequal(domain, lp_workgroup()) ) 
+       {
+               /*
+                * Get the machine account password for the domain to contact.
+                * This is either our own domain for a workstation, or possibly
+                * any domain for a PDC with trusted domains.
+                */
+
+               if ( !secrets_fetch_trust_account_password (domain, ret_pwd,
+                       pass_last_set_time, channel) ) 
+               {
+                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
+                                 "password for my domain %s\n", domain));
+                       return False;
+               }
+               
+               return True;
+       }
+       else if ( lp_allow_trusted_domains() ) 
+       {
+               /* if we are not a domain member, then we must be a DC and 
+                  this must be a trusted domain */
+
+               if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, 
+                       pass_last_set_time) ) 
+               {
+                       DEBUG(0, ("get_trust_pw: could not fetch trust account "
+                                 "password for trusted domain %s\n", domain));
+                       return False;
+               }
+               
+               *channel = SEC_CHAN_DOMAIN;
+               E_md4hash(pwd, ret_pwd);
+               SAFE_FREE(pwd);
+
+               return True;
+       }
+       
+       /* Failure */
+       return False;
+}
+
+/**********************************************************************
+ Authenticate a user with a clear test password
+**********************************************************************/
 
 enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
 {
@@ -70,6 +124,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
        DATA_BLOB nt_resp;
        DOM_CRED ret_creds;
        int attempts = 0;
+       unsigned char local_lm_response[24];
+       unsigned char local_nt_response[24];
 
        /* Ensure null termination */
        state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
@@ -95,38 +151,29 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
                goto done;
        }
 
-       {
-               unsigned char local_lm_response[24];
-               unsigned char local_nt_response[24];
-               
-               generate_random_buffer(chal, 8, False);
-               SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
+       /* do password magic */
+       
+       generate_random_buffer(chal, 8, False);
+       SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
                
-               SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);
+       SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);
 
-               lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
-               nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
-       }
+       lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
+       nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
        
-       /*
-        * Get the machine account password for our primary domain
-        */
-
-       if (!secrets_fetch_trust_account_password(
-                lp_workgroup(), trust_passwd, &last_change_time,
-               &sec_channel_type)) {
-               DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
-                          "password for domain %s\n", lp_workgroup()));
+       if ( !get_trust_pw(name_domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
                result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                goto done;
        }
 
+       /* check authentication loop */
+
        do {
                ZERO_STRUCT(info3);
                ZERO_STRUCT(ret_creds);
        
                /* Don't shut this down - it belongs to the connection cache code */
-               result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, 
+               result = cm_get_netlogon_cli(name_domain, trust_passwd, 
                                             sec_channel_type, False, &cli);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -173,8 +220,10 @@ done:
        
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
-       
-/* Challenge Response Authentication Protocol */
+
+/**********************************************************************
+ Challenge Response Authentication Protocol 
+**********************************************************************/
 
 enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) 
 {
@@ -187,7 +236,6 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
        TALLOC_CTX *mem_ctx = NULL;
        char *user = NULL;
        const char *domain = NULL;
-       const char *contact_domain;
        const char *workstation;
        DOM_CRED ret_creds;
        int attempts = 0;
@@ -235,52 +283,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
 
        DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid,
                  domain, user));
-                 
-       /* check our role as a domain member first */
-       if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
-               if ( !lp_allow_trusted_domains() && !strequal(domain, lp_workgroup()) ) {
-                       DEBUG(5,("winbindd_pam_auth_crap: failing autghentication becuase of disallowed trust domains\n"));
-                       result = NT_STATUS_LOGON_FAILURE;
-                       goto done;
-               }
-               
-               contact_domain = domain;
-
-               /*
-                * Get the machine account password for the domain to contact.
-                * This is either our own domain for a workstation, or possibly
-                * any domain for a PDC with trusted domains.
-                */
-
-               if (!secrets_fetch_trust_account_password (contact_domain,
-                                                          trust_passwd,
-                                                          &last_change_time,
-                                                          &sec_channel_type)) {
-                       DEBUG(0, ("winbindd_pam_auth_crap: could not fetch trust account "
-                                 "password for domain %s\n", contact_domain));
-                       result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-                       goto done;
-               }
-       }
-       else if ( lp_allow_trusted_domains() ) {
-               /* if we are not a domain member, then we must be a DC.  Must never 
-                  see a logon for our domain */
-               DOM_SID sid;
-               char *pwd;
-               contact_domain = domain;
-
-               if (!secrets_fetch_trusted_domain_password (contact_domain,
-                                                           &pwd, &sid,
-                                                           &last_change_time)) {
-                       DEBUG(0, ("winbindd_pam_auth_crap: could not fetch trust account "
-                                 "password for domain %s\n", contact_domain));
-                       result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-                       goto done;
-               }
-               sec_channel_type = SEC_CHAN_DOMAIN;
-               E_md4hash(pwd, trust_passwd);
-               SAFE_FREE(pwd);
-
+          
+       if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
+               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               goto done;
        }
 
        if (*state->request.data.auth_crap.workstation) {
@@ -310,8 +316,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                ZERO_STRUCT(ret_creds);
 
                /* Don't shut this down - it belongs to the connection cache code */
-               result = cm_get_netlogon_cli(contact_domain, trust_passwd,
-                                            sec_channel_type, False, &cli);
+               result = cm_get_netlogon_cli(domain, trust_passwd, sec_channel_type, False, &cli);
 
                if (!NT_STATUS_IS_OK(result)) {
                        DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
index 518f335f271195f30901cbef20278386c7a174fd..9d9360a6fae83ca6745382c50d1a3459d3c64822 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) Tim Potter 2000
    Copyright (C) Jeremy Allison 2001.
+   Copyright (C) Gerald (Jerry) Carter 2003.
    
    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
@@ -118,9 +119,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
        /* don't handle our own domain if we are a DC.  This code handles cases where
           the account doesn't exist anywhere and gets passed on down the NSS layer */
 
-       if ( ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role()==ROLE_DOMAIN_BDC)) &&
-               strequal(name_domain, lp_workgroup()) ) 
-       {
+       if ( IS_DC_FOR_DOMAIN(domain->name) ) {
                DEBUG(7,("winbindd_getpwnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n", 
                        name_domain, name_user));
                return WINBINDD_ERROR;
@@ -296,6 +295,12 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state)
        for(domain = domain_list(); domain != NULL; domain = domain->next) {
                struct getent_state *domain_state;
                 
+               
+               /* don't add our domaina if we are a PDC */
+               
+               if ( IS_DC_FOR_DOMAIN( domain->name ) )
+                       continue; 
+                                               
                /* Create a state record for this domain */
                 
                if ((domain_state = (struct getent_state *)