LCOV - code coverage report
Current view: top level - libcli/auth - schannel_state_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 220 280 78.6 %
Date: 2024-02-28 12:06:22 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    module to store/fetch session keys for the schannel server
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009
       8             :    Copyright (C) Guenther Deschner 2009
       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 "system/filesys.h"
      26             : #include "../lib/tdb/include/tdb.h"
      27             : #include "../lib/util/util_tdb.h"
      28             : #include "../lib/param/param.h"
      29             : #include "../libcli/auth/schannel.h"
      30             : #include "../librpc/gen_ndr/ndr_schannel.h"
      31             : #include "lib/dbwrap/dbwrap.h"
      32             : 
      33             : #define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
      34             : 
      35             : /******************************************************************************
      36             :  Open or create the schannel session store tdb.  Non-static so it can
      37             :  be called from parent processes to correctly handle TDB_CLEAR_IF_FIRST
      38             : *******************************************************************************/
      39             : 
      40       32350 : struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx,
      41             :                                                struct loadparm_context *lp_ctx)
      42             : {
      43       32350 :         struct db_context *db_sc = NULL;
      44       32350 :         char *fname = lpcfg_private_db_path(mem_ctx, lp_ctx, "schannel_store");
      45        3182 :         int hash_size, tdb_flags;
      46             : 
      47       32350 :         if (!fname) {
      48           0 :                 return NULL;
      49             :         }
      50             : 
      51       32350 :         hash_size = lpcfg_tdb_hash_size(lp_ctx, fname);
      52       32350 :         tdb_flags = lpcfg_tdb_flags(lp_ctx, TDB_CLEAR_IF_FIRST|TDB_NOSYNC);
      53             : 
      54       32350 :         db_sc = dbwrap_local_open(
      55             :                 mem_ctx,
      56             :                 fname,
      57             :                 hash_size,
      58             :                 tdb_flags,
      59             :                 O_RDWR|O_CREAT,
      60             :                 0600,
      61             :                 DBWRAP_LOCK_ORDER_NONE,
      62             :                 DBWRAP_FLAG_NONE);
      63             : 
      64       32350 :         if (!db_sc) {
      65           0 :                 DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n",
      66             :                          fname, strerror(errno)));
      67           0 :                 TALLOC_FREE(fname);
      68           0 :                 return NULL;
      69             :         }
      70             : 
      71       32350 :         TALLOC_FREE(fname);
      72             : 
      73       32350 :         return db_sc;
      74             : }
      75             : 
      76             : /********************************************************************
      77             :  ********************************************************************/
      78             : 
      79             : static
      80       12578 : NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc,
      81             :                                         TALLOC_CTX *mem_ctx,
      82             :                                         struct netlogon_creds_CredentialState *creds)
      83             : {
      84        1218 :         enum ndr_err_code ndr_err;
      85        1218 :         DATA_BLOB blob;
      86        1218 :         TDB_DATA value;
      87        1218 :         char *keystr;
      88        1218 :         char *name_upper;
      89        1218 :         NTSTATUS status;
      90             : 
      91       12578 :         if (strlen(creds->computer_name) > 15) {
      92             :                 /*
      93             :                  * We may want to check for a completely
      94             :                  * valid netbios name.
      95             :                  */
      96          18 :                 return STATUS_BUFFER_OVERFLOW;
      97             :         }
      98             : 
      99       12560 :         name_upper = strupper_talloc(mem_ctx, creds->computer_name);
     100       12560 :         if (!name_upper) {
     101           0 :                 return NT_STATUS_NO_MEMORY;
     102             :         }
     103             : 
     104       12560 :         keystr = talloc_asprintf(mem_ctx, "%s/%s",
     105             :                                  SECRETS_SCHANNEL_STATE, name_upper);
     106       12560 :         TALLOC_FREE(name_upper);
     107       12560 :         if (!keystr) {
     108           0 :                 return NT_STATUS_NO_MEMORY;
     109             :         }
     110             : 
     111       12560 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, creds,
     112             :                         (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
     113       12560 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     114           0 :                 talloc_free(keystr);
     115           0 :                 return ndr_map_error2ntstatus(ndr_err);
     116             :         }
     117             : 
     118       12560 :         value.dptr = blob.data;
     119       12560 :         value.dsize = blob.length;
     120             : 
     121       12560 :         status = dbwrap_store_bystring(db_sc, keystr, value, TDB_REPLACE);
     122       12560 :         if (!NT_STATUS_IS_OK(status)) {
     123           0 :                 DEBUG(0,("Unable to add %s to session key db - %s\n",
     124             :                          keystr, nt_errstr(status)));
     125           0 :                 talloc_free(keystr);
     126           0 :                 return status;
     127             :         }
     128             : 
     129       12560 :         DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
     130             :                 keystr));
     131             : 
     132       12560 :         if (DEBUGLEVEL >= 10) {
     133           0 :                 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
     134             :         }
     135             : 
     136       12560 :         talloc_free(keystr);
     137             : 
     138       12560 :         return NT_STATUS_OK;
     139             : }
     140             : 
     141             : /********************************************************************
     142             :  ********************************************************************/
     143             : 
     144             : static
     145       19661 : NTSTATUS schannel_fetch_session_key_tdb(struct db_context *db_sc,
     146             :                                         TALLOC_CTX *mem_ctx,
     147             :                                         const char *computer_name,
     148             :                                         struct netlogon_creds_CredentialState **pcreds)
     149             : {
     150        1823 :         NTSTATUS status;
     151        1823 :         TDB_DATA value;
     152        1823 :         enum ndr_err_code ndr_err;
     153        1823 :         DATA_BLOB blob;
     154       19661 :         struct netlogon_creds_CredentialState *creds = NULL;
     155       19661 :         char *keystr = NULL;
     156        1823 :         char *name_upper;
     157             : 
     158       19661 :         *pcreds = NULL;
     159             : 
     160       19661 :         name_upper = strupper_talloc(mem_ctx, computer_name);
     161       19661 :         if (!name_upper) {
     162           0 :                 return NT_STATUS_NO_MEMORY;
     163             :         }
     164             : 
     165       19661 :         keystr = talloc_asprintf(mem_ctx, "%s/%s",
     166             :                                  SECRETS_SCHANNEL_STATE, name_upper);
     167       19661 :         TALLOC_FREE(name_upper);
     168       19661 :         if (!keystr) {
     169           0 :                 return NT_STATUS_NO_MEMORY;
     170             :         }
     171             : 
     172       19661 :         status = dbwrap_fetch_bystring(db_sc, keystr, keystr, &value);
     173       19661 :         if (!NT_STATUS_IS_OK(status)) {
     174          18 :                 DEBUG(10,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
     175             :                         keystr ));
     176          18 :                 goto done;
     177             :         }
     178             : 
     179       19643 :         creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
     180       19643 :         if (!creds) {
     181           0 :                 status = NT_STATUS_NO_MEMORY;
     182           0 :                 goto done;
     183             :         }
     184             : 
     185       19643 :         blob = data_blob_const(value.dptr, value.dsize);
     186             : 
     187       19643 :         ndr_err = ndr_pull_struct_blob(&blob, creds, creds,
     188             :                         (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
     189       19643 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     190           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     191           0 :                 goto done;
     192             :         }
     193             : 
     194       19643 :         if (DEBUGLEVEL >= 10) {
     195           0 :                 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
     196             :         }
     197             : 
     198       19643 :         DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
     199             :                 keystr));
     200             : 
     201       17822 :         status = NT_STATUS_OK;
     202             : 
     203       19661 :  done:
     204             : 
     205       19661 :         talloc_free(keystr);
     206             : 
     207       19661 :         if (!NT_STATUS_IS_OK(status)) {
     208          18 :                 talloc_free(creds);
     209          18 :                 return status;
     210             :         }
     211             : 
     212       19643 :         *pcreds = creds;
     213             : 
     214       19643 :         return NT_STATUS_OK;
     215             : }
     216             : 
     217             : /******************************************************************************
     218             :  Wrapper around schannel_fetch_session_key_tdb()
     219             :  Note we must be root here.
     220             : *******************************************************************************/
     221             : 
     222        8694 : NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx,
     223             :                                   struct loadparm_context *lp_ctx,
     224             :                                   const char *computer_name,
     225             :                                   struct netlogon_creds_CredentialState **_creds)
     226             : {
     227         760 :         TALLOC_CTX *tmpctx;
     228         760 :         struct db_context *db_sc;
     229         760 :         struct netlogon_creds_CredentialState *creds;
     230         760 :         NTSTATUS status;
     231             : 
     232        8694 :         tmpctx = talloc_named(mem_ctx, 0, "schannel_get_creds_state");
     233        8694 :         if (!tmpctx) {
     234           0 :                 return NT_STATUS_NO_MEMORY;
     235             :         }
     236             : 
     237        8694 :         db_sc = open_schannel_session_store(tmpctx, lp_ctx);
     238        8694 :         if (!db_sc) {
     239           0 :                 TALLOC_FREE(tmpctx);
     240           0 :                 return NT_STATUS_ACCESS_DENIED;
     241             :         }
     242             : 
     243        8694 :         status = schannel_fetch_session_key_tdb(db_sc, tmpctx,
     244             :                                                 computer_name, &creds);
     245        8694 :         if (NT_STATUS_IS_OK(status)) {
     246        8694 :                 *_creds = talloc_steal(mem_ctx, creds);
     247        8694 :                 if (!*_creds) {
     248           0 :                         status = NT_STATUS_NO_MEMORY;
     249             :                 }
     250             :         }
     251             : 
     252        8694 :         talloc_free(tmpctx);
     253        8694 :         return status;
     254             : }
     255             : 
     256             : /******************************************************************************
     257             :  Wrapper around schannel_store_session_key_tdb()
     258             :  Note we must be root here.
     259             : *******************************************************************************/
     260             : 
     261        1629 : NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx,
     262             :                                    struct loadparm_context *lp_ctx,
     263             :                                    struct netlogon_creds_CredentialState *creds)
     264             : {
     265         157 :         TALLOC_CTX *tmpctx;
     266         157 :         struct db_context *db_sc;
     267         157 :         NTSTATUS status;
     268             : 
     269        1629 :         tmpctx = talloc_named(mem_ctx, 0, "schannel_save_creds_state");
     270        1629 :         if (!tmpctx) {
     271           0 :                 return NT_STATUS_NO_MEMORY;
     272             :         }
     273             : 
     274        1629 :         db_sc = open_schannel_session_store(tmpctx, lp_ctx);
     275        1629 :         if (!db_sc) {
     276           0 :                 status = NT_STATUS_ACCESS_DENIED;
     277           0 :                 goto fail;
     278             :         }
     279             : 
     280        1629 :         status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
     281             : 
     282        1629 : fail:
     283        1629 :         talloc_free(tmpctx);
     284        1629 :         return status;
     285             : }
     286             : 
     287             : 
     288             : /*
     289             :  * Create a very lossy hash of the computer name.
     290             :  *
     291             :  * The idea here is to compress the computer name into small space so
     292             :  * that malicious clients cannot fill the database with junk, as only a
     293             :  * maximum of 16k of entries are possible.
     294             :  *
     295             :  * Collisions are certainly possible, and the design behaves in the
     296             :  * same way as when the hostname is reused, but clients that use the
     297             :  * same connection do not go via the cache, and the cache only needs
     298             :  * to function between the ReqChallenge and ServerAuthenticate
     299             :  * packets.
     300             :  */
     301       11000 : static void hash_computer_name(const char *computer_name,
     302             :                                char keystr[16])
     303             : {
     304        1199 :         unsigned int hash;
     305       11000 :         TDB_DATA computer_tdb_data = {
     306             :                 .dptr = (uint8_t *)discard_const_p(char, computer_name),
     307       11000 :                 .dsize = strlen(computer_name)
     308             :         };
     309       11000 :         hash = tdb_jenkins_hash(&computer_tdb_data);
     310             : 
     311             :         /* we are using 14 bits of the digest to index our connections, so
     312             :            that we use at most 16,384 buckets.*/
     313       11000 :         snprintf(keystr, 15, "CHALLENGE/%x%x", hash & 0xFF,
     314             :                  (hash & 0xFF00 >> 8) & 0x3f);
     315       11000 :         return;
     316             : }
     317             : 
     318             : 
     319             : static
     320        9142 : NTSTATUS schannel_store_challenge_tdb(struct db_context *db_sc,
     321             :                                       TALLOC_CTX *mem_ctx,
     322             :                                       const struct netr_Credential *client_challenge,
     323             :                                       const struct netr_Credential *server_challenge,
     324             :                                       const char *computer_name)
     325             : {
     326        1001 :         enum ndr_err_code ndr_err;
     327        1001 :         DATA_BLOB blob;
     328        1001 :         TDB_DATA value;
     329        9142 :         char *name_upper = NULL;
     330        1001 :         NTSTATUS status;
     331        9142 :         char keystr[16] = { 0, };
     332        1001 :         struct netlogon_cache_entry cache_entry;
     333             : 
     334        9142 :         if (strlen(computer_name) > 255) {
     335             :                 /*
     336             :                  * We don't make this a limit at 15 chars as Samba has
     337             :                  * a test showing this can be longer :-(
     338             :                  */
     339           0 :                 return STATUS_BUFFER_OVERFLOW;
     340             :         }
     341             : 
     342        9142 :         name_upper = strupper_talloc(mem_ctx, computer_name);
     343        9142 :         if (name_upper == NULL) {
     344           0 :                 return NT_STATUS_NO_MEMORY;
     345             :         }
     346             : 
     347        9142 :         hash_computer_name(name_upper, keystr);
     348             : 
     349        9142 :         cache_entry.computer_name = name_upper;
     350        9142 :         cache_entry.client_challenge = *client_challenge;
     351        9142 :         cache_entry.server_challenge = *server_challenge;
     352             : 
     353        9142 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &cache_entry,
     354             :                                (ndr_push_flags_fn_t)ndr_push_netlogon_cache_entry);
     355        9142 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     356           0 :                 return NT_STATUS_UNSUCCESSFUL;
     357             :         }
     358             : 
     359        9142 :         value.dptr = blob.data;
     360        9142 :         value.dsize = blob.length;
     361             : 
     362        9142 :         status = dbwrap_store_bystring(db_sc, keystr, value, TDB_REPLACE);
     363        9142 :         if (!NT_STATUS_IS_OK(status)) {
     364           0 :                 DEBUG(0,("%s: failed to stored challenge info for '%s' "
     365             :                          "with key %s - %s\n",
     366             :                          __func__, cache_entry.computer_name, keystr,
     367             :                          nt_errstr(status)));
     368           0 :                 return status;
     369             :         }
     370             : 
     371        9142 :         DEBUG(3,("%s: stored challenge info for '%s' with key %s\n",
     372             :                 __func__, cache_entry.computer_name, keystr));
     373             : 
     374        9142 :         if (DEBUGLEVEL >= 10) {
     375           0 :                 NDR_PRINT_DEBUG(netlogon_cache_entry, &cache_entry);
     376             :         }
     377             : 
     378        9142 :         return NT_STATUS_OK;
     379             : }
     380             : 
     381             : /********************************************************************
     382             :  Fetch a single challenge from the TDB.
     383             :  ********************************************************************/
     384             : 
     385             : static
     386         144 : NTSTATUS schannel_fetch_challenge_tdb(struct db_context *db_sc,
     387             :                                       TALLOC_CTX *mem_ctx,
     388             :                                       struct netr_Credential *client_challenge,
     389             :                                       struct netr_Credential *server_challenge,
     390             :                                       const char *computer_name)
     391             : {
     392          24 :         NTSTATUS status;
     393          24 :         TDB_DATA value;
     394          24 :         enum ndr_err_code ndr_err;
     395          24 :         DATA_BLOB blob;
     396         144 :         char keystr[16] = { 0, };
     397          24 :         struct netlogon_cache_entry cache_entry;
     398         144 :         char *name_upper = NULL;
     399             : 
     400         144 :         name_upper = strupper_talloc(mem_ctx, computer_name);
     401         144 :         if (name_upper == NULL) {
     402           0 :                 return NT_STATUS_NO_MEMORY;
     403             :         }
     404             : 
     405         144 :         hash_computer_name(name_upper, keystr);
     406             : 
     407         144 :         status = dbwrap_fetch_bystring(db_sc, mem_ctx, keystr, &value);
     408         144 :         if (!NT_STATUS_IS_OK(status)) {
     409          72 :                 DEBUG(3,("%s: Failed to find entry for %s with key %s - %s\n",
     410             :                         __func__, name_upper, keystr, nt_errstr(status)));
     411          72 :                 goto done;
     412             :         }
     413             : 
     414          72 :         blob = data_blob_const(value.dptr, value.dsize);
     415             : 
     416          72 :         ndr_err = ndr_pull_struct_blob_all(&blob, mem_ctx, &cache_entry,
     417             :                                            (ndr_pull_flags_fn_t)ndr_pull_netlogon_cache_entry);
     418          72 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     419           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     420           0 :                 DEBUG(3,("%s: Failed to parse entry for %s with key %s - %s\n",
     421             :                         __func__, name_upper, keystr, nt_errstr(status)));
     422           0 :                 goto done;
     423             :         }
     424             : 
     425          72 :         if (DEBUGLEVEL >= 10) {
     426           0 :                 NDR_PRINT_DEBUG(netlogon_cache_entry, &cache_entry);
     427             :         }
     428             : 
     429          72 :         if (strcmp(cache_entry.computer_name, name_upper) != 0) {
     430           0 :                 status = NT_STATUS_NOT_FOUND;
     431             : 
     432           0 :                 DEBUG(1, ("%s: HASH COLLISION with key %s ! "
     433             :                           "Wanted to fetch record for %s but got %s.\n",
     434             :                           __func__, keystr, name_upper,
     435             :                           cache_entry.computer_name));
     436             :         } else {
     437             : 
     438          72 :                 DEBUG(3,("%s: restored key %s for %s\n",
     439             :                          __func__, keystr, cache_entry.computer_name));
     440             : 
     441          72 :                 *client_challenge = cache_entry.client_challenge;
     442          72 :                 *server_challenge = cache_entry.server_challenge;
     443             :         }
     444         144 :  done:
     445             : 
     446         144 :         if (!NT_STATUS_IS_OK(status)) {
     447          72 :                 return status;
     448             :         }
     449             : 
     450          72 :         return NT_STATUS_OK;
     451             : }
     452             : 
     453             : /******************************************************************************
     454             :  Wrapper around schannel_fetch_challenge_tdb()
     455             :  Note we must be root here.
     456             : 
     457             : *******************************************************************************/
     458             : 
     459         144 : NTSTATUS schannel_get_challenge(struct loadparm_context *lp_ctx,
     460             :                                 struct netr_Credential *client_challenge,
     461             :                                 struct netr_Credential *server_challenge,
     462             :                                 const char *computer_name)
     463             : {
     464         144 :         TALLOC_CTX *frame = talloc_stackframe();
     465          24 :         struct db_context *db_sc;
     466          24 :         NTSTATUS status;
     467             : 
     468         144 :         db_sc = open_schannel_session_store(frame, lp_ctx);
     469         144 :         if (!db_sc) {
     470           0 :                 TALLOC_FREE(frame);
     471           0 :                 return NT_STATUS_ACCESS_DENIED;
     472             :         }
     473             : 
     474         144 :         status = schannel_fetch_challenge_tdb(db_sc, frame,
     475             :                                               client_challenge,
     476             :                                               server_challenge,
     477             :                                               computer_name);
     478         144 :         TALLOC_FREE(frame);
     479         144 :         return status;
     480             : }
     481             : 
     482             : /******************************************************************************
     483             :  Wrapper around dbwrap_delete_bystring()
     484             :  Note we must be root here.
     485             : 
     486             :  This allows the challenge to be removed from the TDB, which should be
     487             :  as soon as the TDB or in-memory copy it is used, to avoid reuse.
     488             : *******************************************************************************/
     489             : 
     490        1714 : NTSTATUS schannel_delete_challenge(struct loadparm_context *lp_ctx,
     491             :                                    const char *computer_name)
     492             : {
     493        1714 :         TALLOC_CTX *frame = talloc_stackframe();
     494         174 :         struct db_context *db_sc;
     495         174 :         char *name_upper;
     496        1714 :         char keystr[16] = { 0, };
     497             : 
     498        1714 :         db_sc = open_schannel_session_store(frame, lp_ctx);
     499        1714 :         if (!db_sc) {
     500           0 :                 TALLOC_FREE(frame);
     501           0 :                 return NT_STATUS_ACCESS_DENIED;
     502             :         }
     503             : 
     504        1714 :         name_upper = strupper_talloc(frame, computer_name);
     505        1714 :         if (!name_upper) {
     506           0 :                 TALLOC_FREE(frame);
     507           0 :                 return NT_STATUS_NO_MEMORY;
     508             :         }
     509             : 
     510        1714 :         hash_computer_name(name_upper, keystr);
     511             : 
     512             :         /* Now delete it, we do not want to permit fetch of this twice */
     513        1714 :         dbwrap_delete_bystring(db_sc, keystr);
     514             : 
     515        1714 :         TALLOC_FREE(frame);
     516        1714 :         return NT_STATUS_OK;
     517             : }
     518             : 
     519             : /******************************************************************************
     520             :  Wrapper around schannel_store_session_key_tdb()
     521             :  Note we must be root here.
     522             : *******************************************************************************/
     523             : 
     524        9142 : NTSTATUS schannel_save_challenge(struct loadparm_context *lp_ctx,
     525             :                                  const struct netr_Credential *client_challenge,
     526             :                                  const struct netr_Credential *server_challenge,
     527             :                                  const char *computer_name)
     528             : {
     529        9142 :         TALLOC_CTX *frame = talloc_stackframe();
     530        1001 :         struct db_context *db_sc;
     531        1001 :         NTSTATUS status;
     532             : 
     533        9142 :         db_sc = open_schannel_session_store(frame, lp_ctx);
     534        9142 :         if (!db_sc) {
     535           0 :                 TALLOC_FREE(frame);
     536           0 :                 return NT_STATUS_ACCESS_DENIED;
     537             :         }
     538             : 
     539        9142 :         status = schannel_store_challenge_tdb(db_sc, frame,
     540             :                                               client_challenge,
     541             :                                               server_challenge,
     542             :                                               computer_name);
     543             : 
     544        9142 :         TALLOC_FREE(frame);
     545        9142 :         return status;
     546             : }
     547             : 
     548             : /********************************************************************
     549             :  Validate an incoming authenticator against the credentials for the
     550             :  remote machine stored in the schannel database.
     551             : 
     552             :  The credentials are (re)read and from the schannel database, and
     553             :  written back after the calculations are performed.
     554             : 
     555             :  If the creds_out parameter is not NULL returns the credentials.
     556             :  ********************************************************************/
     557             : 
     558       10967 : NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
     559             :                                     struct loadparm_context *lp_ctx,
     560             :                                     const char *computer_name,
     561             :                                     struct netr_Authenticator *received_authenticator,
     562             :                                     struct netr_Authenticator *return_authenticator,
     563             :                                     struct netlogon_creds_CredentialState **creds_out)
     564             : {
     565        1063 :         TALLOC_CTX *tmpctx;
     566        1063 :         struct db_context *db_sc;
     567        1063 :         struct netlogon_creds_CredentialState *creds;
     568        1063 :         NTSTATUS status;
     569       10967 :         char *name_upper = NULL;
     570       10967 :         char *keystr = NULL;
     571        1063 :         struct db_record *record;
     572        1063 :         TDB_DATA key;
     573             : 
     574       10967 :         if (creds_out != NULL) {
     575       10967 :                 *creds_out = NULL;
     576             :         }
     577             : 
     578       10967 :         tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
     579       10967 :         if (!tmpctx) {
     580           0 :                 return NT_STATUS_NO_MEMORY;
     581             :         }
     582             : 
     583       10967 :         name_upper = strupper_talloc(tmpctx, computer_name);
     584       10967 :         if (!name_upper) {
     585           0 :                 status = NT_STATUS_NO_MEMORY;
     586           0 :                 goto done;
     587             :         }
     588             : 
     589       10967 :         keystr = talloc_asprintf(tmpctx, "%s/%s",
     590             :                                  SECRETS_SCHANNEL_STATE, name_upper);
     591       10967 :         if (!keystr) {
     592           0 :                 status = NT_STATUS_NO_MEMORY;
     593           0 :                 goto done;
     594             :         }
     595             : 
     596       10967 :         key = string_term_tdb_data(keystr);
     597             : 
     598       10967 :         db_sc = open_schannel_session_store(tmpctx, lp_ctx);
     599       10967 :         if (!db_sc) {
     600           0 :                 status = NT_STATUS_ACCESS_DENIED;
     601           0 :                 goto done;
     602             :         }
     603             : 
     604       10967 :         record = dbwrap_fetch_locked(db_sc, tmpctx, key);
     605       10967 :         if (!record) {
     606           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     607           0 :                 goto done;
     608             :         }
     609             : 
     610             :         /* Because this is a shared structure (even across
     611             :          * disconnects) we must update the database every time we
     612             :          * update the structure */
     613             : 
     614       10967 :         status = schannel_fetch_session_key_tdb(db_sc, tmpctx,
     615             :                                                 computer_name, &creds);
     616       10967 :         if (!NT_STATUS_IS_OK(status)) {
     617          18 :                 goto done;
     618             :         }
     619             : 
     620       10949 :         status = netlogon_creds_server_step_check(creds,
     621             :                                                   received_authenticator,
     622             :                                                   return_authenticator);
     623       10949 :         if (!NT_STATUS_IS_OK(status)) {
     624           0 :                 goto done;
     625             :         }
     626             : 
     627       10949 :         status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
     628       10949 :         if (!NT_STATUS_IS_OK(status)) {
     629           0 :                 goto done;
     630             :         }
     631             : 
     632       10949 :         if (creds_out) {
     633       10949 :                 *creds_out = talloc_steal(mem_ctx, creds);
     634       10949 :                 if (!*creds_out) {
     635           0 :                         status = NT_STATUS_NO_MEMORY;
     636           0 :                         goto done;
     637             :                 }
     638             :         }
     639             : 
     640        9888 :         status = NT_STATUS_OK;
     641             : 
     642       10967 : done:
     643       10967 :         talloc_free(tmpctx);
     644       10967 :         return status;
     645             : }
     646             : 

Generated by: LCOV version 1.14