BUG 1165, 1126: Fix bug with secondary groups (security = ads) and winbind use defaul...
authorGerald Carter <jerry@samba.org>
Tue, 16 Mar 2004 16:41:54 +0000 (16:41 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 16 Mar 2004 16:41:54 +0000 (16:41 +0000)
(This used to be commit f2eaa14b1eb7e89c945b2b06a48e17998c75d620)

source3/auth/auth_server.c
source3/auth/auth_unix.c
source3/auth/auth_util.c
source3/smbd/sesssetup.c

index 41adc2178416eee813356d2da5de5d4d6da5c077..bc611ec229bff47ae15380665ab28fcd7164734e 100644 (file)
@@ -377,18 +377,17 @@ use this machine as the password server.\n"));
        cli_ulogoff(cli);
 
        if (NT_STATUS_IS_OK(nt_status)) {
-               struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
-               if (pass) {
-                       nt_status = make_server_info_pw(server_info, pass);
-               } else {
-                       auth_add_user_script(user_info->domain.str, user_info->internal_username.str);
-                       pass = Get_Pwnam(user_info->internal_username.str);
+               fstring real_username;
+               struct passwd *pass;
 
-                       if (pass) {
-                               nt_status = make_server_info_pw(server_info, pass);
-                       } else {
-                               nt_status = NT_STATUS_NO_SUCH_USER;
-                       }
+               if ( (pass = smb_getpwnam( user_info->internal_username.str, 
+                       real_username, True )) != NULL ) 
+               {
+                       nt_status = make_server_info_pw(server_info, pass->pw_name, pass);
+               }
+               else
+               {
+                       nt_status = NT_STATUS_NO_SUCH_USER;
                }
        }
 
index b9de6f7acbdcbaf0044779aa6f07727b40bfc6cd..f744cba0c434e53c754eee80a8bfcf304590f8d8 100644 (file)
@@ -108,7 +108,7 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context,
 
        if (NT_STATUS_IS_OK(nt_status)) {
                if (pass) {
-                       make_server_info_pw(server_info, pass);
+                       make_server_info_pw(server_info, pass->pw_name, pass);
                } else {
                        /* we need to do somthing more useful here */
                        nt_status = NT_STATUS_NO_SUCH_USER;
index 0f945b33cb3be9cf458cf2d31ae0c8eb997f50a1..dfc3f6cc210e002facfcbbc3df32833a5c202779 100644 (file)
@@ -757,6 +757,7 @@ Fill a server_info struct from a SAM_ACCOUNT with their groups
 ***************************************************************************/
 
 static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, 
+                               const char * unix_username,
                                SAM_ACCOUNT *sampass,
                                uid_t uid, gid_t gid)
 {
@@ -770,7 +771,7 @@ static NTSTATUS add_user_groups(auth_serversupplied_info **server_info,
        BOOL is_guest;
        uint32 rid;
 
-       nt_status = get_user_groups(pdb_get_username(sampass), uid, gid, 
+       nt_status = get_user_groups(unix_username, uid, gid, 
                &n_groupSIDs, &groupSIDs, &unix_groups);
                
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -828,9 +829,11 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
        
        passwd_free(&pwd);
 
-       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, sampass, 
+       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, pdb_get_username(sampass), 
+                                                        sampass,
                                                         (*server_info)->uid, 
-                                                        (*server_info)->gid))) {
+                                                        (*server_info)->gid))) 
+       {
                free_server_info(server_info);
                return nt_status;
        }
@@ -848,7 +851,9 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
  to a SAM_ACCOUNT
 ***************************************************************************/
 
-NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd)
+NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, 
+                             char *unix_username,
+                            struct passwd *pwd)
 {
        NTSTATUS nt_status;
        SAM_ACCOUNT *sampass = NULL;
@@ -861,11 +866,13 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, const struc
 
        (*server_info)->sam_account    = sampass;
 
-       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, sampass, pwd->pw_uid, pwd->pw_gid))) {
+       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
+               sampass, pwd->pw_uid, pwd->pw_gid))) 
+       {
                return nt_status;
        }
 
-       (*server_info)->unix_name = smb_xstrdup(pwd->pw_name);
+       (*server_info)->unix_name = smb_xstrdup(unix_username);
 
        (*server_info)->sam_fill_level = SAM_FILL_ALL;
        (*server_info)->uid = pwd->pw_uid;
@@ -924,52 +931,30 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
                                 SAM_ACCOUNT **sam_account)
 {
        fstring dom_user;
+       fstring real_username;
        struct passwd *passwd;
 
        fstr_sprintf(dom_user, "%s%s%s", domain, lp_winbind_separator(), 
                username);
 
-       passwd = Get_Pwnam(dom_user);
-       
-       if ( passwd ) {
-               char *p;
-               
-               /* make sure we get the case of the username correct */
-               /* work around 'winbind use default domain = yes' */
-               
-               p = strchr( passwd->pw_name, *lp_winbind_separator() );
-               if ( !p ) 
-                       fstr_sprintf(dom_user, "%s%s%s", domain, 
-                               lp_winbind_separator(), passwd->pw_name);
-               else 
-                       fstrcpy( dom_user, passwd->pw_name );
-       }
-       else {
-               /* if the lookup for DOMAIN\username failed, try again 
-                  with just 'username'.  This is need for accessing the server
-                  as a trust user that actually maps to a local account */
-
-               fstrcpy( dom_user, username );
-               passwd = Get_Pwnam( dom_user );
-               
-               /* make sure we get the case of the username correct */
-               if ( passwd )
-                       fstrcpy( dom_user, passwd->pw_name );
-       }
+       /* get the passwd struct but don't create the user if he/she 
+          does not exist.  We were explicitly called from a following
+          a winbindd authentication request so we should assume that 
+          nss_winbindd is working */
 
-       if ( !passwd )
+       if ( !(passwd = smb_getpwnam( dom_user, real_username, True )) )
                return NT_STATUS_NO_SUCH_USER;
 
        *uid = passwd->pw_uid;
        *gid = passwd->pw_gid;
 
-       /* This is pointless -- there is no suport for differeing 
+       /* This is pointless -- there is no suport for differing 
           unix and windows names.  Make sure to always store the 
           one we actually looked up and succeeded. Have I mentioned
           why I hate the 'winbind use default domain' parameter?   
                                         --jerry              */
           
-       *found_username = talloc_strdup(mem_ctx, dom_user);
+       *found_username = talloc_strdup( mem_ctx, real_username );
        
        DEBUG(5,("fill_sam_account: located username was [%s]\n",
                *found_username));
@@ -983,40 +968,72 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
  the username if we fallback to the username only.
  ****************************************************************************/
  
-struct passwd *smb_getpwnam( char *domuser )
+struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
 {
        struct passwd *pw = NULL;
        char *p;
        fstring mapped_username;
+       
+       /* we only save a copy of the username it has been mangled 
+          by winbindd use default domain */
+          
+       save_username[0] = '\0';
+       
+       /* save a local copy of the username and run it through the 
+          username map */
+          
+       fstrcpy( mapped_username, domuser );
+       map_username( mapped_username );        
+       
+       p = strchr_m( mapped_username, *lp_winbind_separator() );
+       
+       /* code for a DOMAIN\user string */
+       
+       if ( p ) {
+               pw = Get_Pwnam( domuser );
+               if ( pw ) {     
+                       /* make sure we get the case of the username correct */
+                       /* work around 'winbind use default domain = yes' */
 
-       pw = Get_Pwnam( domuser );
-       if ( pw )
-               return pw;
-
-       /* fallback to looking up just the username */
+                       if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
+                               char *domain;
+                               
+                               domain = mapped_username;
+                               *p = '\0';
+                               fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
+                       }
+                       else
+                               fstrcpy( save_username, pw->pw_name );
 
-       p = strchr( domuser, *lp_winbind_separator() );
+                       /* whew -- done! */             
+                       return pw;
+               }
 
-       if ( p ) {
-               p += 1;
+               /* setup for lookup of just the username */
+               p++;
                fstrcpy( mapped_username, p );
-               map_username( mapped_username );        
+
+       }
+       
+       /* just lookup a plain username */
+       
+       pw = Get_Pwnam(mapped_username);
+               
+       /* Create local user if requested. */
+       
+       if ( !pw && create ) {
+               /* Don't add a machine account. */
+               if (mapped_username[strlen(mapped_username)-1] == '$')
+                       return NULL;
+
+               auth_add_user_script(NULL, mapped_username);
                pw = Get_Pwnam(mapped_username);
-               if (!pw) {
-                       /* Don't add a machine account. */
-                       if (mapped_username[strlen(mapped_username)-1] == '$')
-                               return NULL;
-
-                       /* Create local user if requested. */
-                       p = strchr( mapped_username, *lp_winbind_separator() );
-                       if (p)
-                               p += 1;
-                       else
-                               p = mapped_username;
-                       auth_add_user_script(NULL, p);
-                       return Get_Pwnam(p);
-               }
        }
+       
+       /* one last check for a valid passwd struct */
+       
+       if ( pw )
+               fstrcpy( save_username, pw->pw_name );
 
        return pw;
 }
index c42a35e809c38831a7bab4cc75cb89f2b8f74c10..d91aa9472865b9a49e070c76a3cf7992b5def20c 100644 (file)
@@ -143,7 +143,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
        DATA_BLOB ticket;
        char *client, *p, *domain;
        fstring netbios_domain_name;
-       const struct passwd *pw;
+       struct passwd *pw;
        char *user;
        int sess_vuid;
        NTSTATUS ret;
@@ -154,6 +154,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
        uint8 tok_id[2];
        BOOL foreign = False;
        DATA_BLOB nullblob = data_blob(NULL, 0);
+       fstring real_username;
 
        ZERO_STRUCT(ticket);
        ZERO_STRUCT(auth_data);
@@ -239,7 +240,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
 
        asprintf(&user, "%s%c%s", domain, *lp_winbind_separator(), client);
        
-       pw = smb_getpwnam( user );
+       /* lookup the passwd struct, create a new user if necessary */
+
+       pw = smb_getpwnam( user, real_username, True );
        
        if (!pw) {
                DEBUG(1,("Username %s is invalid on this system\n",user));
@@ -251,10 +254,11 @@ static int reply_spnego_kerberos(connection_struct *conn,
 
        /* setup the string used by %U */
        
-       sub_set_smb_name(pw->pw_name);
+       sub_set_smb_name( real_username );
        reload_services(True);
        
-       if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
+       if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info, real_username, pw))) 
+       {
                DEBUG(1,("make_server_info_from_pw failed!\n"));
                SAFE_FREE(user);
                SAFE_FREE(client);