r21108: Send sys_notify_watch through the VFS, FAM is next
[ira/wip.git] / source3 / smbd / password.c
index e64455040090ef5f7e2b5a04b3e5ce29f1f76e91..38000e93f4b8ebaaff6395d9a8cf04fe90e9289f 100644 (file)
@@ -29,9 +29,6 @@ static user_struct *validated_users;
 static int next_vuid = VUID_OFFSET;
 static int num_validated_vuids;
 
-extern userdom_struct current_user_info;
-
-
 /****************************************************************************
  Check if a uid has been validated, and return an pointer to the user_struct
  if it has. NULL if not. vuid is biased by an offset. This allows us to
@@ -100,7 +97,7 @@ void invalidate_vuid(uint16 vuid)
        session_yield(vuser);
        SAFE_FREE(vuser->session_keystr);
 
-       talloc_free(vuser->server_info);
+       TALLOC_FREE(vuser->server_info);
 
        data_blob_free(&vuser->session_key);
 
@@ -111,7 +108,7 @@ void invalidate_vuid(uint16 vuid)
        conn_clear_vuid_cache(vuid);
 
        SAFE_FREE(vuser->groups);
-       talloc_free(vuser->nt_user_token);
+       TALLOC_FREE(vuser->nt_user_token);
        SAFE_FREE(vuser);
        num_validated_vuids--;
 }
@@ -155,10 +152,9 @@ int register_vuid(auth_serversupplied_info *server_info,
 {
        user_struct *vuser = NULL;
 
-       /* Ensure no vuid gets registered in share level security. */
+       /* Paranoia check. */
        if(lp_security() == SEC_SHARE) {
-               data_blob_free(&session_key);
-               return UID_FIELD_INVALID;
+               smb_panic("Tried to register uid in security=share\n");
        }
 
        /* Limit allowed vuids to 16bits - VUID_OFFSET. */
@@ -189,6 +185,11 @@ int register_vuid(auth_serversupplied_info *server_info,
        vuser->vuid = next_vuid;
 
        if (!server_info) {
+               /*
+                * This happens in an unfinished NTLMSSP session setup. We
+                * need to allocate a vuid between the first and second calls
+                * to NTLMSSP.
+                */
                next_vuid++;
                num_validated_vuids++;
                
@@ -215,7 +216,7 @@ int register_vuid(auth_serversupplied_info *server_info,
                                 "vuser->groups\n"));
                        data_blob_free(&session_key);
                        free(vuser);
-                       talloc_free(server_info);
+                       TALLOC_FREE(server_info);
                        return UID_FIELD_INVALID;
                }
        }
@@ -252,7 +253,7 @@ int register_vuid(auth_serversupplied_info *server_info,
                        if (passwd) {
                                vuser->unix_homedir =
                                        smb_xstrdup(passwd->pw_dir);
-                               talloc_free(passwd);
+                               TALLOC_FREE(passwd);
                        }
                }
                
@@ -280,7 +281,7 @@ int register_vuid(auth_serversupplied_info *server_info,
        } else {
                DEBUG(1, ("server_info does not contain a user_token - "
                          "cannot continue\n"));
-               talloc_free(server_info);
+               TALLOC_FREE(server_info);
                data_blob_free(&session_key);
                SAFE_FREE(vuser->homedir);
                SAFE_FREE(vuser->unix_homedir);
@@ -305,7 +306,7 @@ int register_vuid(auth_serversupplied_info *server_info,
                DEBUG(1, ("Failed to claim session for vuid=%d\n",
                          vuser->vuid));
                invalidate_vuid(vuser->vuid);
-               return -1;
+               return UID_FIELD_INVALID;
        }
 
        /* Register a home dir service for this user iff
@@ -383,7 +384,7 @@ void add_session_user(const char *user)
                                 "too large.\n"));
                        return;
                }
-               newlist = (char *)SMB_REALLOC(
+               newlist = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR(
                        session_userlist,
                        len_session_userlist + PSTRING_LEN );
                if( newlist == NULL ) {
@@ -401,6 +402,134 @@ void add_session_user(const char *user)
        safe_strcat(session_userlist,suser,len_session_userlist-1);
 }
 
+/****************************************************************************
+ Check if a user is in a netgroup user list. If at first we don't succeed,
+ try lower case.
+****************************************************************************/
+
+BOOL user_in_netgroup(const char *user, const char *ngname)
+{
+#ifdef HAVE_NETGROUP
+       static char *mydomain = NULL;
+       fstring lowercase_user;
+
+       if (mydomain == NULL)
+               yp_get_default_domain(&mydomain);
+
+       if(mydomain == NULL) {
+               DEBUG(5,("Unable to get default yp domain, let's try without specifying it\n"));
+       }
+
+       DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+               user, mydomain?mydomain:"(ANY)", ngname));
+
+       if (innetgr(ngname, NULL, user, mydomain)) {
+               DEBUG(5,("user_in_netgroup: Found\n"));
+               return (True);
+       } else {
+
+               /*
+                * Ok, innetgr is case sensitive. Try once more with lowercase
+                * just in case. Attempt to fix #703. JRA.
+                */
+
+               fstrcpy(lowercase_user, user);
+               strlower_m(lowercase_user);
+       
+               DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+                       lowercase_user, mydomain?mydomain:"(ANY)", ngname));
+
+               if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
+                       DEBUG(5,("user_in_netgroup: Found\n"));
+                       return (True);
+               }
+       }
+#endif /* HAVE_NETGROUP */
+       return False;
+}
+
+/****************************************************************************
+ Check if a user is in a user list - can check combinations of UNIX
+ and netgroup lists.
+****************************************************************************/
+
+BOOL user_in_list(const char *user,const char **list)
+{
+       if (!list || !*list)
+               return False;
+
+       DEBUG(10,("user_in_list: checking user %s in list\n", user));
+
+       while (*list) {
+
+               DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
+                         user, *list));
+
+               /*
+                * Check raw username.
+                */
+               if (strequal(user, *list))
+                       return(True);
+
+               /*
+                * Now check to see if any combination
+                * of UNIX and netgroups has been specified.
+                */
+
+               if(**list == '@') {
+                       /*
+                        * Old behaviour. Check netgroup list
+                        * followed by UNIX list.
+                        */
+                       if(user_in_netgroup(user, *list +1))
+                               return True;
+                       if(user_in_group(user, *list +1))
+                               return True;
+               } else if (**list == '+') {
+
+                       if((*(*list +1)) == '&') {
+                               /*
+                                * Search UNIX list followed by netgroup.
+                                */
+                               if(user_in_group(user, *list +2))
+                                       return True;
+                               if(user_in_netgroup(user, *list +2))
+                                       return True;
+
+                       } else {
+
+                               /*
+                                * Just search UNIX list.
+                                */
+
+                               if(user_in_group(user, *list +1))
+                                       return True;
+                       }
+
+               } else if (**list == '&') {
+
+                       if(*(*list +1) == '+') {
+                               /*
+                                * Search netgroup list followed by UNIX list.
+                                */
+                               if(user_in_netgroup(user, *list +2))
+                                       return True;
+                               if(user_in_group(user, *list +2))
+                                       return True;
+                       } else {
+                               /*
+                                * Just search netgroup list.
+                                */
+                               if(user_in_netgroup(user, *list +1))
+                                       return True;
+                       }
+               }
+    
+               list++;
+       }
+       return(False);
+}
+
 /****************************************************************************
  Check if a username is valid.
 ****************************************************************************/
@@ -417,9 +546,11 @@ static BOOL user_ok(const char *user, int snum)
                str_list_copy(&invalid, lp_invalid_users(snum));
                if (invalid &&
                    str_list_substitute(invalid, "%S", lp_servicename(snum))) {
-                       if ( invalid &&
-                            str_list_sub_basic(invalid,
-                                               current_user_info.smb_name) ) {
+
+                       /* This is used in sec=share only, so no current user
+                        * around to pass to str_list_sub_basic() */
+
+                       if ( invalid && str_list_sub_basic(invalid, "", "") ) {
                                ret = !user_in_list(user,
                                                    (const char **)invalid);
                        }
@@ -432,9 +563,11 @@ static BOOL user_ok(const char *user, int snum)
                str_list_copy(&valid, lp_valid_users(snum));
                if ( valid &&
                     str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
-                       if ( valid &&
-                            str_list_sub_basic(valid,
-                                               current_user_info.smb_name) ) {
+
+                       /* This is used in sec=share only, so no current user
+                        * around to pass to str_list_sub_basic() */
+
+                       if ( valid && str_list_sub_basic(valid, "", "") ) {
                                ret = user_in_list(user, (const char **)valid);
                        }
                }