LCOV - code coverage report
Current view: top level - source4/auth - unix_token.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 71 88 80.7 %
Date: 2021-09-23 10:06:22 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Deal with unix elements in the security token
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    Copyright (C) Andrew Bartlett 2011
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "auth/auth.h"
      25             : #include "libcli/wbclient/wbclient.h"
      26             : #include "param/param.h"
      27             : 
      28             : #undef DBGC_CLASS
      29             : #define DBGC_CLASS DBGC_AUTH
      30             : 
      31             : /*
      32             :   form a security_unix_token from the current security_token
      33             : */
      34       11177 : NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx,
      35             :                                       struct security_token *token,
      36             :                                       struct security_unix_token **sec)
      37             : {
      38             :         uint32_t s, g;
      39             :         NTSTATUS status;
      40             :         struct id_map *ids;
      41             :         bool match;
      42             : 
      43       11177 :         match = security_token_is_system(token);
      44       11177 :         if (match) {
      45             :                 /*
      46             :                  * SYSTEM user uid and gid is 0
      47             :                  */
      48             : 
      49         942 :                 *sec = talloc_zero(mem_ctx, struct security_unix_token);
      50         942 :                 if (*sec == NULL) {
      51           0 :                         return NT_STATUS_NO_MEMORY;
      52             :                 }
      53             : 
      54         942 :                 return NT_STATUS_OK;
      55             :         }
      56             : 
      57             :         /* we can't do unix security without a user and group */
      58       10235 :         if (token->num_sids < 2) {
      59           0 :                 return NT_STATUS_ACCESS_DENIED;
      60             :         }
      61             : 
      62       10235 :         *sec = talloc_zero(mem_ctx, struct security_unix_token);
      63       10235 :         if (*sec == NULL) {
      64           0 :                 return NT_STATUS_NO_MEMORY;
      65             :         }
      66             : 
      67       10235 :         ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids);
      68       10235 :         NT_STATUS_HAVE_NO_MEMORY(ids);
      69             : 
      70      132563 :         for (s=0; s < token->num_sids; s++) {
      71      122850 :                 ids[s].sid = &token->sids[s];
      72      122850 :                 ids[s].status = ID_UNKNOWN;
      73             :         }
      74             : 
      75       10235 :         status = wbc_sids_to_xids(ids, token->num_sids);
      76       10235 :         NT_STATUS_NOT_OK_RETURN(status);
      77             : 
      78       10235 :         g = token->num_sids;
      79       10235 :         if (ids[0].xid.type != ID_TYPE_BOTH) {
      80        7979 :                 g--;
      81             :         }
      82       10235 :         (*sec)->ngroups = g;
      83       10235 :         (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
      84       10235 :         NT_STATUS_HAVE_NO_MEMORY((*sec)->groups);
      85             : 
      86       10235 :         g=0;
      87       10235 :         if (ids[0].xid.type == ID_TYPE_BOTH) {
      88        2256 :                 (*sec)->uid = ids[0].xid.id;
      89        2256 :                 (*sec)->groups[g] = ids[0].xid.id;
      90        2256 :                 g++;
      91        7979 :         } else if (ids[0].xid.type == ID_TYPE_UID) {
      92        7979 :                 (*sec)->uid = ids[0].xid.id;
      93             :         } else {
      94             :                 struct dom_sid_buf buf;
      95           0 :                 DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID.  Conversion was returned as type %d, full token:\n",
      96             :                           dom_sid_str_buf(ids[0].sid, &buf),
      97             :                           (int)ids[0].xid.type));
      98           0 :                 security_token_debug(DBGC_AUTH, 0, token);
      99           0 :                 return NT_STATUS_INVALID_SID;
     100             :         }
     101             : 
     102       15359 :         if (ids[1].xid.type == ID_TYPE_BOTH ||
     103        7666 :             ids[1].xid.type == ID_TYPE_GID) {
     104       10235 :                 (*sec)->gid = ids[1].xid.id;
     105       10235 :                 (*sec)->groups[g] = ids[1].xid.id;
     106       10235 :                 g++;
     107             :         } else {
     108             :                 struct dom_sid_buf buf;
     109           0 :                 DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID.  Conversion was returned as type %d, full token:\n",
     110             :                           dom_sid_str_buf(ids[1].sid, &buf),
     111             :                           (int)ids[1].xid.type));
     112           0 :                 security_token_debug(DBGC_AUTH, 0, token);
     113           0 :                 return NT_STATUS_INVALID_SID;
     114             :         }
     115             : 
     116      188453 :         for (s=2; s < token->num_sids; s++) {
     117      102380 :                 if (ids[s].xid.type == ID_TYPE_BOTH ||
     118           0 :                     ids[s].xid.type == ID_TYPE_GID) {
     119      102380 :                         (*sec)->groups[g] = ids[s].xid.id;
     120      102380 :                         g++;
     121             :                 } else {
     122             :                         struct dom_sid_buf buf;
     123           0 :                         DEBUG(0, ("Unable to convert SID (%s) at index %u in user token to a GID.  Conversion was returned as type %d, full token:\n",
     124             :                                   dom_sid_str_buf(ids[s].sid, &buf),
     125             :                                   (unsigned int)s, (int)ids[s].xid.type));
     126           0 :                         security_token_debug(DBGC_AUTH, 0, token);
     127           0 :                         return NT_STATUS_INVALID_SID;
     128             :                 }
     129             :         }
     130             : 
     131       10235 :         DEBUG(5, ("Successfully converted security token to a unix token:"));
     132       10235 :         security_token_debug(0, 5, token);
     133       10235 :         TALLOC_FREE(ids);
     134             : 
     135       10235 :         return NT_STATUS_OK;
     136             : }
     137             : 
     138             : /*
     139             :  * Fill in the unix_info elements in a struct session_info
     140             :  */
     141        9946 : NTSTATUS fill_unix_info(struct loadparm_context *lp_ctx,
     142             :                         const char *original_user_name,
     143             :                         struct auth_session_info *session_info)
     144             : {
     145        9946 :         session_info->unix_info = talloc_zero(session_info,
     146             :                                               struct auth_user_info_unix);
     147        9946 :         NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info);
     148             : 
     149       19261 :         session_info->unix_info->unix_name =
     150       25608 :                 talloc_asprintf(session_info->unix_info,
     151        9946 :                                 "%s%s%s", session_info->info->domain_name,
     152             :                                 lpcfg_winbind_separator(lp_ctx),
     153        9946 :                                 session_info->info->account_name);
     154        9946 :         NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->unix_name);
     155             : 
     156        9946 :         if (original_user_name == NULL) {
     157         942 :                 original_user_name = session_info->unix_info->unix_name;
     158             :         }
     159             : 
     160       19261 :         session_info->unix_info->sanitized_username =
     161       15662 :                 talloc_alpha_strcpy(session_info->unix_info,
     162             :                                     original_user_name,
     163             :                                     ". _-$");
     164        9946 :         NT_STATUS_HAVE_NO_MEMORY(session_info->unix_info->sanitized_username);
     165             : 
     166        9946 :         return NT_STATUS_OK;
     167             : }
     168             : 
     169             : /*
     170             :   Fill in the auth_user_info_unix and auth_unix_token elements in a struct session_info
     171             : */
     172        9840 : NTSTATUS auth_session_info_fill_unix(struct loadparm_context *lp_ctx,
     173             :                                      const char *original_user_name,
     174             :                                      struct auth_session_info *session_info)
     175             : {
     176        9840 :         NTSTATUS status = NT_STATUS_OK;
     177             : 
     178        9840 :         status = security_token_to_unix_token(session_info,
     179             :                                               session_info->security_token,
     180             :                                               &session_info->unix_token);
     181        9840 :         if (!NT_STATUS_IS_OK(status)) {
     182           0 :                 return status;
     183             :         }
     184             : 
     185        9840 :         status = fill_unix_info(lp_ctx,
     186             :                                 original_user_name,
     187             :                                 session_info);
     188        9840 :         if (!NT_STATUS_IS_OK(status)) {
     189           0 :                 return status;
     190             :         }
     191             : 
     192        9840 :         return NT_STATUS_OK;
     193             : }
     194             : 
     195             : /*
     196             :  * Set the given auth_user_info_unix and auth_unix_token elements in a
     197             :  * struct session_info, similar auth_session_info_fill_unix().
     198             :  * Receives the uid and gid for the unix token as parameters and does
     199             :  * not query the unix token from winbind (via security_token_to_unix_token()).
     200             :  * This is useful to fill a user session info manually if winbind is not
     201             :  * available.
     202             :  */
     203         106 : NTSTATUS auth_session_info_set_unix(struct loadparm_context *lp_ctx,
     204             :                                     const char *original_user_name,
     205             :                                     int uid,
     206             :                                     int gid,
     207             :                                     struct auth_session_info *session_info)
     208             : {
     209             :         NTSTATUS status;
     210             : 
     211         106 :         session_info->unix_token = talloc_zero(session_info,
     212             :                                                struct security_unix_token);
     213         106 :         if (session_info->unix_token == NULL) {
     214           0 :                 return NT_STATUS_NO_MEMORY;
     215             :         }
     216             : 
     217         106 :         session_info->unix_token->uid = uid;
     218         106 :         session_info->unix_token->gid = gid;
     219             : 
     220         106 :         status = fill_unix_info(lp_ctx,
     221             :                                 original_user_name,
     222             :                                 session_info);
     223         106 :         if (!NT_STATUS_IS_OK(status)) {
     224           0 :                 return status;
     225             :         }
     226             : 
     227         106 :         return NT_STATUS_OK;
     228             : }

Generated by: LCOV version 1.13