LCOV - code coverage report
Current view: top level - source4/auth - session.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 112 164 68.3 %
Date: 2021-09-23 10:06:22 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Authentication utility functions
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Andrew Bartlett 2001-2010
       6             :    Copyright (C) Jeremy Allison 2000-2001
       7             :    Copyright (C) Rafal Szczesniak 2002
       8             :    Copyright (C) Stefan Metzmacher 2005
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             :    
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "auth/auth.h"
      26             : #include "auth/auth_sam.h"
      27             : #include "auth/credentials/credentials.h"
      28             : #include "auth/credentials/credentials_krb5.h"
      29             : #include "libcli/security/security.h"
      30             : #include "libcli/auth/libcli_auth.h"
      31             : #include "dsdb/samdb/samdb.h"
      32             : #include "auth/session_proto.h"
      33             : #include "system/kerberos.h"
      34             : #include <gssapi/gssapi.h>
      35             : #include "libcli/wbclient/wbclient.h"
      36             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_AUTH
      39             : 
      40           7 : _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx, 
      41             :                                             struct loadparm_context *lp_ctx)
      42             : {
      43             :         NTSTATUS nt_status;
      44           7 :         struct auth_session_info *session_info = NULL;
      45           7 :         nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
      46           7 :         if (!NT_STATUS_IS_OK(nt_status)) {
      47           0 :                 return NULL;
      48             :         }
      49           7 :         return session_info;
      50             : }
      51             : 
      52       73553 : _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
      53             :                                              struct loadparm_context *lp_ctx, /* Optional, if you don't want privilages */
      54             :                                              struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */
      55             :                                              struct auth_user_info_dc *user_info_dc,
      56             :                                              uint32_t session_info_flags,
      57             :                                              struct auth_session_info **_session_info)
      58             : {
      59             :         struct auth_session_info *session_info;
      60             :         NTSTATUS nt_status;
      61       73553 :         unsigned int i, num_sids = 0;
      62             : 
      63             :         const char *filter;
      64             : 
      65       73553 :         struct dom_sid *sids = NULL;
      66             :         const struct dom_sid *anonymous_sid, *system_sid;
      67             : 
      68       73553 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      69       73553 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
      70             : 
      71       73553 :         session_info = talloc_zero(tmp_ctx, struct auth_session_info);
      72       73553 :         if (session_info == NULL) {
      73           0 :                 TALLOC_FREE(tmp_ctx);
      74           0 :                 return NT_STATUS_NO_MEMORY;
      75             :         }
      76             : 
      77       73553 :         session_info->info = talloc_reference(session_info, user_info_dc->info);
      78             : 
      79       73553 :         session_info->torture = talloc_zero(session_info, struct auth_user_info_torture);
      80       73553 :         if (session_info->torture == NULL) {
      81           0 :                 TALLOC_FREE(tmp_ctx);
      82           0 :                 return NT_STATUS_NO_MEMORY;
      83             :         }
      84       73553 :         session_info->torture->num_dc_sids = user_info_dc->num_sids;
      85       73553 :         session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids);
      86       73553 :         if (session_info->torture->dc_sids == NULL) {
      87           0 :                 TALLOC_FREE(tmp_ctx);
      88           0 :                 return NT_STATUS_NO_MEMORY;
      89             :         }
      90             : 
      91             :         /* unless set otherwise, the session key is the user session
      92             :          * key from the auth subsystem */ 
      93       73553 :         session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length);
      94       73553 :         if (!session_info->session_key.data && session_info->session_key.length) {
      95           0 :                 if (session_info->session_key.data == NULL) {
      96           0 :                         TALLOC_FREE(tmp_ctx);
      97           0 :                         return NT_STATUS_NO_MEMORY;
      98             :                 }
      99             :         }
     100             : 
     101       73553 :         anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS);
     102       73553 :         if (anonymous_sid == NULL) {
     103           0 :                 TALLOC_FREE(tmp_ctx);
     104           0 :                 return NT_STATUS_NO_MEMORY;
     105             :         }
     106             : 
     107       73553 :         system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM);
     108       73553 :         if (system_sid == NULL) {
     109           0 :                 TALLOC_FREE(tmp_ctx);
     110           0 :                 return NT_STATUS_NO_MEMORY;
     111             :         }
     112             : 
     113       73553 :         sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids);
     114       73553 :         if (sids == NULL) {
     115           0 :                 TALLOC_FREE(tmp_ctx);
     116           0 :                 return NT_STATUS_NO_MEMORY;
     117             :         }
     118             : 
     119       73553 :         num_sids = user_info_dc->num_sids;
     120             : 
     121      334613 :         for (i=0; i < user_info_dc->num_sids; i++) {
     122      261060 :                 sids[i] = user_info_dc->sids[i];
     123             :         }
     124             : 
     125             :         /*
     126             :          * Finally add the "standard" sids.
     127             :          * The only difference between guest and "anonymous"
     128             :          * is the addition of Authenticated_Users.
     129             :          */
     130             : 
     131       73553 :         if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
     132       36867 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 2);
     133       36867 :                 if (sids == NULL) {
     134           0 :                         TALLOC_FREE(tmp_ctx);
     135           0 :                         return NT_STATUS_NO_MEMORY;
     136             :                 }
     137             : 
     138       36867 :                 sid_copy(&sids[num_sids], &global_sid_World);
     139       36867 :                 num_sids++;
     140             : 
     141       36867 :                 sid_copy(&sids[num_sids], &global_sid_Network);
     142       36867 :                 num_sids++;
     143             :         }
     144             : 
     145       73553 :         if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
     146       36914 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
     147       36914 :                 if (sids == NULL) {
     148           0 :                         TALLOC_FREE(tmp_ctx);
     149           0 :                         return NT_STATUS_NO_MEMORY;
     150             :                 }
     151             : 
     152       36914 :                 sid_copy(&sids[num_sids], &global_sid_Authenticated_Users);
     153       36914 :                 num_sids++;
     154             :         }
     155             : 
     156       73553 :         if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
     157        8001 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
     158        8001 :                 if (sids == NULL) {
     159           0 :                         TALLOC_FREE(tmp_ctx);
     160           0 :                         return NT_STATUS_NO_MEMORY;
     161             :                 }
     162             : 
     163        8001 :                 if (!dom_sid_parse(SID_NT_NTLM_AUTHENTICATION, &sids[num_sids])) {
     164           0 :                         TALLOC_FREE(tmp_ctx);
     165           0 :                         return NT_STATUS_INTERNAL_ERROR;
     166             :                 }
     167        8001 :                 num_sids++;
     168             :         }
     169             : 
     170             : 
     171       73553 :         if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(anonymous_sid, &sids[PRIMARY_USER_SID_INDEX])) {
     172             :                 /* Don't expand nested groups of system, anonymous etc*/
     173       41883 :         } else if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(system_sid, &sids[PRIMARY_USER_SID_INDEX])) {
     174             :                 /* Don't expand nested groups of system, anonymous etc*/
     175       36474 :         } else if (sam_ctx) {
     176       33875 :                 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
     177             :                                          GROUP_TYPE_BUILTIN_LOCAL_GROUP);
     178             : 
     179             :                 /* Search for each group in the token */
     180      772127 :                 for (i = 0; i < num_sids; i++) {
     181             :                         struct dom_sid_buf buf;
     182             :                         const char *sid_dn;
     183             :                         DATA_BLOB sid_blob;
     184             : 
     185      722080 :                         sid_dn = talloc_asprintf(
     186             :                                 tmp_ctx,
     187             :                                 "<SID=%s>",
     188      415940 :                                 dom_sid_str_buf(&sids[i], &buf));
     189      415940 :                         if (sid_dn == NULL) {
     190           0 :                                 TALLOC_FREE(tmp_ctx);
     191           0 :                                 return NT_STATUS_NO_MEMORY;
     192             :                         }
     193      415940 :                         sid_blob = data_blob_string_const(sid_dn);
     194             : 
     195             :                         /* This function takes in memberOf values and expands
     196             :                          * them, as long as they meet the filter - so only
     197             :                          * builtin groups
     198             :                          *
     199             :                          * We already have the SID in the token, so set
     200             :                          * 'only childs' flag to true */
     201      415940 :                         nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter,
     202             :                                                               tmp_ctx, &sids, &num_sids);
     203      415940 :                         if (!NT_STATUS_IS_OK(nt_status)) {
     204           0 :                                 talloc_free(tmp_ctx);
     205           0 :                                 return nt_status;
     206             :                         }
     207             :                 }
     208             :         }
     209             : 
     210       73553 :         nt_status = security_token_create(session_info,
     211             :                                           lp_ctx,
     212             :                                           num_sids,
     213             :                                           sids,
     214             :                                           session_info_flags,
     215             :                                           &session_info->security_token);
     216       73553 :         if (!NT_STATUS_IS_OK(nt_status)) {
     217           0 :                 TALLOC_FREE(tmp_ctx);
     218           0 :                 return nt_status;
     219             :         }
     220             : 
     221       73553 :         session_info->unique_session_token = GUID_random();
     222             : 
     223       73553 :         session_info->credentials = NULL;
     224             : 
     225       73553 :         talloc_steal(mem_ctx, session_info);
     226       73553 :         *_session_info = session_info;
     227       73553 :         talloc_free(tmp_ctx);
     228       73553 :         return NT_STATUS_OK;
     229             : }
     230             : 
     231             : 
     232             : /* Fill out the auth_session_info with a cli_credentials based on the
     233             :  * auth_session_info we were forwarded over named pipe forwarding.
     234             :  *
     235             :  * NOTE: The stucture members of session_info_transport are stolen
     236             :  * with talloc_move() into auth_session_info for long term use
     237             :  */
     238        7018 : struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
     239             :                                                            struct auth_session_info_transport *session_info_transport,
     240             :                                                            struct loadparm_context *lp_ctx,
     241             :                                                            const char **reason)
     242             : {
     243             :         struct auth_session_info *session_info;
     244        7018 :         session_info = talloc_steal(mem_ctx, session_info_transport->session_info);
     245             :         /*
     246             :          * This is to allow us to check the type of this pointer using
     247             :          * talloc_get_type()
     248             :          */
     249        7018 :         talloc_set_name(session_info, "struct auth_session_info");
     250             : #ifdef HAVE_GSS_IMPORT_CRED
     251        7018 :         if (session_info_transport->exported_gssapi_credentials.length) {
     252             :                 struct cli_credentials *creds;
     253             :                 OM_uint32 minor_status;
     254             :                 gss_buffer_desc cred_token;
     255             :                 gss_cred_id_t cred_handle;
     256             :                 const char *error_string;
     257             :                 int ret;
     258             :                 bool ok;
     259             : 
     260        1155 :                 DEBUG(10, ("Delegated credentials supplied by client\n"));
     261             : 
     262        1155 :                 cred_token.value = session_info_transport->exported_gssapi_credentials.data;
     263        1155 :                 cred_token.length = session_info_transport->exported_gssapi_credentials.length;
     264             : 
     265        1155 :                 ret = gss_import_cred(&minor_status,
     266             :                                       &cred_token,
     267             :                                       &cred_handle);
     268        1155 :                 if (ret != GSS_S_COMPLETE) {
     269           0 :                         *reason = "Internal error in gss_import_cred()";
     270           0 :                         return NULL;
     271             :                 }
     272             : 
     273        1155 :                 creds = cli_credentials_init(session_info);
     274        1155 :                 if (!creds) {
     275           0 :                         *reason = "Out of memory in cli_credentials_init()";
     276           0 :                         return NULL;
     277             :                 }
     278        1155 :                 session_info->credentials = creds;
     279             : 
     280        1155 :                 ok = cli_credentials_set_conf(creds, lp_ctx);
     281        1155 :                 if (!ok) {
     282           0 :                         *reason = "Failed to load smb.conf";
     283           0 :                         return NULL;
     284             :                 }
     285             : 
     286             :                 /* Just so we don't segfault trying to get at a username */
     287        1155 :                 cli_credentials_set_anonymous(creds);
     288             : 
     289        1155 :                 ret = cli_credentials_set_client_gss_creds(creds,
     290             :                                                            lp_ctx,
     291             :                                                            cred_handle,
     292             :                                                            CRED_SPECIFIED,
     293             :                                                            &error_string);
     294        1155 :                 if (ret) {
     295           0 :                         *reason = talloc_asprintf(mem_ctx,
     296             :                                                   "Failed to set pipe forwarded"
     297             :                                                   "creds: %s\n", error_string);
     298           0 :                         return NULL;
     299             :                 }
     300             : 
     301             :                 /* This credential handle isn't useful for password
     302             :                  * authentication, so ensure nobody tries to do that */
     303        1155 :                 cli_credentials_set_kerberos_state(creds,
     304             :                                                    CRED_USE_KERBEROS_REQUIRED,
     305             :                                                    CRED_SPECIFIED);
     306             : 
     307             :         }
     308             : #endif
     309        6388 :         return session_info;
     310             : }
     311             : 
     312             : 
     313             : /* Create a auth_session_info_transport from an auth_session_info.
     314             :  *
     315             :  * NOTE: Members of the auth_session_info_transport structure are
     316             :  * talloc_referenced() into this structure, and should not be changed.
     317             :  */
     318        1439 : NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
     319             :                                                   struct auth_session_info *session_info,
     320             :                                                   struct tevent_context *event_ctx,
     321             :                                                   struct loadparm_context *lp_ctx,
     322             :                                                   struct auth_session_info_transport **transport_out)
     323             : {
     324             : 
     325         996 :         struct auth_session_info_transport *session_info_transport
     326         443 :                 = talloc_zero(mem_ctx, struct auth_session_info_transport);
     327        1439 :         if (!session_info_transport) {
     328           0 :                 return NT_STATUS_NO_MEMORY;
     329             :         };
     330        1439 :         session_info_transport->session_info = talloc_reference(session_info_transport, session_info);
     331        1439 :         if (!session_info_transport->session_info) {
     332           0 :                 return NT_STATUS_NO_MEMORY;
     333             :         };
     334             : #ifdef HAVE_GSS_EXPORT_CRED
     335        1439 :         if (session_info->credentials) {
     336             :                 struct gssapi_creds_container *gcc;
     337             :                 OM_uint32 gret;
     338             :                 OM_uint32 minor_status;
     339             :                 gss_buffer_desc cred_token;
     340             :                 const char *error_string;
     341             :                 int ret;
     342             : 
     343        1305 :                 ret = cli_credentials_get_client_gss_creds(session_info->credentials,
     344             :                                                            event_ctx,
     345             :                                                            lp_ctx,
     346             :                                                            &gcc, &error_string);
     347        1305 :                 if (ret != 0) {
     348           0 :                         *transport_out = session_info_transport;
     349           0 :                         return NT_STATUS_OK;
     350             :                 }
     351             : 
     352        1305 :                 gret = gss_export_cred(&minor_status,
     353        1305 :                                        gcc->creds,
     354             :                                        &cred_token);
     355        1305 :                 if (gret != GSS_S_COMPLETE) {
     356           0 :                         return NT_STATUS_INTERNAL_ERROR;
     357             :                 }
     358             : 
     359        1305 :                 if (cred_token.length) {
     360             :                         session_info_transport->exported_gssapi_credentials
     361        1305 :                                 = data_blob_talloc(session_info_transport,
     362             :                                                    cred_token.value,
     363             :                                                    cred_token.length);
     364        1305 :                         gss_release_buffer(&minor_status, &cred_token);
     365        1305 :                         NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
     366             :                 }
     367             :         }
     368             : #endif
     369        1439 :         *transport_out = session_info_transport;
     370        1439 :         return NT_STATUS_OK;
     371             : }
     372             : 
     373             : 
     374             : /* Produce a session_info for an arbitary DN or principal in the local
     375             :  * DB, assuming the local DB holds all the groups
     376             :  *
     377             :  * Supply either a principal or a DN
     378             :  */
     379         158 : NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
     380             :                                             struct loadparm_context *lp_ctx,
     381             :                                             struct ldb_context *sam_ctx,
     382             :                                             const char *principal,
     383             :                                             struct ldb_dn *user_dn,
     384             :                                             uint32_t session_info_flags,
     385             :                                             struct auth_session_info **session_info)
     386             : {
     387             :         NTSTATUS nt_status;
     388             :         struct auth_user_info_dc *user_info_dc;
     389         158 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     390         158 :         if (!tmp_ctx) {
     391           0 :                 return NT_STATUS_NO_MEMORY;
     392             :         }
     393         158 :         nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
     394             :                                                       principal, user_dn,
     395             :                                                       &user_info_dc);
     396         158 :         if (!NT_STATUS_IS_OK(nt_status)) {
     397           0 :                 talloc_free(tmp_ctx);
     398           0 :                 return nt_status;
     399             :         }
     400             : 
     401         158 :         nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
     402             :                                                user_info_dc, session_info_flags,
     403             :                                                session_info);
     404             : 
     405         158 :         if (NT_STATUS_IS_OK(nt_status)) {
     406         158 :                 talloc_steal(mem_ctx, *session_info);
     407             :         }
     408         158 :         talloc_free(tmp_ctx);
     409         158 :         return nt_status;
     410             : }
     411             : 
     412             : /**
     413             :  * prints a struct auth_session_info security token to debug output.
     414             :  */
     415           0 : void auth_session_info_debug(int dbg_lev, 
     416             :                              const struct auth_session_info *session_info)
     417             : {
     418           0 :         if (!session_info) {
     419           0 :                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
     420           0 :                 return; 
     421             :         }
     422             : 
     423           0 :         security_token_debug(DBGC_AUTH, dbg_lev,
     424           0 :                              session_info->security_token);
     425             : }

Generated by: LCOV version 1.13