LCOV - code coverage report
Current view: top level - libcli/auth - session.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 70 100 70.0 %
Date: 2024-06-13 04:01:37 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    code to encrypt/decrypt data using the user session key
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "libcli/auth/libcli_auth.h"
      24             : 
      25             : /*
      26             :   encrypt or decrypt a blob of data using the user session key
      27             :   as used in lsa_SetSecret
      28             : 
      29             :   before calling, the out blob must be initialised to be the same size
      30             :   as the in blob
      31             : */
      32        6550 : int sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key,
      33             :                     enum samba_gnutls_direction encrypt)
      34             : {
      35             :         int i, k, rc;
      36             : 
      37        6550 :         if (in->length % 8 != 0) {
      38           0 :                 return GNUTLS_E_INVALID_REQUEST;
      39             :         }
      40             : 
      41       26122 :         for (i=0,k=0;
      42       31668 :              i<in->length;
      43       25118 :              i += 8, k += 7) {
      44             :                 uint8_t bin[8], bout[8], key[7];
      45             : 
      46       25118 :                 memcpy(bin,  &in->data[i], 8);
      47             : 
      48       25118 :                 if (k + 7 > session_key->length) {
      49        6012 :                         k = (session_key->length - k);
      50             :                 }
      51       25118 :                 memcpy(key, &session_key->data[k], 7);
      52             : 
      53       25118 :                 rc = des_crypt56_gnutls(bout, bin, key, encrypt);
      54       25118 :                 if (rc != 0) {
      55           0 :                         return rc;
      56             :                 }
      57             : 
      58       25118 :                 memcpy(&out->data[i], bout, 8);
      59             :         }
      60        6550 :         return 0;
      61             : }
      62             : 
      63             : 
      64             : /*
      65             :   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
      66             : 
      67             :   note that we round the length to a multiple of 8. This seems to be needed for 
      68             :   compatibility with windows
      69             : 
      70             :   caller should free using data_blob_free()
      71             : */
      72        1182 : DATA_BLOB sess_encrypt_string(const char *str, const DATA_BLOB *session_key)
      73             : {
      74             :         DATA_BLOB ret, src;
      75        1182 :         int slen = strlen(str);
      76        1182 :         int dlen = (slen+7) & ~7;
      77             :         int rc;
      78             : 
      79        1182 :         src = data_blob(NULL, 8+dlen);
      80        1182 :         if (!src.data) {
      81           0 :                 return data_blob(NULL, 0);
      82             :         }
      83             : 
      84        1182 :         ret = data_blob(NULL, 8+dlen);
      85        1182 :         if (!ret.data) {
      86           0 :                 data_blob_free(&src);
      87           0 :                 return data_blob(NULL, 0);
      88             :         }
      89             : 
      90        1182 :         SIVAL(src.data, 0, slen);
      91        1182 :         SIVAL(src.data, 4, 1);
      92        1182 :         memset(src.data+8, 0,   dlen);
      93        1182 :         memcpy(src.data+8, str, slen);
      94             : 
      95        1182 :         rc = sess_crypt_blob(&ret, &src, session_key, SAMBA_GNUTLS_ENCRYPT);
      96             :         
      97        1182 :         data_blob_free(&src);
      98        1182 :         if (rc != 0) {
      99           0 :                 data_blob_free(&ret);
     100           0 :                 return data_blob(NULL, 0);
     101             :         }
     102             : 
     103        1182 :         return ret;
     104             : }
     105             : 
     106             : /*
     107             :   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
     108             : 
     109             :   caller should free the returned string
     110             : */
     111        1192 : char *sess_decrypt_string(TALLOC_CTX *mem_ctx, 
     112             :                           DATA_BLOB *blob, const DATA_BLOB *session_key)
     113             : {
     114             :         DATA_BLOB out;
     115             :         int rc, slen;
     116             :         char *ret;
     117             : 
     118        1192 :         if (blob->length < 8) {
     119           0 :                 return NULL;
     120             :         }
     121             :         
     122        1192 :         out = data_blob_talloc(mem_ctx, NULL, blob->length);
     123        1192 :         if (!out.data) {
     124           0 :                 return NULL;
     125             :         }
     126             : 
     127        1192 :         rc = sess_crypt_blob(&out, blob, session_key, SAMBA_GNUTLS_DECRYPT);
     128        1192 :         if (rc != 0) {
     129           0 :                 data_blob_free(&out);
     130           0 :                 return NULL;
     131             :         }
     132             : 
     133        1192 :         if (IVAL(out.data, 4) != 1) {
     134           0 :                 DEBUG(0,("Unexpected revision number %d in session crypted string\n",
     135             :                          IVAL(out.data, 4)));
     136           0 :                 data_blob_free(&out);
     137           0 :                 return NULL;
     138             :         }
     139             : 
     140        1192 :         slen = IVAL(out.data, 0);
     141        1192 :         if (slen > blob->length - 8) {
     142           0 :                 DEBUG(0,("Invalid crypt length %d\n", slen));
     143           0 :                 data_blob_free(&out);
     144           0 :                 return NULL;
     145             :         }
     146             : 
     147        1192 :         ret = talloc_strndup(mem_ctx, (const char *)(out.data+8), slen);
     148             : 
     149        1192 :         data_blob_free(&out);
     150             : 
     151        1192 :         DEBUG(0,("decrypted string '%s' of length %d\n", ret, slen));
     152             : 
     153        1192 :         return ret;
     154             : }
     155             : 
     156             : /*
     157             :   a convenient wrapper around sess_crypt_blob() for DATA_BLOBs, using the LSA convention
     158             : 
     159             :   note that we round the length to a multiple of 8. This seems to be needed for 
     160             :   compatibility with windows
     161             : 
     162             :   caller should free using data_blob_free()
     163             : */
     164        1198 : DATA_BLOB sess_encrypt_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob_in, const DATA_BLOB *session_key)
     165             : {
     166             :         DATA_BLOB ret, src;
     167        1198 :         int dlen = (blob_in->length+7) & ~7;
     168             :         int rc;
     169             : 
     170        1198 :         src = data_blob_talloc(mem_ctx, NULL, 8+dlen);
     171        1198 :         if (!src.data) {
     172           0 :                 return data_blob(NULL, 0);
     173             :         }
     174             : 
     175        1198 :         ret = data_blob_talloc(mem_ctx, NULL, 8+dlen);
     176        1198 :         if (!ret.data) {
     177           0 :                 data_blob_free(&src);
     178           0 :                 return data_blob(NULL, 0);
     179             :         }
     180             : 
     181        1198 :         SIVAL(src.data, 0, blob_in->length);
     182        1198 :         SIVAL(src.data, 4, 1);
     183        1198 :         memset(src.data+8, 0, dlen);
     184        1198 :         memcpy(src.data+8, blob_in->data, blob_in->length);
     185             : 
     186        1198 :         rc = sess_crypt_blob(&ret, &src, session_key, SAMBA_GNUTLS_ENCRYPT);
     187             :         
     188        1198 :         data_blob_free(&src);
     189        1198 :         if (rc != 0) {
     190           0 :                 data_blob_free(&ret);
     191           0 :                 return data_blob(NULL, 0);
     192             :         }
     193             : 
     194        1198 :         return ret;
     195             : }
     196             : 
     197             : /*
     198             :   Decrypt a DATA_BLOB using the LSA convention
     199             : */
     200        2350 : NTSTATUS sess_decrypt_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const DATA_BLOB *session_key, 
     201             :                            DATA_BLOB *ret)
     202             : {
     203             :         DATA_BLOB out;
     204             :         int rc, slen;
     205             : 
     206        2350 :         if (blob->length < 8) {
     207           0 :                 DEBUG(0, ("Unexpected length %d in session crypted secret (BLOB)\n",
     208             :                           (int)blob->length));
     209           0 :                 return NT_STATUS_INVALID_PARAMETER;
     210             :         }
     211             :         
     212        2350 :         out = data_blob_talloc(mem_ctx, NULL, blob->length);
     213        2350 :         if (!out.data) {
     214           0 :                 return NT_STATUS_NO_MEMORY;
     215             :         }
     216             : 
     217        2350 :         rc = sess_crypt_blob(&out, blob, session_key, SAMBA_GNUTLS_DECRYPT);
     218        2350 :         if (rc != 0) {
     219           0 :                 data_blob_free(&out);
     220           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     221             :         }
     222             : 
     223        2350 :         if (IVAL(out.data, 4) != 1) {
     224        1162 :                 DEBUG(2,("Unexpected revision number %d in session crypted secret (BLOB)\n",
     225             :                          IVAL(out.data, 4)));
     226        1162 :                 return NT_STATUS_UNKNOWN_REVISION;
     227             :         }
     228             :                 
     229        1188 :         slen = IVAL(out.data, 0);
     230        1188 :         if (slen > blob->length - 8) {
     231           0 :                 DEBUG(0,("Invalid crypt length %d in session crypted secret (BLOB)\n", slen));
     232           0 :                 return NT_STATUS_WRONG_PASSWORD;
     233             :         }
     234             : 
     235        1188 :         *ret = data_blob_talloc(mem_ctx, out.data+8, slen);
     236        1188 :         if (slen && !ret->data) {
     237           0 :                 return NT_STATUS_NO_MEMORY;
     238             :         }
     239             : 
     240        1188 :         data_blob_free(&out);
     241             : 
     242        1188 :         return NT_STATUS_OK;
     243             : }

Generated by: LCOV version 1.13