LCOV - code coverage report
Current view: top level - source3/smbd - share_access.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 79 103 76.7 %
Date: 2021-08-25 13:27:56 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Check access based on valid users, read list and friends
       4             :    Copyright (C) Volker Lendecke 2005
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "smbd/smbd.h"
      22             : #include "smbd/globals.h"
      23             : #include "../libcli/security/security.h"
      24             : #include "passdb/lookup_sid.h"
      25             : #include "auth.h"
      26             : 
      27             : /*
      28             :  * We dropped NIS support in 2021, but need to keep configs working.
      29             :  *
      30             :  * TODO FIXME: Remove me in future
      31             :  */
      32             : 
      33         433 : static bool do_group_checks(const char **name, const char **pattern)
      34             : {
      35         433 :         if ((*name)[0] == '@') {
      36          18 :                 *pattern = "+";
      37          18 :                 *name += 1;
      38          18 :                 return True;
      39             :         }
      40             : 
      41         415 :         if (((*name)[0] == '+') && ((*name)[1] == '&')) {
      42          12 :                 *pattern = "+";
      43          12 :                 *name += 2;
      44          12 :                 return True;
      45             :         }
      46             : 
      47         403 :         if ((*name)[0] == '+') {
      48          24 :                 *pattern = "+";
      49          24 :                 *name += 1;
      50          24 :                 return True;
      51             :         }
      52             : 
      53         379 :         if (((*name)[0] == '&') && ((*name)[1] == '+')) {
      54          12 :                 *pattern = "+";
      55          12 :                 *name += 2;
      56          12 :                 return True;
      57             :         }
      58             : 
      59         367 :         if ((*name)[0] == '&') {
      60           0 :                 *pattern = "+";
      61           0 :                 *name += 1;
      62           0 :                 return True;
      63             :         }
      64             : 
      65         367 :         return False;
      66             : }
      67             : 
      68         433 : static bool token_contains_name(TALLOC_CTX *mem_ctx,
      69             :                                 const char *username,
      70             :                                 const char *domain,
      71             :                                 const char *sharename,
      72             :                                 const struct security_token *token,
      73             :                                 const char *name)
      74             : {
      75             :         const char *prefix;
      76             :         struct dom_sid sid;
      77             :         enum lsa_SidType type;
      78             : 
      79         433 :         if (username != NULL) {
      80         433 :                 size_t domain_len = domain != NULL ? strlen(domain) : 0;
      81             : 
      82             :                 /* Check if username starts with domain name */
      83         433 :                 if (domain_len > 0) {
      84         433 :                         const char *sep = lp_winbind_separator();
      85         433 :                         int cmp = strncasecmp_m(username, domain, domain_len);
      86         433 :                         if (cmp == 0 && sep[0] == username[domain_len]) {
      87             :                                 /* Move after the winbind separator */
      88         148 :                                 domain_len += 1;
      89             :                         } else {
      90         285 :                                 domain_len = 0;
      91             :                         }
      92             :                 }
      93         433 :                 name = talloc_sub_basic(mem_ctx,
      94             :                                         username + domain_len,
      95             :                                         domain,
      96             :                                         name);
      97             :         }
      98         433 :         if (sharename != NULL) {
      99         337 :                 name = talloc_string_sub(mem_ctx, name, "%S", sharename);
     100             :         }
     101             : 
     102         433 :         if (name == NULL) {
     103             :                 /* This is too security sensitive, better panic than return a
     104             :                  * result that might be interpreted in a wrong way. */
     105           0 :                 smb_panic("substitutions failed");
     106             :         }
     107             : 
     108         433 :         if ( string_to_sid( &sid, name ) ) {
     109           0 :                 DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name));
     110           0 :                 return nt_token_check_sid( &sid, token );
     111             :         }
     112             : 
     113         433 :         if (!do_group_checks(&name, &prefix)) {
     114         367 :                 if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL,
     115             :                                  NULL, NULL, &sid, &type)) {
     116           0 :                         DEBUG(5, ("lookup_name %s failed\n", name));
     117           0 :                         return False;
     118             :                 }
     119         367 :                 if (type != SID_NAME_USER) {
     120           0 :                         DEBUG(5, ("%s is a %s, expected a user\n",
     121             :                                   name, sid_type_lookup(type)));
     122           0 :                         return False;
     123             :                 }
     124         367 :                 return nt_token_check_sid(&sid, token);
     125             :         }
     126             : 
     127          66 :         for (/* initialized above */ ; *prefix != '\0'; prefix++) {
     128          66 :                 if (*prefix == '+') {
     129          66 :                         if (!lookup_name_smbconf(mem_ctx, name,
     130             :                                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
     131             :                                          NULL, NULL, &sid, &type)) {
     132           0 :                                 DEBUG(5, ("lookup_name %s failed\n", name));
     133           0 :                                 return False;
     134             :                         }
     135          66 :                         if ((type != SID_NAME_DOM_GRP) &&
     136           0 :                             (type != SID_NAME_ALIAS) &&
     137           0 :                             (type != SID_NAME_WKN_GRP)) {
     138           0 :                                 DEBUG(5, ("%s is a %s, expected a group\n",
     139             :                                           name, sid_type_lookup(type)));
     140           0 :                                 return False;
     141             :                         }
     142          66 :                         if (nt_token_check_sid(&sid, token)) {
     143          66 :                                 return True;
     144             :                         }
     145           0 :                         continue;
     146             :                 }
     147           0 :                 if (*prefix == '&') {
     148           0 :                         continue;
     149             :                 }
     150           0 :                 smb_panic("got invalid prefix from do_groups_check");
     151             :         }
     152           0 :         return False;
     153             : }
     154             : 
     155             : /*
     156             :  * Check whether a user is contained in the list provided.
     157             :  *
     158             :  * Please note that the user name and share names passed in here mainly for
     159             :  * the substitution routines that expand the parameter values, the decision
     160             :  * whether a user is in the list is done after a lookup_name on the expanded
     161             :  * parameter value, solely based on comparing the SIDs in token.
     162             :  *
     163             :  * The other use is the netgroup check when using @group or &group.
     164             :  */
     165             : 
     166       43089 : bool token_contains_name_in_list(const char *username,
     167             :                                  const char *domain,
     168             :                                  const char *sharename,
     169             :                                  const struct security_token *token,
     170             :                                  const char **list)
     171             : {
     172       43089 :         if (list == NULL) {
     173       42141 :                 return False;
     174             :         }
     175         989 :         while (*list != NULL) {
     176         433 :                 TALLOC_CTX *frame = talloc_stackframe();
     177             :                 bool ret;
     178             : 
     179         433 :                 ret = token_contains_name(frame, username, domain, sharename,
     180             :                                           token, *list);
     181         433 :                 TALLOC_FREE(frame);
     182         433 :                 if (ret) {
     183         286 :                         return true;
     184             :                 }
     185         147 :                 list += 1;
     186             :         }
     187         135 :         return False;
     188             : }
     189             : 
     190             : /*
     191             :  * Check whether the user described by "token" has access to share snum.
     192             :  *
     193             :  * This looks at "invalid users" and "valid users".
     194             :  *
     195             :  * Please note that the user name and share names passed in here mainly for
     196             :  * the substitution routines that expand the parameter values, the decision
     197             :  * whether a user is in the list is done after a lookup_name on the expanded
     198             :  * parameter value, solely based on comparing the SIDs in token.
     199             :  *
     200             :  * The other use is the netgroup check when using @group or &group.
     201             :  */
     202             : 
     203      127299 : bool user_ok_token(const char *username, const char *domain,
     204             :                    const struct security_token *token, int snum)
     205             : {
     206      127299 :         const struct loadparm_substitution *lp_sub =
     207             :                 loadparm_s3_global_substitution();
     208             : 
     209      127299 :         if (lp_invalid_users(snum) != NULL) {
     210          64 :                 if (token_contains_name_in_list(username, domain,
     211          32 :                                                 lp_servicename(talloc_tos(), lp_sub, snum),
     212             :                                                 token,
     213             :                                                 lp_invalid_users(snum))) {
     214           8 :                         DEBUG(10, ("User %s in 'invalid users'\n", username));
     215           8 :                         return False;
     216             :                 }
     217             :         }
     218             : 
     219      127291 :         if (lp_valid_users(snum) != NULL) {
     220         538 :                 if (!token_contains_name_in_list(username, domain,
     221         269 :                                                  lp_servicename(talloc_tos(), lp_sub, snum),
     222             :                                                  token,
     223             :                                                  lp_valid_users(snum))) {
     224         103 :                         DEBUG(10, ("User %s not in 'valid users'\n",
     225             :                                    username));
     226         103 :                         return False;
     227             :                 }
     228             :         }
     229             : 
     230      127188 :         DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n",
     231             :                    lp_servicename(talloc_tos(), lp_sub, snum), username));
     232             : 
     233      125609 :         return True;
     234             : }
     235             : 
     236             : /*
     237             :  * Check whether the user described by "token" is restricted to read-only
     238             :  * access on share snum.
     239             :  *
     240             :  * This looks at "read list", "write list" and "read only".
     241             :  *
     242             :  * Please note that the user name and share names passed in here mainly for
     243             :  * the substitution routines that expand the parameter values, the decision
     244             :  * whether a user is in the list is done after a lookup_name on the expanded
     245             :  * parameter value, solely based on comparing the SIDs in token.
     246             :  *
     247             :  * The other use is the netgroup check when using @group or &group.
     248             :  */
     249             : 
     250       85266 : bool is_share_read_only_for_token(const char *username,
     251             :                                   const char *domain,
     252             :                                   const struct security_token *token,
     253             :                                   connection_struct *conn)
     254             : {
     255       85266 :         const struct loadparm_substitution *lp_sub =
     256             :                 loadparm_s3_global_substitution();
     257       85266 :         int snum = SNUM(conn);
     258       85266 :         bool result = conn->read_only;
     259             : 
     260       85266 :         if (lp_read_list(snum) != NULL) {
     261           0 :                 if (token_contains_name_in_list(username, domain,
     262           0 :                                                 lp_servicename(talloc_tos(), lp_sub, snum),
     263             :                                                 token,
     264             :                                                 lp_read_list(snum))) {
     265           0 :                         result = True;
     266             :                 }
     267             :         }
     268             : 
     269       85266 :         if (lp_write_list(snum) != NULL) {
     270          48 :                 if (token_contains_name_in_list(username, domain,
     271          24 :                                                 lp_servicename(talloc_tos(), lp_sub, snum),
     272             :                                                 token,
     273             :                                                 lp_write_list(snum))) {
     274          24 :                         result = False;
     275             :                 }
     276             :         }
     277             : 
     278       85266 :         DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
     279             :                   "%s\n", lp_servicename(talloc_tos(), lp_sub, snum),
     280             :                   result ? "read-only" : "read-write", username));
     281             : 
     282       85266 :         return result;
     283             : }

Generated by: LCOV version 1.13