Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/smbd/uid.c

    r596 r745  
    1919
    2020#include "includes.h"
     21#include "system/passwd.h"
     22#include "smbd/smbd.h"
    2123#include "smbd/globals.h"
     24#include "../librpc/gen_ndr/netlogon.h"
     25#include "libcli/security/security.h"
     26#include "passdb/lookup_sid.h"
     27#include "auth.h"
    2228
    2329/* what user is current? */
     
    3238        struct passwd *pass;
    3339
    34         pass = Get_Pwnam_alloc(talloc_autofree_context(), lp_guestaccount());
     40        pass = Get_Pwnam_alloc(talloc_tos(), lp_guestaccount());
    3541        if (!pass) {
    3642                return false;
     
    5460
    5561/****************************************************************************
    56  talloc free the conn->server_info if not used in the vuid cache.
    57 ****************************************************************************/
    58 
    59 static void free_conn_server_info_if_unused(connection_struct *conn)
     62 talloc free the conn->session_info if not used in the vuid cache.
     63****************************************************************************/
     64
     65static void free_conn_session_info_if_unused(connection_struct *conn)
    6066{
    6167        unsigned int i;
     
    6571                ent = &conn->vuid_cache.array[i];
    6672                if (ent->vuid != UID_FIELD_INVALID &&
    67                                 conn->server_info == ent->server_info) {
     73                                conn->session_info == ent->session_info) {
    6874                        return;
    6975                }
    7076        }
    7177        /* Not used, safe to free. */
    72         TALLOC_FREE(conn->server_info);
     78        TALLOC_FREE(conn->session_info);
    7379}
    7480
     
    7682 Check if a username is OK.
    7783
    78  This sets up conn->server_info with a copy related to this vuser that
     84 This sets up conn->session_info with a copy related to this vuser that
    7985 later code can then mess with.
    8086********************************************************************/
     
    8288static bool check_user_ok(connection_struct *conn,
    8389                        uint16_t vuid,
    84                         const struct auth_serversupplied_info *server_info,
     90                        const struct auth_serversupplied_info *session_info,
    8591                        int snum)
    8692{
     
    96102                        ent = &conn->vuid_cache.array[i];
    97103                        if (ent->vuid == vuid) {
    98                                 free_conn_server_info_if_unused(conn);
    99                                 conn->server_info = ent->server_info;
     104                                free_conn_session_info_if_unused(conn);
     105                                conn->session_info = ent->session_info;
    100106                                conn->read_only = ent->read_only;
    101                                 conn->admin_user = ent->admin_user;
    102107                                return(True);
    103108                        }
     
    105110        }
    106111
    107         if (!user_ok_token(server_info->unix_name,
    108                            pdb_get_domain(server_info->sam_account),
    109                            server_info->ptok, snum))
     112        if (!user_ok_token(session_info->unix_name,
     113                           session_info->info3->base.domain.string,
     114                           session_info->security_token, snum))
    110115                return(False);
    111116
    112117        readonly_share = is_share_read_only_for_token(
    113                 server_info->unix_name,
    114                 pdb_get_domain(server_info->sam_account),
    115                 server_info->ptok,
     118                session_info->unix_name,
     119                session_info->info3->base.domain.string,
     120                session_info->security_token,
    116121                conn);
    117122
    118123        if (!readonly_share &&
    119             !share_access_check(server_info->ptok, lp_servicename(snum),
    120                                 FILE_WRITE_DATA)) {
     124            !share_access_check(session_info->security_token,
     125                                lp_servicename(snum), FILE_WRITE_DATA,
     126                                NULL)) {
    121127                /* smb.conf allows r/w, but the security descriptor denies
    122128                 * write. Fall back to looking at readonly. */
     
    126132        }
    127133
    128         if (!share_access_check(server_info->ptok, lp_servicename(snum),
     134        if (!share_access_check(session_info->security_token,
     135                                lp_servicename(snum),
    129136                                readonly_share ?
    130                                 FILE_READ_DATA : FILE_WRITE_DATA)) {
     137                                FILE_READ_DATA : FILE_WRITE_DATA,
     138                                NULL)) {
    131139                return False;
    132140        }
    133141
    134142        admin_user = token_contains_name_in_list(
    135                 server_info->unix_name,
    136                 pdb_get_domain(server_info->sam_account),
    137                 NULL, server_info->ptok, lp_admin_users(snum));
     143                session_info->unix_name,
     144                session_info->info3->base.domain.string,
     145                NULL, session_info->security_token, lp_admin_users(snum));
    138146
    139147        if (valid_vuid) {
     
    144152                        (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
    145153
    146                 TALLOC_FREE(ent->server_info);
     154                TALLOC_FREE(ent->session_info);
    147155
    148156                /*
    149                  * If force_user was set, all server_info's are based on the same
     157                 * If force_user was set, all session_info's are based on the same
    150158                 * username-based faked one.
    151159                 */
    152160
    153                 ent->server_info = copy_serverinfo(
    154                         conn, conn->force_user ? conn->server_info : server_info);
    155 
    156                 if (ent->server_info == NULL) {
     161                ent->session_info = copy_serverinfo(
     162                        conn, conn->force_user ? conn->session_info : session_info);
     163
     164                if (ent->session_info == NULL) {
    157165                        ent->vuid = UID_FIELD_INVALID;
    158166                        return false;
     
    161169                ent->vuid = vuid;
    162170                ent->read_only = readonly_share;
    163                 ent->admin_user = admin_user;
    164                 free_conn_server_info_if_unused(conn);
    165                 conn->server_info = ent->server_info;
     171                free_conn_session_info_if_unused(conn);
     172                conn->session_info = ent->session_info;
    166173        }
    167174
    168175        conn->read_only = readonly_share;
    169         conn->admin_user = admin_user;
     176        if (admin_user) {
     177                DEBUG(2,("check_user_ok: user %s is an admin user. "
     178                        "Setting uid as %d\n",
     179                        conn->session_info->unix_name,
     180                        sec_initial_uid() ));
     181                conn->session_info->utok.uid = sec_initial_uid();
     182        }
    170183
    171184        return(True);
     
    189202                        ent->vuid = UID_FIELD_INVALID;
    190203                        /*
    191                          * We need to keep conn->server_info around
    192                          * if it's equal to ent->server_info as a SMBulogoff
     204                         * We need to keep conn->session_info around
     205                         * if it's equal to ent->session_info as a SMBulogoff
    193206                         * is often followed by a SMBtdis (with an invalid
    194207                         * vuid). The debug code (or regular code in
    195208                         * vfs_full_audit) wants to refer to the
    196                          * conn->server_info pointer to print debug
     209                         * conn->session_info pointer to print debug
    197210                         * statements. Theoretically this is a bug,
    198                          * as once the vuid is gone the server_info
     211                         * as once the vuid is gone the session_info
    199212                         * on the conn struct isn't valid any more,
    200213                         * but there's enough code that assumes
    201                          * conn->server_info is never null that
     214                         * conn->session_info is never null that
    202215                         * it's easier to hold onto the old pointer
    203216                         * until we get a new sessionsetupX.
     
    206219                         * leaking memory here. See bug #6315. JRA.
    207220                         */
    208                         if (conn->server_info == ent->server_info) {
    209                                 ent->server_info = NULL;
     221                        if (conn->session_info == ent->session_info) {
     222                                ent->session_info = NULL;
    210223                        } else {
    211                                 TALLOC_FREE(ent->server_info);
     224                                TALLOC_FREE(ent->session_info);
    212225                        }
    213226                        ent->read_only = False;
    214                         ent->admin_user = False;
    215227                }
    216228        }
     
    222234****************************************************************************/
    223235
    224 bool change_to_user(connection_struct *conn, uint16 vuid)
    225 {
    226         const struct auth_serversupplied_info *server_info = NULL;
    227         struct smbd_server_connection *sconn = smbd_server_conn;
    228         user_struct *vuser = get_valid_user_struct(sconn, vuid);
     236static bool change_to_user_internal(connection_struct *conn,
     237                                    const struct auth_serversupplied_info *session_info,
     238                                    uint16_t vuid)
     239{
    229240        int snum;
    230241        gid_t gid;
     
    233244        int num_groups = 0;
    234245        gid_t *group_list = NULL;
     246        bool ok;
     247
     248        snum = SNUM(conn);
     249
     250        ok = check_user_ok(conn, vuid, session_info, snum);
     251        if (!ok) {
     252                DEBUG(2,("SMB user %s (unix user %s) "
     253                         "not permitted access to share %s.\n",
     254                         session_info->sanitized_username,
     255                         session_info->unix_name,
     256                         lp_servicename(snum)));
     257                return false;
     258        }
     259
     260        uid = conn->session_info->utok.uid;
     261        gid = conn->session_info->utok.gid;
     262        num_groups = conn->session_info->utok.ngroups;
     263        group_list  = conn->session_info->utok.groups;
     264
     265        /*
     266         * See if we should force group for this service. If so this overrides
     267         * any group set in the force user code.
     268         */
     269        if((group_c = *lp_force_group(snum))) {
     270
     271                SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
     272
     273                if (group_c == '+') {
     274                        int i;
     275
     276                        /*
     277                         * Only force group if the user is a member of the
     278                         * service group. Check the group memberships for this
     279                         * user (we already have this) to see if we should force
     280                         * the group.
     281                         */
     282                        for (i = 0; i < num_groups; i++) {
     283                                if (group_list[i] == conn->force_group_gid) {
     284                                        conn->session_info->utok.gid =
     285                                                conn->force_group_gid;
     286                                        gid = conn->force_group_gid;
     287                                        gid_to_sid(&conn->session_info->security_token
     288                                                   ->sids[1], gid);
     289                                        break;
     290                                }
     291                        }
     292                } else {
     293                        conn->session_info->utok.gid = conn->force_group_gid;
     294                        gid = conn->force_group_gid;
     295                        gid_to_sid(&conn->session_info->security_token->sids[1],
     296                                   gid);
     297                }
     298        }
     299
     300        /*Set current_user since we will immediately also call set_sec_ctx() */
     301        current_user.ut.ngroups = num_groups;
     302        current_user.ut.groups  = group_list;
     303
     304        set_sec_ctx(uid,
     305                    gid,
     306                    current_user.ut.ngroups,
     307                    current_user.ut.groups,
     308                    conn->session_info->security_token);
     309
     310        current_user.conn = conn;
     311        current_user.vuid = vuid;
     312
     313        DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
     314                 (int)getuid(),
     315                 (int)geteuid(),
     316                 (int)getgid(),
     317                 (int)getegid()));
     318
     319        return true;
     320}
     321
     322bool change_to_user(connection_struct *conn, uint16_t vuid)
     323{
     324        const struct auth_serversupplied_info *session_info = NULL;
     325        user_struct *vuser;
     326        int snum = SNUM(conn);
    235327
    236328        if (!conn) {
    237                 DEBUG(2,("change_to_user: Connection not open\n"));
     329                DEBUG(2,("Connection not open\n"));
    238330                return(False);
    239331        }
     332
     333        vuser = get_valid_user_struct(conn->sconn, vuid);
    240334
    241335        /*
     
    247341
    248342        if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
    249            (current_user.ut.uid == conn->server_info->utok.uid)) {
    250                 DEBUG(4,("change_to_user: Skipping user change - already "
     343           (current_user.ut.uid == conn->session_info->utok.uid)) {
     344                DEBUG(4,("Skipping user change - already "
    251345                         "user\n"));
    252346                return(True);
    253         } else if ((current_user.conn == conn) && 
     347        } else if ((current_user.conn == conn) &&
    254348                   (vuser != NULL) && (current_user.vuid == vuid) &&
    255                    (current_user.ut.uid == vuser->server_info->utok.uid)) {
    256                 DEBUG(4,("change_to_user: Skipping user change - already "
     349                   (current_user.ut.uid == vuser->session_info->utok.uid)) {
     350                DEBUG(4,("Skipping user change - already "
    257351                         "user\n"));
    258352                return(True);
    259353        }
    260354
    261         snum = SNUM(conn);
    262 
    263         server_info = vuser ? vuser->server_info : conn->server_info;
    264 
    265         if (!server_info) {
     355        session_info = vuser ? vuser->session_info : conn->session_info;
     356
     357        if (session_info == NULL) {
    266358                /* Invalid vuid sent - even with security = share. */
    267                 DEBUG(2,("change_to_user: Invalid vuid %d used on "
    268                          "share %s.\n",vuid, lp_servicename(snum) ));
     359                DEBUG(2,("Invalid vuid %d used on "
     360                         "share %s.\n", vuid, lp_servicename(snum) ));
    269361                return false;
    270362        }
    271363
    272         if (!check_user_ok(conn, vuid, server_info, snum)) {
    273                 DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
    274                          "not permitted access to share %s.\n",
    275                          server_info->sanitized_username,
    276                          server_info->unix_name, vuid,
    277                          lp_servicename(snum)));
    278                 return false;
    279         }
    280 
    281         /*
    282          * conn->server_info is now correctly set up with a copy we can mess
    283          * with for force_group etc.
    284          */
    285 
    286         if (conn->force_user) /* security = share sets this too */ {
    287                 uid = conn->server_info->utok.uid;
    288                 gid = conn->server_info->utok.gid;
    289                 group_list = conn->server_info->utok.groups;
    290                 num_groups = conn->server_info->utok.ngroups;
    291         } else if (vuser) {
    292                 uid = conn->admin_user ? 0 : vuser->server_info->utok.uid;
    293                 gid = conn->server_info->utok.gid;
    294                 num_groups = conn->server_info->utok.ngroups;
    295                 group_list  = conn->server_info->utok.groups;
    296         } else {
    297                 DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
    298                          "share %s.\n",vuid, lp_servicename(snum) ));
     364        /* security = share sets force_user. */
     365        if (!conn->force_user && vuser == NULL) {
     366                DEBUG(2,("Invalid vuid used %d in accessing "
     367                        "share %s.\n", vuid, lp_servicename(snum) ));
    299368                return False;
    300369        }
    301370
    302         /*
    303          * See if we should force group for this service.
    304          * If so this overrides any group set in the force
    305          * user code.
    306          */
    307 
    308         if((group_c = *lp_force_group(snum))) {
    309 
    310                 SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
    311 
    312                 if(group_c == '+') {
    313 
    314                         /*
    315                          * Only force group if the user is a member of
    316                          * the service group. Check the group memberships for
    317                          * this user (we already have this) to
    318                          * see if we should force the group.
    319                          */
    320 
    321                         int i;
    322                         for (i = 0; i < num_groups; i++) {
    323                                 if (group_list[i]
    324                                     == conn->force_group_gid) {
    325                                         conn->server_info->utok.gid =
    326                                                 conn->force_group_gid;
    327                                         gid = conn->force_group_gid;
    328                                         gid_to_sid(&conn->server_info->ptok
    329                                                    ->user_sids[1], gid);
    330                                         break;
    331                                 }
    332                         }
    333                 } else {
    334                         conn->server_info->utok.gid = conn->force_group_gid;
    335                         gid = conn->force_group_gid;
    336                         gid_to_sid(&conn->server_info->ptok->user_sids[1],
    337                                    gid);
    338                 }
    339         }
    340 
    341         /* Now set current_user since we will immediately also call
    342            set_sec_ctx() */
    343 
    344         current_user.ut.ngroups = num_groups;
    345         current_user.ut.groups  = group_list;   
    346 
    347         set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
    348                     conn->server_info->ptok);
    349 
    350         current_user.conn = conn;
    351         current_user.vuid = vuid;
    352 
    353         DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
    354                  (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
    355 
    356         return(True);
     371        return change_to_user_internal(conn, session_info, vuid);
     372}
     373
     374bool change_to_user_by_session(connection_struct *conn,
     375                               const struct auth_serversupplied_info *session_info)
     376{
     377        SMB_ASSERT(conn != NULL);
     378        SMB_ASSERT(session_info != NULL);
     379
     380        if ((current_user.conn == conn) &&
     381            (current_user.ut.uid == session_info->utok.uid)) {
     382                DEBUG(7, ("Skipping user change - already user\n"));
     383
     384                return true;
     385        }
     386
     387        return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
    357388}
    358389
     
    381412****************************************************************************/
    382413
    383 bool become_authenticated_pipe_user(pipes_struct *p)
     414bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info)
    384415{
    385416        if (!push_sec_ctx())
    386417                return False;
    387418
    388         set_sec_ctx(p->server_info->utok.uid, p->server_info->utok.gid,
    389                     p->server_info->utok.ngroups, p->server_info->utok.groups,
    390                     p->server_info->ptok);
     419        set_sec_ctx(session_info->utok.uid, session_info->utok.gid,
     420                    session_info->utok.ngroups, session_info->utok.groups,
     421                    session_info->security_token);
    391422
    392423        return True;
     
    426457        ctx_p->vuid = current_user.vuid;
    427458
    428         DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
     459        DEBUG(4, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
    429460                (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
    430461
     
    500531}
    501532
     533bool become_user_by_session(connection_struct *conn,
     534                            const struct auth_serversupplied_info *session_info)
     535{
     536        if (!push_sec_ctx())
     537                return false;
     538
     539        push_conn_ctx();
     540
     541        if (!change_to_user_by_session(conn, session_info)) {
     542                pop_sec_ctx();
     543                pop_conn_ctx();
     544                return false;
     545        }
     546
     547        return true;
     548}
     549
    502550bool unbecome_user(void)
    503551{
     
    506554        return True;
    507555}
     556
     557/****************************************************************************
     558 Return the current user we are running effectively as on this connection.
     559 I'd like to make this return conn->session_info->utok.uid, but become_root()
     560 doesn't alter this value.
     561****************************************************************************/
     562
     563uid_t get_current_uid(connection_struct *conn)
     564{
     565        return current_user.ut.uid;
     566}
     567
     568/****************************************************************************
     569 Return the current group we are running effectively as on this connection.
     570 I'd like to make this return conn->session_info->utok.gid, but become_root()
     571 doesn't alter this value.
     572****************************************************************************/
     573
     574gid_t get_current_gid(connection_struct *conn)
     575{
     576        return current_user.ut.gid;
     577}
     578
     579/****************************************************************************
     580 Return the UNIX token we are running effectively as on this connection.
     581 I'd like to make this return &conn->session_info->utok, but become_root()
     582 doesn't alter this value.
     583****************************************************************************/
     584
     585const struct security_unix_token *get_current_utok(connection_struct *conn)
     586{
     587        return &current_user.ut;
     588}
     589
     590const struct security_token *get_current_nttok(connection_struct *conn)
     591{
     592        return current_user.nt_user_token;
     593}
     594
     595uint16_t get_current_vuid(connection_struct *conn)
     596{
     597        return current_user.vuid;
     598}
Note: See TracChangeset for help on using the changeset viewer.