root/source4/libcli/auth/session.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sess_crypt_blob
  2. sess_encrypt_string
  3. sess_decrypt_string
  4. sess_encrypt_blob
  5. sess_decrypt_blob

   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 void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key,
     /* [<][>][^][v][top][bottom][index][help] */
  33                      bool forward)
  34 {
  35         int i, k;
  36 
  37         for (i=0,k=0;
  38              i<in->length;
  39              i += 8, k += 7) {
  40                 uint8_t bin[8], bout[8], key[7];
  41 
  42                 memset(bin, 0, 8);
  43                 memcpy(bin,  &in->data[i], MIN(8, in->length-i));
  44 
  45                 if (k + 7 > session_key->length) {
  46                         k = (session_key->length - k);
  47                 }
  48                 memcpy(key, &session_key->data[k], 7);
  49 
  50                 des_crypt56(bout, bin, key, forward?1:0);
  51 
  52                 memcpy(&out->data[i], bout, MIN(8, in->length-i));
  53         }
  54 }
  55 
  56 
  57 /*
  58   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
  59 
  60   note that we round the length to a multiple of 8. This seems to be needed for 
  61   compatibility with windows
  62 
  63   caller should free using data_blob_free()
  64 */
  65 DATA_BLOB sess_encrypt_string(const char *str, const DATA_BLOB *session_key)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67         DATA_BLOB ret, src;
  68         int slen = strlen(str);
  69         int dlen = (slen+7) & ~7;
  70 
  71         src = data_blob(NULL, 8+dlen);
  72         if (!src.data) {
  73                 return data_blob(NULL, 0);
  74         }
  75 
  76         ret = data_blob(NULL, 8+dlen);
  77         if (!ret.data) {
  78                 data_blob_free(&src);
  79                 return data_blob(NULL, 0);
  80         }
  81 
  82         SIVAL(src.data, 0, slen);
  83         SIVAL(src.data, 4, 1);
  84         memset(src.data+8, 0,   dlen);
  85         memcpy(src.data+8, str, slen);
  86 
  87         sess_crypt_blob(&ret, &src, session_key, true);
  88         
  89         data_blob_free(&src);
  90 
  91         return ret;
  92 }
  93 
  94 /*
  95   a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
  96 
  97   caller should free the returned string
  98 */
  99 char *sess_decrypt_string(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 100                           DATA_BLOB *blob, const DATA_BLOB *session_key)
 101 {
 102         DATA_BLOB out;
 103         int slen;
 104         char *ret;
 105 
 106         if (blob->length < 8) {
 107                 return NULL;
 108         }
 109         
 110         out = data_blob_talloc(mem_ctx, NULL, blob->length);
 111         if (!out.data) {
 112                 return NULL;
 113         }
 114 
 115         sess_crypt_blob(&out, blob, session_key, false);
 116 
 117         if (IVAL(out.data, 4) != 1) {
 118                 DEBUG(0,("Unexpected revision number %d in session crypted string\n",
 119                          IVAL(out.data, 4)));
 120                 data_blob_free(&out);
 121                 return NULL;
 122         }
 123 
 124         slen = IVAL(out.data, 0);
 125         if (slen > blob->length - 8) {
 126                 DEBUG(0,("Invalid crypt length %d\n", slen));
 127                 data_blob_free(&out);
 128                 return NULL;
 129         }
 130 
 131         ret = talloc_strndup(mem_ctx, (const char *)(out.data+8), slen);
 132 
 133         data_blob_free(&out);
 134 
 135         DEBUG(0,("decrypted string '%s' of length %d\n", ret, slen));
 136 
 137         return ret;
 138 }
 139 
 140 /*
 141   a convenient wrapper around sess_crypt_blob() for DATA_BLOBs, using the LSA convention
 142 
 143   note that we round the length to a multiple of 8. This seems to be needed for 
 144   compatibility with windows
 145 
 146   caller should free using data_blob_free()
 147 */
 148 DATA_BLOB sess_encrypt_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob_in, const DATA_BLOB *session_key)
     /* [<][>][^][v][top][bottom][index][help] */
 149 {
 150         DATA_BLOB ret, src;
 151         int dlen = (blob_in->length+7) & ~7;
 152 
 153         src = data_blob_talloc(mem_ctx, NULL, 8+dlen);
 154         if (!src.data) {
 155                 return data_blob(NULL, 0);
 156         }
 157 
 158         ret = data_blob_talloc(mem_ctx, NULL, 8+dlen);
 159         if (!ret.data) {
 160                 data_blob_free(&src);
 161                 return data_blob(NULL, 0);
 162         }
 163 
 164         SIVAL(src.data, 0, blob_in->length);
 165         SIVAL(src.data, 4, 1);
 166         memset(src.data+8, 0, dlen);
 167         memcpy(src.data+8, blob_in->data, blob_in->length);
 168 
 169         sess_crypt_blob(&ret, &src, session_key, true);
 170         
 171         data_blob_free(&src);
 172 
 173         return ret;
 174 }
 175 
 176 /*
 177   Decrypt a DATA_BLOB using the LSA convention
 178 */
 179 NTSTATUS sess_decrypt_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const DATA_BLOB *session_key, 
     /* [<][>][^][v][top][bottom][index][help] */
 180                            DATA_BLOB *ret)
 181 {
 182         DATA_BLOB out;
 183         int slen;
 184 
 185         if (blob->length < 8) {
 186                 DEBUG(0, ("Unexpected length %d in session crypted secret (BLOB)\n",
 187                           (int)blob->length));
 188                 return NT_STATUS_INVALID_PARAMETER;
 189         }
 190         
 191         out = data_blob_talloc(mem_ctx, NULL, blob->length);
 192         if (!out.data) {
 193                 return NT_STATUS_NO_MEMORY;
 194         }
 195 
 196         sess_crypt_blob(&out, blob, session_key, false);
 197 
 198         if (IVAL(out.data, 4) != 1) {
 199                 DEBUG(2,("Unexpected revision number %d in session crypted secret (BLOB)\n",
 200                          IVAL(out.data, 4)));
 201                 return NT_STATUS_UNKNOWN_REVISION;
 202         }
 203                 
 204         slen = IVAL(out.data, 0);
 205         if (slen > blob->length - 8) {
 206                 DEBUG(0,("Invalid crypt length %d in session crypted secret (BLOB)\n", slen));
 207                 return NT_STATUS_WRONG_PASSWORD;
 208         }
 209 
 210         *ret = data_blob_talloc(mem_ctx, out.data+8, slen);
 211         if (slen && !ret->data) {
 212                 return NT_STATUS_NO_MEMORY;
 213         }
 214 
 215         data_blob_free(&out);
 216 
 217         return NT_STATUS_OK;
 218 }

/* [<][>][^][v][top][bottom][index][help] */