LCOV - code coverage report
Current view: top level - libcli/auth - session.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 73 113 64.6 %
Date: 2024-02-28 12:06:22 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        7858 : int sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key,
      33             :                     enum samba_gnutls_direction encrypt)
      34             : {
      35           2 :         int i, k, rc;
      36             : 
      37        7858 :         if (in->length % 8 != 0) {
      38           0 :                 return GNUTLS_E_INVALID_REQUEST;
      39             :         }
      40             : 
      41        7858 :         if (session_key->length < 7) {
      42           0 :                 return GNUTLS_E_INVALID_REQUEST;
      43             :         }
      44             : 
      45        7856 :         for (i=0,k=0;
      46       37554 :              i<in->length;
      47       29696 :              i += 8, k += 7) {
      48           6 :                 uint8_t bin[8], bout[8], key[7];
      49             : 
      50       29696 :                 memcpy(bin,  &in->data[i], 8);
      51             : 
      52       29696 :                 if (k + 7 > session_key->length) {
      53        6994 :                         k = (session_key->length - k);
      54             :                 }
      55       29696 :                 memcpy(key, &session_key->data[k], 7);
      56             : 
      57       29696 :                 rc = des_crypt56_gnutls(bout, bin, key, encrypt);
      58       29696 :                 if (rc != 0) {
      59           0 :                         return rc;
      60             :                 }
      61             : 
      62       29696 :                 memcpy(&out->data[i], bout, 8);
      63             :         }
      64        7856 :         return 0;
      65             : }
      66             : 
      67             : 
      68             : /*
      69             :   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
      70             : 
      71             :   note that we round the length to a multiple of 8. This seems to be needed for 
      72             :   compatibility with windows
      73             : 
      74             :   caller should free using data_blob_free()
      75             : */
      76        1634 : DATA_BLOB sess_encrypt_string(const char *str, const DATA_BLOB *session_key)
      77             : {
      78           0 :         DATA_BLOB ret, src;
      79        1634 :         int slen = strlen(str);
      80        1634 :         int dlen = (slen+7) & ~7;
      81           0 :         int rc;
      82             : 
      83        1634 :         src = data_blob(NULL, 8+dlen);
      84        1634 :         if (!src.data) {
      85           0 :                 return data_blob(NULL, 0);
      86             :         }
      87             : 
      88        1634 :         ret = data_blob(NULL, 8+dlen);
      89        1634 :         if (!ret.data) {
      90           0 :                 data_blob_free(&src);
      91           0 :                 return data_blob(NULL, 0);
      92             :         }
      93             : 
      94        1634 :         SIVAL(src.data, 0, slen);
      95        1634 :         SIVAL(src.data, 4, 1);
      96        1634 :         memset(src.data+8, 0,   dlen);
      97        1634 :         memcpy(src.data+8, str, slen);
      98             : 
      99        1634 :         rc = sess_crypt_blob(&ret, &src, session_key, SAMBA_GNUTLS_ENCRYPT);
     100             :         
     101        1634 :         data_blob_free(&src);
     102        1634 :         if (rc != 0) {
     103           0 :                 data_blob_free(&ret);
     104           0 :                 return data_blob(NULL, 0);
     105             :         }
     106             : 
     107        1634 :         return ret;
     108             : }
     109             : 
     110             : /*
     111             :   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
     112             : 
     113             :   caller should free the returned string
     114             : */
     115        1656 : char *sess_decrypt_string(TALLOC_CTX *mem_ctx, 
     116             :                           DATA_BLOB *blob, const DATA_BLOB *session_key)
     117             : {
     118           0 :         DATA_BLOB out;
     119           0 :         int rc, slen;
     120           0 :         char *ret;
     121             : 
     122        1656 :         if (blob->length < 8) {
     123           0 :                 return NULL;
     124             :         }
     125             :         
     126        1656 :         out = data_blob_talloc(mem_ctx, NULL, blob->length);
     127        1656 :         if (!out.data) {
     128           0 :                 return NULL;
     129             :         }
     130             : 
     131        1656 :         rc = sess_crypt_blob(&out, blob, session_key, SAMBA_GNUTLS_DECRYPT);
     132        1656 :         if (rc != 0) {
     133           0 :                 data_blob_free(&out);
     134           0 :                 return NULL;
     135             :         }
     136             : 
     137        1656 :         if (IVAL(out.data, 4) != 1) {
     138           0 :                 DEBUG(0,("Unexpected revision number %d in session encrypted string\n",
     139             :                          IVAL(out.data, 4)));
     140           0 :                 data_blob_free(&out);
     141           0 :                 return NULL;
     142             :         }
     143             : 
     144        1656 :         slen = IVAL(out.data, 0);
     145        1656 :         if (slen > blob->length - 8) {
     146           0 :                 DEBUG(0,("Invalid crypt length %d\n", slen));
     147           0 :                 data_blob_free(&out);
     148           0 :                 return NULL;
     149             :         }
     150             : 
     151        1656 :         ret = talloc_strndup(mem_ctx, (const char *)(out.data+8), slen);
     152             : 
     153        1656 :         data_blob_free(&out);
     154             : 
     155        1656 :         DEBUG(0,("decrypted string '%s' of length %d\n", ret, slen));
     156             : 
     157        1656 :         return ret;
     158             : }
     159             : 
     160             : /*
     161             :   a convenient wrapper around sess_crypt_blob() for DATA_BLOBs, using the LSA convention
     162             : 
     163             :   note that we round the length to a multiple of 8. This seems to be needed for 
     164             :   compatibility with windows
     165             : 
     166             :   caller should free using data_blob_free()
     167             : */
     168        1230 : DATA_BLOB sess_encrypt_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob_in, const DATA_BLOB *session_key)
     169             : {
     170           0 :         DATA_BLOB ret, src;
     171        1230 :         int dlen = (blob_in->length+7) & ~7;
     172           0 :         int rc;
     173             : 
     174        1230 :         src = data_blob_talloc(mem_ctx, NULL, 8+dlen);
     175        1230 :         if (!src.data) {
     176           0 :                 return data_blob(NULL, 0);
     177             :         }
     178             : 
     179        1230 :         ret = data_blob_talloc(mem_ctx, NULL, 8+dlen);
     180        1230 :         if (!ret.data) {
     181           0 :                 data_blob_free(&src);
     182           0 :                 return data_blob(NULL, 0);
     183             :         }
     184             : 
     185        1230 :         SIVAL(src.data, 0, blob_in->length);
     186        1230 :         SIVAL(src.data, 4, 1);
     187        1230 :         memset(src.data+8, 0, dlen);
     188        1230 :         memcpy(src.data+8, blob_in->data, blob_in->length);
     189             : 
     190        1230 :         rc = sess_crypt_blob(&ret, &src, session_key, SAMBA_GNUTLS_ENCRYPT);
     191             :         
     192        1230 :         data_blob_free(&src);
     193        1230 :         if (rc != 0) {
     194           0 :                 data_blob_free(&ret);
     195           0 :                 return data_blob(NULL, 0);
     196             :         }
     197             : 
     198        1230 :         return ret;
     199             : }
     200             : 
     201             : /*
     202             :   Decrypt a DATA_BLOB using the LSA convention
     203             : */
     204        2382 : NTSTATUS sess_decrypt_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const DATA_BLOB *session_key, 
     205             :                            DATA_BLOB *ret)
     206             : {
     207           0 :         DATA_BLOB out;
     208           0 :         int rc, slen;
     209             : 
     210        2382 :         if (blob->length < 8) {
     211           0 :                 DEBUG(0, ("Unexpected length %d in session encrypted secret (BLOB)\n",
     212             :                           (int)blob->length));
     213           0 :                 return NT_STATUS_INVALID_PARAMETER;
     214             :         }
     215             :         
     216        2382 :         out = data_blob_talloc(mem_ctx, NULL, blob->length);
     217        2382 :         if (!out.data) {
     218           0 :                 return NT_STATUS_NO_MEMORY;
     219             :         }
     220             : 
     221        2382 :         rc = sess_crypt_blob(&out, blob, session_key, SAMBA_GNUTLS_DECRYPT);
     222        2382 :         if (rc != 0) {
     223           0 :                 data_blob_free(&out);
     224           0 :                 return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
     225             :         }
     226             : 
     227        2382 :         if (IVAL(out.data, 4) != 1) {
     228        1170 :                 DEBUG(2,("Unexpected revision number %d in session encrypted secret (BLOB)\n",
     229             :                          IVAL(out.data, 4)));
     230        1170 :                 return NT_STATUS_UNKNOWN_REVISION;
     231             :         }
     232             :                 
     233        1212 :         slen = IVAL(out.data, 0);
     234        1212 :         if (slen > blob->length - 8) {
     235           0 :                 DEBUG(0,("Invalid crypt length %d in session encrypted secret (BLOB)\n", slen));
     236           0 :                 return NT_STATUS_WRONG_PASSWORD;
     237             :         }
     238             : 
     239        1212 :         *ret = data_blob_talloc(mem_ctx, out.data+8, slen);
     240        1212 :         if (slen && !ret->data) {
     241           0 :                 return NT_STATUS_NO_MEMORY;
     242             :         }
     243             : 
     244        1212 :         data_blob_free(&out);
     245             : 
     246        1212 :         return NT_STATUS_OK;
     247             : }

Generated by: LCOV version 1.14