Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/smbd/uid.c

    r740 r988  
    3838        struct passwd *pass;
    3939
    40         pass = Get_Pwnam_alloc(talloc_tos(), lp_guestaccount());
     40        pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
    4141        if (!pass) {
    4242                return false;
     
    6969        for (i = 0; i < VUID_CACHE_SIZE; i++) {
    7070                struct vuid_cache_entry *ent;
    71                 ent = &conn->vuid_cache.array[i];
     71                ent = &conn->vuid_cache->array[i];
    7272                if (ent->vuid != UID_FIELD_INVALID &&
    7373                                conn->session_info == ent->session_info) {
     
    7979}
    8080
     81/****************************************************************************
     82  Setup the share access mask for a connection.
     83****************************************************************************/
     84
     85static uint32_t create_share_access_mask(int snum,
     86                                bool readonly_share,
     87                                const struct security_token *token)
     88{
     89        uint32_t share_access = 0;
     90
     91        share_access_check(token,
     92                        lp_servicename(talloc_tos(), snum),
     93                        MAXIMUM_ALLOWED_ACCESS,
     94                        &share_access);
     95
     96        if (readonly_share) {
     97                share_access &=
     98                        ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
     99                          SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
     100                          SEC_DIR_DELETE_CHILD );
     101        }
     102
     103        if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
     104                share_access |= SEC_FLAG_SYSTEM_SECURITY;
     105        }
     106        if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
     107                share_access |= SEC_RIGHTS_PRIV_RESTORE;
     108        }
     109        if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
     110                share_access |= SEC_RIGHTS_PRIV_BACKUP;
     111        }
     112        if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
     113                share_access |= SEC_STD_WRITE_OWNER;
     114        }
     115
     116        return share_access;
     117}
     118
    81119/*******************************************************************
    82  Check if a username is OK.
    83 
    84  This sets up conn->session_info with a copy related to this vuser that
    85  later code can then mess with.
     120 Calculate access mask and if this user can access this share.
    86121********************************************************************/
    87122
    88 static bool check_user_ok(connection_struct *conn,
    89                         uint16_t vuid,
    90                         const struct auth_serversupplied_info *session_info,
    91                         int snum)
    92 {
    93         bool valid_vuid = (vuid != UID_FIELD_INVALID);
    94         unsigned int i;
    95         bool readonly_share;
    96         bool admin_user;
    97 
    98         if (valid_vuid) {
    99                 struct vuid_cache_entry *ent;
    100 
    101                 for (i=0; i<VUID_CACHE_SIZE; i++) {
    102                         ent = &conn->vuid_cache.array[i];
    103                         if (ent->vuid == vuid) {
    104                                 free_conn_session_info_if_unused(conn);
    105                                 conn->session_info = ent->session_info;
    106                                 conn->read_only = ent->read_only;
    107                                 return(True);
    108                         }
    109                 }
    110         }
    111 
    112         if (!user_ok_token(session_info->unix_name,
    113                            session_info->info3->base.domain.string,
    114                            session_info->security_token, snum))
    115                 return(False);
     123NTSTATUS check_user_share_access(connection_struct *conn,
     124                                const struct auth_session_info *session_info,
     125                                uint32_t *p_share_access,
     126                                bool *p_readonly_share)
     127{
     128        int snum = SNUM(conn);
     129        uint32_t share_access = 0;
     130        bool readonly_share = false;
     131
     132        if (!user_ok_token(session_info->unix_info->unix_name,
     133                           session_info->info->domain_name,
     134                           session_info->security_token, snum)) {
     135                return NT_STATUS_ACCESS_DENIED;
     136        }
    116137
    117138        readonly_share = is_share_read_only_for_token(
    118                 session_info->unix_name,
    119                 session_info->info3->base.domain.string,
     139                session_info->unix_info->unix_name,
     140                session_info->info->domain_name,
    120141                session_info->security_token,
    121142                conn);
    122143
     144        share_access = create_share_access_mask(snum,
     145                                        readonly_share,
     146                                        session_info->security_token);
     147
     148        if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) {
     149                /* No access, read or write. */
     150                DEBUG(3,("user %s connection to %s denied due to share "
     151                         "security descriptor.\n",
     152                         session_info->unix_info->unix_name,
     153                         lp_servicename(talloc_tos(), snum)));
     154                return NT_STATUS_ACCESS_DENIED;
     155        }
     156
    123157        if (!readonly_share &&
    124             !share_access_check(session_info->security_token,
    125                                 lp_servicename(snum), FILE_WRITE_DATA,
    126                                 NULL)) {
     158            !(share_access & FILE_WRITE_DATA)) {
    127159                /* smb.conf allows r/w, but the security descriptor denies
    128160                 * write. Fall back to looking at readonly. */
     
    132164        }
    133165
    134         if (!share_access_check(session_info->security_token,
    135                                 lp_servicename(snum),
    136                                 readonly_share ?
    137                                 FILE_READ_DATA : FILE_WRITE_DATA,
    138                                 NULL)) {
    139                 return False;
     166        *p_share_access = share_access;
     167        *p_readonly_share = readonly_share;
     168
     169        return NT_STATUS_OK;
     170}
     171
     172/*******************************************************************
     173 Check if a username is OK.
     174
     175 This sets up conn->session_info with a copy related to this vuser that
     176 later code can then mess with.
     177********************************************************************/
     178
     179static bool check_user_ok(connection_struct *conn,
     180                        uint64_t vuid,
     181                        const struct auth_session_info *session_info,
     182                        int snum)
     183{
     184        unsigned int i;
     185        bool readonly_share = false;
     186        bool admin_user = false;
     187        struct vuid_cache_entry *ent = NULL;
     188        uint32_t share_access = 0;
     189        NTSTATUS status;
     190
     191        for (i=0; i<VUID_CACHE_SIZE; i++) {
     192                ent = &conn->vuid_cache->array[i];
     193                if (ent->vuid == vuid) {
     194                        if (vuid == UID_FIELD_INVALID) {
     195                                /*
     196                                 * Slow path, we don't care
     197                                 * about the array traversal.
     198                                */
     199                                continue;
     200                        }
     201                        free_conn_session_info_if_unused(conn);
     202                        conn->session_info = ent->session_info;
     203                        conn->read_only = ent->read_only;
     204                        conn->share_access = ent->share_access;
     205                        return(True);
     206                }
     207        }
     208
     209        status = check_user_share_access(conn,
     210                                        session_info,
     211                                        &share_access,
     212                                        &readonly_share);
     213        if (!NT_STATUS_IS_OK(status)) {
     214                return false;
    140215        }
    141216
    142217        admin_user = token_contains_name_in_list(
    143                 session_info->unix_name,
    144                 session_info->info3->base.domain.string,
     218                session_info->unix_info->unix_name,
     219                session_info->info->domain_name,
    145220                NULL, session_info->security_token, lp_admin_users(snum));
    146221
    147         if (valid_vuid) {
    148                 struct vuid_cache_entry *ent =
    149                         &conn->vuid_cache.array[conn->vuid_cache.next_entry];
    150 
    151                 conn->vuid_cache.next_entry =
    152                         (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE;
    153 
    154                 TALLOC_FREE(ent->session_info);
    155 
     222        ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry];
     223
     224        conn->vuid_cache->next_entry =
     225                (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE;
     226
     227        TALLOC_FREE(ent->session_info);
     228
     229        /*
     230         * If force_user was set, all session_info's are based on the same
     231         * username-based faked one.
     232         */
     233
     234        ent->session_info = copy_session_info(
     235                conn, conn->force_user ? conn->session_info : session_info);
     236
     237        if (ent->session_info == NULL) {
     238                ent->vuid = UID_FIELD_INVALID;
     239                return false;
     240        }
     241
     242        /*
     243         * It's actually OK to call check_user_ok() with
     244         * vuid == UID_FIELD_INVALID as called from change_to_user_by_session().
     245         * All this will do is throw away one entry in the cache.
     246         */
     247
     248        ent->vuid = vuid;
     249        ent->read_only = readonly_share;
     250        ent->share_access = share_access;
     251        free_conn_session_info_if_unused(conn);
     252        conn->session_info = ent->session_info;
     253        if (vuid == UID_FIELD_INVALID) {
    156254                /*
    157                  * If force_user was set, all session_info's are based on the same
    158                  * username-based faked one.
     255                 * Not strictly needed, just make it really
     256                 * clear this entry is actually an unused one.
    159257                 */
    160 
    161                 ent->session_info = copy_serverinfo(
    162                         conn, conn->force_user ? conn->session_info : session_info);
    163 
    164                 if (ent->session_info == NULL) {
    165                         ent->vuid = UID_FIELD_INVALID;
    166                         return false;
    167                 }
    168 
    169                 ent->vuid = vuid;
    170                 ent->read_only = readonly_share;
    171                 free_conn_session_info_if_unused(conn);
    172                 conn->session_info = ent->session_info;
     258                ent->read_only = false;
     259                ent->share_access = 0;
     260                ent->session_info = NULL;
    173261        }
    174262
    175263        conn->read_only = readonly_share;
     264        conn->share_access = share_access;
     265
    176266        if (admin_user) {
    177267                DEBUG(2,("check_user_ok: user %s is an admin user. "
    178268                        "Setting uid as %d\n",
    179                         conn->session_info->unix_name,
     269                        conn->session_info->unix_info->unix_name,
    180270                        sec_initial_uid() ));
    181                 conn->session_info->utok.uid = sec_initial_uid();
     271                conn->session_info->unix_token->uid = sec_initial_uid();
    182272        }
    183273
    184274        return(True);
    185 }
    186 
    187 /****************************************************************************
    188  Clear a vuid out of the connection's vuid cache
    189  This is only called on SMBulogoff.
    190 ****************************************************************************/
    191 
    192 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
    193 {
    194         int i;
    195 
    196         for (i=0; i<VUID_CACHE_SIZE; i++) {
    197                 struct vuid_cache_entry *ent;
    198 
    199                 ent = &conn->vuid_cache.array[i];
    200 
    201                 if (ent->vuid == vuid) {
    202                         ent->vuid = UID_FIELD_INVALID;
    203                         /*
    204                          * We need to keep conn->session_info around
    205                          * if it's equal to ent->session_info as a SMBulogoff
    206                          * is often followed by a SMBtdis (with an invalid
    207                          * vuid). The debug code (or regular code in
    208                          * vfs_full_audit) wants to refer to the
    209                          * conn->session_info pointer to print debug
    210                          * statements. Theoretically this is a bug,
    211                          * as once the vuid is gone the session_info
    212                          * on the conn struct isn't valid any more,
    213                          * but there's enough code that assumes
    214                          * conn->session_info is never null that
    215                          * it's easier to hold onto the old pointer
    216                          * until we get a new sessionsetupX.
    217                          * As everything is hung off the
    218                          * conn pointer as a talloc context we're not
    219                          * leaking memory here. See bug #6315. JRA.
    220                          */
    221                         if (conn->session_info == ent->session_info) {
    222                                 ent->session_info = NULL;
    223                         } else {
    224                                 TALLOC_FREE(ent->session_info);
    225                         }
    226                         ent->read_only = False;
    227                 }
    228         }
    229275}
    230276
     
    235281
    236282static bool change_to_user_internal(connection_struct *conn,
    237                                     const struct auth_serversupplied_info *session_info,
    238                                     uint16_t vuid)
     283                                    const struct auth_session_info *session_info,
     284                                    uint64_t vuid)
    239285{
    240286        int snum;
     
    252298                DEBUG(2,("SMB user %s (unix user %s) "
    253299                         "not permitted access to share %s.\n",
    254                          session_info->sanitized_username,
    255                          session_info->unix_name,
    256                          lp_servicename(snum)));
     300                         session_info->unix_info->sanitized_username,
     301                         session_info->unix_info->unix_name,
     302                         lp_servicename(talloc_tos(), snum)));
    257303                return false;
    258304        }
    259305
    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;
     306        uid = conn->session_info->unix_token->uid;
     307        gid = conn->session_info->unix_token->gid;
     308        num_groups = conn->session_info->unix_token->ngroups;
     309        group_list  = conn->session_info->unix_token->groups;
    264310
    265311        /*
     
    267313         * any group set in the force user code.
    268314         */
    269         if((group_c = *lp_force_group(snum))) {
     315        if((group_c = *lp_force_group(talloc_tos(), snum))) {
    270316
    271317                SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
     
    282328                        for (i = 0; i < num_groups; i++) {
    283329                                if (group_list[i] == conn->force_group_gid) {
    284                                         conn->session_info->utok.gid =
     330                                        conn->session_info->unix_token->gid =
    285331                                                conn->force_group_gid;
    286332                                        gid = conn->force_group_gid;
     
    291337                        }
    292338                } else {
    293                         conn->session_info->utok.gid = conn->force_group_gid;
     339                        conn->session_info->unix_token->gid = conn->force_group_gid;
    294340                        gid = conn->force_group_gid;
    295341                        gid_to_sid(&conn->session_info->security_token->sids[1],
     
    320366}
    321367
    322 bool change_to_user(connection_struct *conn, uint16_t vuid)
    323 {
    324         const struct auth_serversupplied_info *session_info = NULL;
    325         user_struct *vuser;
     368bool change_to_user(connection_struct *conn, uint64_t vuid)
     369{
     370        struct user_struct *vuser;
    326371        int snum = SNUM(conn);
    327372
     
    333378        vuser = get_valid_user_struct(conn->sconn, vuid);
    334379
    335         /*
    336          * We need a separate check in security=share mode due to vuid
    337          * always being UID_FIELD_INVALID. If we don't do this then
    338          * in share mode security we are *always* changing uid's between
    339          * SMB's - this hurts performance - Badly.
    340          */
    341 
    342         if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
    343            (current_user.ut.uid == conn->session_info->utok.uid)) {
     380        if ((current_user.conn == conn) &&
     381                   (vuser != NULL) && (current_user.vuid == vuid) &&
     382                   (current_user.ut.uid == vuser->session_info->unix_token->uid)) {
    344383                DEBUG(4,("Skipping user change - already "
    345384                         "user\n"));
    346385                return(True);
    347         } else if ((current_user.conn == conn) &&
    348                    (vuser != NULL) && (current_user.vuid == vuid) &&
    349                    (current_user.ut.uid == vuser->session_info->utok.uid)) {
    350                 DEBUG(4,("Skipping user change - already "
    351                          "user\n"));
    352                 return(True);
    353         }
    354 
    355         session_info = vuser ? vuser->session_info : conn->session_info;
    356 
    357         if (session_info == NULL) {
    358                 /* Invalid vuid sent - even with security = share. */
    359                 DEBUG(2,("Invalid vuid %d used on "
    360                          "share %s.\n", vuid, lp_servicename(snum) ));
     386        }
     387
     388        if (vuser == NULL) {
     389                /* Invalid vuid sent */
     390                DEBUG(2,("Invalid vuid %llu used on share %s.\n",
     391                         (unsigned long long)vuid, lp_servicename(talloc_tos(),
     392                                                                  snum)));
    361393                return false;
    362394        }
    363395
    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) ));
    368                 return False;
    369         }
    370 
    371         return change_to_user_internal(conn, session_info, vuid);
    372 }
    373 
    374 bool change_to_user_by_session(connection_struct *conn,
    375                                const struct auth_serversupplied_info *session_info)
     396        return change_to_user_internal(conn, vuser->session_info, vuid);
     397}
     398
     399static bool change_to_user_by_session(connection_struct *conn,
     400                                      const struct auth_session_info *session_info)
    376401{
    377402        SMB_ASSERT(conn != NULL);
     
    379404
    380405        if ((current_user.conn == conn) &&
    381             (current_user.ut.uid == session_info->utok.uid)) {
     406            (current_user.ut.uid == session_info->unix_token->uid)) {
    382407                DEBUG(7, ("Skipping user change - already user\n"));
    383408
     
    393418****************************************************************************/
    394419
    395 bool change_to_root_user(void)
     420bool smbd_change_to_root_user(void)
    396421{
    397422        set_root_sec_ctx();
     
    412437****************************************************************************/
    413438
    414 bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info)
     439bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info)
    415440{
    416441        if (!push_sec_ctx())
    417442                return False;
    418443
    419         set_sec_ctx(session_info->utok.uid, session_info->utok.gid,
    420                     session_info->utok.ngroups, session_info->utok.groups,
     444        set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid,
     445                    session_info->unix_token->ngroups, session_info->unix_token->groups,
    421446                    session_info->security_token);
     447
     448        DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
     449                 (int)getuid(),
     450                 (int)geteuid(),
     451                 (int)getgid(),
     452                 (int)getegid()));
    422453
    423454        return True;
     
    431462****************************************************************************/
    432463
    433 bool unbecome_authenticated_pipe_user(void)
     464bool smbd_unbecome_authenticated_pipe_user(void)
    434465{
    435466        return pop_sec_ctx();
     
    457488        ctx_p->vuid = current_user.vuid;
    458489
    459         DEBUG(4, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
    460                 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
     490        DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
     491                (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx));
    461492
    462493        conn_ctx_stack_ndx++;
     
    489520****************************************************************************/
    490521
    491 void become_root(void)
     522void smbd_become_root(void)
    492523{
    493524         /*
     
    504535/* Unbecome the root user */
    505536
    506 void unbecome_root(void)
     537void smbd_unbecome_root(void)
    507538{
    508539        pop_sec_ctx();
     
    515546****************************************************************************/
    516547
    517 bool become_user(connection_struct *conn, uint16 vuid)
     548bool become_user(connection_struct *conn, uint64_t vuid)
    518549{
    519550        if (!push_sec_ctx())
     
    532563
    533564bool become_user_by_session(connection_struct *conn,
    534                             const struct auth_serversupplied_info *session_info)
     565                            const struct auth_session_info *session_info)
    535566{
    536567        if (!push_sec_ctx())
     
    557588/****************************************************************************
    558589 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()
     590 I'd like to make this return conn->session_info->unix_token->uid, but become_root()
    560591 doesn't alter this value.
    561592****************************************************************************/
     
    568599/****************************************************************************
    569600 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()
     601 I'd like to make this return conn->session_info->unix_token->gid, but become_root()
    571602 doesn't alter this value.
    572603****************************************************************************/
     
    579610/****************************************************************************
    580611 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()
     612 I'd like to make this return &conn->session_info->unix_token-> but become_root()
    582613 doesn't alter this value.
    583614****************************************************************************/
     
    588619}
    589620
     621/****************************************************************************
     622 Return the Windows token we are running effectively as on this connection.
     623 If this is currently a NULL token as we're inside become_root() - a temporary
     624 UNIX security override, then we search up the stack for the previous active
     625 token.
     626****************************************************************************/
     627
    590628const struct security_token *get_current_nttok(connection_struct *conn)
    591629{
    592         return current_user.nt_user_token;
    593 }
    594 
    595 uint16_t get_current_vuid(connection_struct *conn)
     630        if (current_user.nt_user_token) {
     631                return current_user.nt_user_token;
     632        }
     633        return sec_ctx_active_token();
     634}
     635
     636uint64_t get_current_vuid(connection_struct *conn)
    596637{
    597638        return current_user.vuid;
Note: See TracChangeset for help on using the changeset viewer.