LCOV - code coverage report
Current view: top level - source4/auth - session.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 113 165 68.5 %
Date: 2024-06-13 04:01:37 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       69408 : _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       69408 :         unsigned int i, num_sids = 0;
      62             : 
      63             :         const char *filter;
      64             : 
      65       69408 :         struct dom_sid *sids = NULL;
      66             :         const struct dom_sid *anonymous_sid, *system_sid;
      67             : 
      68       69408 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
      69       69408 :         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
      70             : 
      71       69408 :         session_info = talloc_zero(tmp_ctx, struct auth_session_info);
      72       69408 :         if (session_info == NULL) {
      73           0 :                 TALLOC_FREE(tmp_ctx);
      74           0 :                 return NT_STATUS_NO_MEMORY;
      75             :         }
      76             : 
      77       69408 :         session_info->info = talloc_reference(session_info, user_info_dc->info);
      78             : 
      79       69408 :         session_info->torture = talloc_zero(session_info, struct auth_user_info_torture);
      80       69408 :         if (session_info->torture == NULL) {
      81           0 :                 TALLOC_FREE(tmp_ctx);
      82           0 :                 return NT_STATUS_NO_MEMORY;
      83             :         }
      84       69408 :         session_info->torture->num_dc_sids = user_info_dc->num_sids;
      85       69408 :         session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids);
      86       69408 :         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       69408 :         session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length);
      94       69408 :         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       69408 :         anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS);
     102       69408 :         if (anonymous_sid == NULL) {
     103           0 :                 TALLOC_FREE(tmp_ctx);
     104           0 :                 return NT_STATUS_NO_MEMORY;
     105             :         }
     106             : 
     107       69408 :         system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM);
     108       69408 :         if (system_sid == NULL) {
     109           0 :                 TALLOC_FREE(tmp_ctx);
     110           0 :                 return NT_STATUS_NO_MEMORY;
     111             :         }
     112             : 
     113       69408 :         sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids);
     114       69408 :         if (sids == NULL) {
     115           0 :                 TALLOC_FREE(tmp_ctx);
     116           0 :                 return NT_STATUS_NO_MEMORY;
     117             :         }
     118             : 
     119       69408 :         num_sids = user_info_dc->num_sids;
     120             : 
     121      320057 :         for (i=0; i < user_info_dc->num_sids; i++) {
     122      250649 :                 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       69408 :         if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
     132       32703 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 2);
     133       32703 :                 if (sids == NULL) {
     134           0 :                         TALLOC_FREE(tmp_ctx);
     135           0 :                         return NT_STATUS_NO_MEMORY;
     136             :                 }
     137             : 
     138       32703 :                 sid_copy(&sids[num_sids], &global_sid_World);
     139       32703 :                 num_sids++;
     140             : 
     141       32703 :                 sid_copy(&sids[num_sids], &global_sid_Network);
     142       32703 :                 num_sids++;
     143             :         }
     144             : 
     145       69408 :         if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
     146       32786 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
     147       32786 :                 if (sids == NULL) {
     148           0 :                         TALLOC_FREE(tmp_ctx);
     149           0 :                         return NT_STATUS_NO_MEMORY;
     150             :                 }
     151             : 
     152       32786 :                 sid_copy(&sids[num_sids], &global_sid_Authenticated_Users);
     153       32786 :                 num_sids++;
     154             :         }
     155             : 
     156       69408 :         if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
     157        8883 :                 sids = talloc_realloc(tmp_ctx, sids, struct dom_sid, num_sids + 1);
     158        8883 :                 if (sids == NULL) {
     159           0 :                         TALLOC_FREE(tmp_ctx);
     160           0 :                         return NT_STATUS_NO_MEMORY;
     161             :                 }
     162             : 
     163        8883 :                 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        8883 :                 num_sids++;
     168             :         }
     169             : 
     170             : 
     171       69408 :         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       36880 :         } 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       32470 :         } else if (sam_ctx) {
     176       30845 :                 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      757076 :                 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      701852 :                         sid_dn = talloc_asprintf(
     186             :                                 tmp_ctx,
     187             :                                 "<SID=%s>",
     188      391271 :                                 dom_sid_str_buf(&sids[i], &buf));
     189      391271 :                         if (sid_dn == NULL) {
     190           0 :                                 TALLOC_FREE(tmp_ctx);
     191           0 :                                 return NT_STATUS_NO_MEMORY;
     192             :                         }
     193      391271 :                         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      391271 :                         nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter,
     202             :                                                               tmp_ctx, &sids, &num_sids);
     203      391271 :                         if (!NT_STATUS_IS_OK(nt_status)) {
     204           0 :                                 talloc_free(tmp_ctx);
     205           0 :                                 return nt_status;
     206             :                         }
     207             :                 }
     208             :         }
     209             : 
     210       69408 :         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       69408 :         if (!NT_STATUS_IS_OK(nt_status)) {
     217           0 :                 TALLOC_FREE(tmp_ctx);
     218           0 :                 return nt_status;
     219             :         }
     220             : 
     221       69408 :         session_info->unique_session_token = GUID_random();
     222             : 
     223       69408 :         session_info->credentials = NULL;
     224             : 
     225       69408 :         session_info->ticket_type = user_info_dc->ticket_type;
     226             : 
     227       69408 :         talloc_steal(mem_ctx, session_info);
     228       69408 :         *_session_info = session_info;
     229       69408 :         talloc_free(tmp_ctx);
     230       69408 :         return NT_STATUS_OK;
     231             : }
     232             : 
     233             : 
     234             : /* Fill out the auth_session_info with a cli_credentials based on the
     235             :  * auth_session_info we were forwarded over named pipe forwarding.
     236             :  *
     237             :  * NOTE: The stucture members of session_info_transport are stolen
     238             :  * with talloc_move() into auth_session_info for long term use
     239             :  */
     240        4923 : struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
     241             :                                                            struct auth_session_info_transport *session_info_transport,
     242             :                                                            struct loadparm_context *lp_ctx,
     243             :                                                            const char **reason)
     244             : {
     245             :         struct auth_session_info *session_info;
     246        4923 :         session_info = talloc_steal(mem_ctx, session_info_transport->session_info);
     247             :         /*
     248             :          * This is to allow us to check the type of this pointer using
     249             :          * talloc_get_type()
     250             :          */
     251        4923 :         talloc_set_name(session_info, "struct auth_session_info");
     252             : #ifdef HAVE_GSS_IMPORT_CRED
     253        4923 :         if (session_info_transport->exported_gssapi_credentials.length) {
     254             :                 struct cli_credentials *creds;
     255             :                 OM_uint32 minor_status;
     256             :                 gss_buffer_desc cred_token;
     257             :                 gss_cred_id_t cred_handle;
     258             :                 const char *error_string;
     259             :                 int ret;
     260             :                 bool ok;
     261             : 
     262        1103 :                 DEBUG(10, ("Delegated credentials supplied by client\n"));
     263             : 
     264        1103 :                 cred_token.value = session_info_transport->exported_gssapi_credentials.data;
     265        1103 :                 cred_token.length = session_info_transport->exported_gssapi_credentials.length;
     266             : 
     267        1103 :                 ret = gss_import_cred(&minor_status,
     268             :                                       &cred_token,
     269             :                                       &cred_handle);
     270        1103 :                 if (ret != GSS_S_COMPLETE) {
     271           0 :                         *reason = "Internal error in gss_import_cred()";
     272           0 :                         return NULL;
     273             :                 }
     274             : 
     275        1103 :                 creds = cli_credentials_init(session_info);
     276        1103 :                 if (!creds) {
     277           0 :                         *reason = "Out of memory in cli_credentials_init()";
     278           0 :                         return NULL;
     279             :                 }
     280        1103 :                 session_info->credentials = creds;
     281             : 
     282        1103 :                 ok = cli_credentials_set_conf(creds, lp_ctx);
     283        1103 :                 if (!ok) {
     284           0 :                         *reason = "Failed to load smb.conf";
     285           0 :                         return NULL;
     286             :                 }
     287             : 
     288             :                 /* Just so we don't segfault trying to get at a username */
     289        1103 :                 cli_credentials_set_anonymous(creds);
     290             : 
     291        1103 :                 ret = cli_credentials_set_client_gss_creds(creds,
     292             :                                                            lp_ctx,
     293             :                                                            cred_handle,
     294             :                                                            CRED_SPECIFIED,
     295             :                                                            &error_string);
     296        1103 :                 if (ret) {
     297           0 :                         *reason = talloc_asprintf(mem_ctx,
     298             :                                                   "Failed to set pipe forwarded"
     299             :                                                   "creds: %s\n", error_string);
     300           0 :                         return NULL;
     301             :                 }
     302             : 
     303             :                 /* This credential handle isn't useful for password
     304             :                  * authentication, so ensure nobody tries to do that */
     305        1103 :                 cli_credentials_set_kerberos_state(creds,
     306             :                                                    CRED_USE_KERBEROS_REQUIRED,
     307             :                                                    CRED_SPECIFIED);
     308             : 
     309             :         }
     310             : #endif
     311        4923 :         return session_info;
     312             : }
     313             : 
     314             : 
     315             : /* Create a auth_session_info_transport from an auth_session_info.
     316             :  *
     317             :  * NOTE: Members of the auth_session_info_transport structure are
     318             :  * talloc_referenced() into this structure, and should not be changed.
     319             :  */
     320        1390 : NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
     321             :                                                   struct auth_session_info *session_info,
     322             :                                                   struct tevent_context *event_ctx,
     323             :                                                   struct loadparm_context *lp_ctx,
     324             :                                                   struct auth_session_info_transport **transport_out)
     325             : {
     326             : 
     327         950 :         struct auth_session_info_transport *session_info_transport
     328         440 :                 = talloc_zero(mem_ctx, struct auth_session_info_transport);
     329        1390 :         if (!session_info_transport) {
     330           0 :                 return NT_STATUS_NO_MEMORY;
     331             :         };
     332        1390 :         session_info_transport->session_info = talloc_reference(session_info_transport, session_info);
     333        1390 :         if (!session_info_transport->session_info) {
     334           0 :                 return NT_STATUS_NO_MEMORY;
     335             :         };
     336             : #ifdef HAVE_GSS_EXPORT_CRED
     337        1390 :         if (session_info->credentials) {
     338             :                 struct gssapi_creds_container *gcc;
     339             :                 OM_uint32 gret;
     340             :                 OM_uint32 minor_status;
     341             :                 gss_buffer_desc cred_token;
     342             :                 const char *error_string;
     343             :                 int ret;
     344             : 
     345        1256 :                 ret = cli_credentials_get_client_gss_creds(session_info->credentials,
     346             :                                                            event_ctx,
     347             :                                                            lp_ctx,
     348             :                                                            &gcc, &error_string);
     349        1256 :                 if (ret != 0) {
     350           0 :                         *transport_out = session_info_transport;
     351           0 :                         return NT_STATUS_OK;
     352             :                 }
     353             : 
     354        1256 :                 gret = gss_export_cred(&minor_status,
     355        1256 :                                        gcc->creds,
     356             :                                        &cred_token);
     357        1256 :                 if (gret != GSS_S_COMPLETE) {
     358           0 :                         return NT_STATUS_INTERNAL_ERROR;
     359             :                 }
     360             : 
     361        1256 :                 if (cred_token.length) {
     362             :                         session_info_transport->exported_gssapi_credentials
     363        1256 :                                 = data_blob_talloc(session_info_transport,
     364             :                                                    cred_token.value,
     365             :                                                    cred_token.length);
     366        1256 :                         gss_release_buffer(&minor_status, &cred_token);
     367        1256 :                         NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
     368             :                 }
     369             :         }
     370             : #endif
     371        1390 :         *transport_out = session_info_transport;
     372        1390 :         return NT_STATUS_OK;
     373             : }
     374             : 
     375             : 
     376             : /* Produce a session_info for an arbitary DN or principal in the local
     377             :  * DB, assuming the local DB holds all the groups
     378             :  *
     379             :  * Supply either a principal or a DN
     380             :  */
     381         159 : NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
     382             :                                             struct loadparm_context *lp_ctx,
     383             :                                             struct ldb_context *sam_ctx,
     384             :                                             const char *principal,
     385             :                                             struct ldb_dn *user_dn,
     386             :                                             uint32_t session_info_flags,
     387             :                                             struct auth_session_info **session_info)
     388             : {
     389             :         NTSTATUS nt_status;
     390             :         struct auth_user_info_dc *user_info_dc;
     391         159 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     392         159 :         if (!tmp_ctx) {
     393           0 :                 return NT_STATUS_NO_MEMORY;
     394             :         }
     395         159 :         nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
     396             :                                                       principal, user_dn,
     397             :                                                       &user_info_dc);
     398         159 :         if (!NT_STATUS_IS_OK(nt_status)) {
     399           0 :                 talloc_free(tmp_ctx);
     400           0 :                 return nt_status;
     401             :         }
     402             : 
     403         159 :         nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
     404             :                                                user_info_dc, session_info_flags,
     405             :                                                session_info);
     406             : 
     407         159 :         if (NT_STATUS_IS_OK(nt_status)) {
     408         159 :                 talloc_steal(mem_ctx, *session_info);
     409             :         }
     410         159 :         talloc_free(tmp_ctx);
     411         159 :         return nt_status;
     412             : }
     413             : 
     414             : /**
     415             :  * prints a struct auth_session_info security token to debug output.
     416             :  */
     417           0 : void auth_session_info_debug(int dbg_lev, 
     418             :                              const struct auth_session_info *session_info)
     419             : {
     420           0 :         if (!session_info) {
     421           0 :                 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
     422           0 :                 return; 
     423             :         }
     424             : 
     425           0 :         security_token_debug(DBGC_AUTH, dbg_lev,
     426           0 :                              session_info->security_token);
     427             : }

Generated by: LCOV version 1.13