1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-04 17:47:26 +03:00
Andrew Bartlett a249198d53 r4682: A LDB-based secrets implementation in Samba4.
This uses LDB (a local secrets.ldb and the global samdb) to fill out
the secrets from an LSA perspective.

Some small changes to come, but the bulk of the work is now done.

A re-provision is required after this change.

Andrew Bartlett
(This used to be commit ded33033521a6a1c7ea80758c5c5aeeebb182a51)
2007-10-10 13:08:42 -05:00

212 lines
4.8 KiB
C

/*
Unix SMB/CIFS implementation.
code to encrypt/decrypt data using the user session key
Copyright (C) Andrew Tridgell 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/*
encrypt or decrypt a blob of data using the user session key
as used in lsa_SetSecret
before calling, the out blob must be initialised to be the same size
as the in blob
*/
void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *session_key,
BOOL forward)
{
int i, k;
for (i=0,k=0;
i<in->length;
i += 8, k += 7) {
uint8_t bin[8], bout[8], key[7];
memset(bin, 0, 8);
memcpy(bin, &in->data[i], MIN(8, in->length-i));
if (k + 7 > session_key->length) {
k = (session_key->length - k);
}
memcpy(key, &session_key->data[k], 7);
des_crypt56(bout, bin, key, forward?1:0);
memcpy(&out->data[i], bout, MIN(8, in->length-i));
}
}
/*
a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
note that we round the length to a multiple of 8. This seems to be needed for
compatibility with windows
caller should free using data_blob_free()
*/
DATA_BLOB sess_encrypt_string(const char *str, const DATA_BLOB *session_key)
{
DATA_BLOB ret, src;
int slen = strlen(str);
int dlen = (slen+7) & ~7;
src = data_blob(NULL, 8+dlen);
if (!src.data) {
return data_blob(NULL, 0);
}
ret = data_blob(NULL, 8+dlen);
if (!ret.data) {
data_blob_free(&src);
return data_blob(NULL, 0);
}
SIVAL(src.data, 0, slen);
SIVAL(src.data, 4, 1);
memset(src.data+8, 0, dlen);
memcpy(src.data+8, str, slen);
sess_crypt_blob(&ret, &src, session_key, True);
data_blob_free(&src);
return ret;
}
/*
a convenient wrapper around sess_crypt_blob() for strings, using the LSA convention
caller should free the returned string
*/
char *sess_decrypt_string(DATA_BLOB *blob, const DATA_BLOB *session_key)
{
DATA_BLOB out;
int slen;
char *ret;
if (blob->length < 8) {
return NULL;
}
out = data_blob(NULL, blob->length);
if (!out.data) {
return NULL;
}
sess_crypt_blob(&out, blob, session_key, False);
if (IVAL(out.data, 4) != 1) {
DEBUG(0,("Unexpected revision number %d in session crypted string\n",
IVAL(out.data, 4)));
return NULL;
}
slen = IVAL(out.data, 0);
if (slen > blob->length - 8) {
DEBUG(0,("Invalid crypt length %d\n", slen));
return NULL;
}
ret = strndup((const char *)(out.data+8), slen);
data_blob_free(&out);
return ret;
}
/*
a convenient wrapper around sess_crypt_blob() for DATA_BLOBs, using the LSA convention
note that we round the length to a multiple of 8. This seems to be needed for
compatibility with windows
caller should free using data_blob_free()
*/
DATA_BLOB sess_encrypt_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob_in, const DATA_BLOB *session_key)
{
DATA_BLOB ret, src;
int dlen = (blob_in->length+7) & ~7;
src = data_blob_talloc(mem_ctx, NULL, 8+dlen);
if (!src.data) {
return data_blob(NULL, 0);
}
ret = data_blob(NULL, 8+dlen);
if (!ret.data) {
data_blob_free(&src);
return data_blob(NULL, 0);
}
SIVAL(src.data, 0, blob_in->length);
SIVAL(src.data, 4, 1);
memset(src.data+8, 0, dlen);
memcpy(src.data+8, blob_in->data, blob_in->length);
sess_crypt_blob(&ret, &src, session_key, True);
data_blob_free(&src);
return ret;
}
/*
Decrypt a DATA_BLOB using the LSA convention
*/
NTSTATUS sess_decrypt_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, const DATA_BLOB *session_key,
DATA_BLOB *ret)
{
DATA_BLOB out;
int slen;
if (blob->length < 8) {
return NT_STATUS_INVALID_PARAMETER;
}
out = data_blob_talloc(mem_ctx, NULL, blob->length);
if (!out.data) {
return NT_STATUS_NO_MEMORY;
}
sess_crypt_blob(&out, blob, session_key, False);
if (IVAL(out.data, 4) != 1) {
DEBUG(0,("Unexpected revision number %d in session crypted string\n",
IVAL(out.data, 4)));
return NT_STATUS_UNKNOWN_REVISION;
}
slen = IVAL(out.data, 0);
if (slen > blob->length - 8) {
DEBUG(0,("Invalid crypt length %d\n", slen));
return NT_STATUS_WRONG_PASSWORD;
}
*ret = data_blob_talloc(mem_ctx, out.data+8, slen);
if (!ret->data) {
return NT_STATUS_NO_MEMORY;
}
data_blob_free(&out);
return NT_STATUS_OK;
}