s3-smbd: Added a change_to_user_by_session() function.
authorAndreas Schneider <asn@samba.org>
Tue, 5 Apr 2011 11:54:31 +0000 (13:54 +0200)
committerJeremy Allison <jra@samba.org>
Mon, 11 Apr 2011 20:10:21 +0000 (22:10 +0200)
Signed-off-by: Jeremy Allison <jra@samba.org>
source3/smbd/proto.h
source3/smbd/uid.c

index f4b2e5ef5945a7c8bb43df44da3f24550a83fd0a..75fc5f834198918cd976e41a11dc3b4bbbffc2a0 100644 (file)
@@ -1050,6 +1050,8 @@ void reply_transs2(struct smb_request *req);
 bool change_to_guest(void);
 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid);
 bool change_to_user(connection_struct *conn, uint16 vuid);
+bool change_to_user_by_session(connection_struct *conn,
+                              const struct auth_serversupplied_info *session_info);
 bool change_to_root_user(void);
 bool become_authenticated_pipe_user(struct pipes_struct *p);
 bool unbecome_authenticated_pipe_user(void);
index 7938cc447a533bd6069a77c9e2515812dc4bdc73..96c457482792f885902d04672a0929f433e6db5c 100644 (file)
@@ -231,104 +231,54 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
  stack, but modify the current_user entries.
 ****************************************************************************/
 
-bool change_to_user(connection_struct *conn, uint16 vuid)
+static bool change_to_user_internal(connection_struct *conn,
+                                   const struct auth_serversupplied_info *session_info,
+                                   uint16_t vuid)
 {
-       const struct auth_serversupplied_info *session_info = NULL;
-       user_struct *vuser;
        int snum;
        gid_t gid;
        uid_t uid;
        char group_c;
        int num_groups = 0;
        gid_t *group_list = NULL;
-
-       if (!conn) {
-               DEBUG(2,("change_to_user: Connection not open\n"));
-               return(False);
-       }
-
-       vuser = get_valid_user_struct(conn->sconn, vuid);
-
-       /*
-        * We need a separate check in security=share mode due to vuid
-        * always being UID_FIELD_INVALID. If we don't do this then
-        * in share mode security we are *always* changing uid's between
-        * SMB's - this hurts performance - Badly.
-        */
-
-       if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
-          (current_user.ut.uid == conn->session_info->utok.uid)) {
-               DEBUG(4,("change_to_user: Skipping user change - already "
-                        "user\n"));
-               return(True);
-       } else if ((current_user.conn == conn) && 
-                  (vuser != NULL) && (current_user.vuid == vuid) &&
-                  (current_user.ut.uid == vuser->session_info->utok.uid)) {
-               DEBUG(4,("change_to_user: Skipping user change - already "
-                        "user\n"));
-               return(True);
-       }
+       bool ok;
 
        snum = SNUM(conn);
 
-       session_info = vuser ? vuser->session_info : conn->session_info;
-
-       if (!session_info) {
-               /* Invalid vuid sent - even with security = share. */
-               DEBUG(2,("change_to_user: Invalid vuid %d used on "
-                        "share %s.\n",vuid, lp_servicename(snum) ));
-               return false;
-       }
-
-       if (!check_user_ok(conn, vuid, session_info, snum)) {
-               DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
+       ok = check_user_ok(conn, vuid, session_info, snum);
+       if (!ok) {
+               DEBUG(2,("SMB user %s (unix user %s) "
                         "not permitted access to share %s.\n",
                         session_info->sanitized_username,
-                        session_info->unix_name, vuid,
+                        session_info->unix_name,
                         lp_servicename(snum)));
                return false;
        }
 
-       /* security = share sets force_user. */
-       if (!conn->force_user && !vuser) {
-               DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
-                       "share %s.\n",vuid, lp_servicename(snum) ));
-               return False;
-       }
-
-       /*
-        * conn->session_info is now correctly set up with a copy we can mess
-        * with for force_group etc.
-        */
-
        uid = conn->session_info->utok.uid;
        gid = conn->session_info->utok.gid;
        num_groups = conn->session_info->utok.ngroups;
        group_list  = conn->session_info->utok.groups;
 
        /*
-        * See if we should force group for this service.
-        * If so this overrides any group set in the force
-        * user code.
+        * See if we should force group for this service. If so this overrides
+        * any group set in the force user code.
         */
-
        if((group_c = *lp_force_group(snum))) {
 
                SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
 
-               if(group_c == '+') {
+               if (group_c == '+') {
+                       int i;
 
                        /*
-                        * Only force group if the user is a member of
-                        * the service group. Check the group memberships for
-                        * this user (we already have this) to
-                        * see if we should force the group.
+                        * Only force group if the user is a member of the
+                        * service group. Check the group memberships for this
+                        * user (we already have this) to see if we should force
+                        * the group.
                         */
-
-                       int i;
                        for (i = 0; i < num_groups; i++) {
-                               if (group_list[i]
-                                   == conn->force_group_gid) {
+                               if (group_list[i] == conn->force_group_gid) {
                                        conn->session_info->utok.gid =
                                                conn->force_group_gid;
                                        gid = conn->force_group_gid;
@@ -345,22 +295,94 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
                }
        }
 
-       /* Now set current_user since we will immediately also call
-          set_sec_ctx() */
-
+       /*Set current_user since we will immediately also call set_sec_ctx() */
        current_user.ut.ngroups = num_groups;
        current_user.ut.groups  = group_list;
 
-       set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
+       set_sec_ctx(uid,
+                   gid,
+                   current_user.ut.ngroups,
+                   current_user.ut.groups,
                    conn->session_info->security_token);
 
        current_user.conn = conn;
        current_user.vuid = vuid;
 
-       DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
-                (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
+       DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
+                (int)getuid(),
+                (int)geteuid(),
+                (int)getgid(),
+                (int)getegid()));
 
-       return(True);
+       return true;
+}
+
+bool change_to_user(connection_struct *conn, uint16_t vuid)
+{
+       const struct auth_serversupplied_info *session_info = NULL;
+       user_struct *vuser;
+       int snum = SNUM(conn);
+
+       if (!conn) {
+               DEBUG(2,("Connection not open\n"));
+               return(False);
+       }
+
+       vuser = get_valid_user_struct(conn->sconn, vuid);
+
+       /*
+        * We need a separate check in security=share mode due to vuid
+        * always being UID_FIELD_INVALID. If we don't do this then
+        * in share mode security we are *always* changing uid's between
+        * SMB's - this hurts performance - Badly.
+        */
+
+       if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
+          (current_user.ut.uid == conn->session_info->utok.uid)) {
+               DEBUG(4,("Skipping user change - already "
+                        "user\n"));
+               return(True);
+       } else if ((current_user.conn == conn) &&
+                  (vuser != NULL) && (current_user.vuid == vuid) &&
+                  (current_user.ut.uid == vuser->session_info->utok.uid)) {
+               DEBUG(4,("Skipping user change - already "
+                        "user\n"));
+               return(True);
+       }
+
+       session_info = vuser ? vuser->session_info : conn->session_info;
+
+       if (session_info == NULL) {
+               /* Invalid vuid sent - even with security = share. */
+               DEBUG(2,("Invalid vuid %d used on "
+                        "share %s.\n", vuid, lp_servicename(snum) ));
+               return false;
+       }
+
+       /* security = share sets force_user. */
+       if (!conn->force_user && vuser == NULL) {
+               DEBUG(2,("Invalid vuid used %d in accessing "
+                       "share %s.\n", vuid, lp_servicename(snum) ));
+               return False;
+       }
+
+       return change_to_user_internal(conn, session_info, vuid);
+}
+
+bool change_to_user_by_session(connection_struct *conn,
+                              const struct auth_serversupplied_info *session_info)
+{
+       SMB_ASSERT(conn != NULL);
+       SMB_ASSERT(session_info != NULL);
+
+       if ((current_user.conn == conn) &&
+           (current_user.ut.uid == session_info->utok.uid)) {
+               DEBUG(7, ("Skipping user change - already user\n"));
+
+               return true;
+       }
+
+       return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
 }
 
 /****************************************************************************