mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
9c2ffef0d5
Signed-off-by: Pavel Filipenský <pfilipensky@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
246 lines
6.4 KiB
C
246 lines
6.4 KiB
C
/*
|
|
Unix SMB/CIFS implementation.
|
|
Copyright (C) Guenther Deschner 2009
|
|
|
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "librpc/gen_ndr/ndr_secrets.h"
|
|
#include "secrets.h"
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
static char *lsa_secret_key(TALLOC_CTX *mem_ctx,
|
|
const char *secret_name)
|
|
{
|
|
return talloc_asprintf_strupper_m(mem_ctx, "SECRETS/LSA/%s",
|
|
secret_name);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
static NTSTATUS lsa_secret_get_common(TALLOC_CTX *mem_ctx,
|
|
const char *secret_name,
|
|
struct lsa_secret *secret)
|
|
{
|
|
char *key;
|
|
DATA_BLOB blob;
|
|
enum ndr_err_code ndr_err;
|
|
|
|
ZERO_STRUCTP(secret);
|
|
|
|
key = lsa_secret_key(mem_ctx, secret_name);
|
|
if (!key) {
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
blob.data = (uint8_t *)secrets_fetch(key, &blob.length);
|
|
talloc_free(key);
|
|
|
|
if (!blob.data) {
|
|
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
|
|
ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, secret,
|
|
(ndr_pull_flags_fn_t)ndr_pull_lsa_secret);
|
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
SAFE_FREE(blob.data);
|
|
return ndr_map_error2ntstatus(ndr_err);
|
|
}
|
|
|
|
/* This is NOT a talloc blob */
|
|
BURN_FREE(blob.data, blob.length);
|
|
|
|
if (secret->secret_current != NULL &&
|
|
secret->secret_current->data != NULL) {
|
|
talloc_keep_secret(secret->secret_current->data);
|
|
}
|
|
if (secret->secret_old != NULL && secret->secret_old->data != NULL) {
|
|
talloc_keep_secret(secret->secret_old->data);
|
|
}
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
NTSTATUS lsa_secret_get(TALLOC_CTX *mem_ctx,
|
|
const char *secret_name,
|
|
DATA_BLOB *secret_current,
|
|
NTTIME *secret_current_lastchange,
|
|
DATA_BLOB *secret_old,
|
|
NTTIME *secret_old_lastchange,
|
|
struct security_descriptor **sd)
|
|
{
|
|
NTSTATUS status;
|
|
struct lsa_secret secret;
|
|
|
|
status = lsa_secret_get_common(mem_ctx, secret_name, &secret);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
return status;
|
|
}
|
|
|
|
if (secret_current) {
|
|
*secret_current = data_blob_null;
|
|
if (secret.secret_current) {
|
|
*secret_current = *secret.secret_current;
|
|
}
|
|
}
|
|
if (secret_current_lastchange) {
|
|
*secret_current_lastchange = secret.secret_current_lastchange;
|
|
}
|
|
if (secret_old) {
|
|
*secret_old = data_blob_null;
|
|
if (secret.secret_old) {
|
|
*secret_old = *secret.secret_old;
|
|
}
|
|
}
|
|
if (secret_old_lastchange) {
|
|
*secret_old_lastchange = secret.secret_old_lastchange;
|
|
}
|
|
if (sd) {
|
|
*sd = secret.sd;
|
|
}
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
static NTSTATUS lsa_secret_set_common(TALLOC_CTX *mem_ctx,
|
|
const char *key,
|
|
struct lsa_secret *secret,
|
|
DATA_BLOB *secret_current,
|
|
DATA_BLOB *secret_old,
|
|
struct security_descriptor *sd)
|
|
{
|
|
enum ndr_err_code ndr_err;
|
|
DATA_BLOB blob;
|
|
struct timeval now = timeval_current();
|
|
|
|
if (!secret) {
|
|
secret = talloc_zero(mem_ctx, struct lsa_secret);
|
|
}
|
|
|
|
if (!secret) {
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
if (secret_old) {
|
|
secret->secret_old = secret_old;
|
|
secret->secret_old_lastchange = timeval_to_nttime(&now);
|
|
} else {
|
|
if (secret->secret_current) {
|
|
secret->secret_old = secret->secret_current;
|
|
secret->secret_old_lastchange = secret->secret_current_lastchange;
|
|
} else {
|
|
secret->secret_old = NULL;
|
|
secret->secret_old_lastchange = timeval_to_nttime(&now);
|
|
}
|
|
}
|
|
if (secret_current) {
|
|
secret->secret_current = secret_current;
|
|
secret->secret_current_lastchange = timeval_to_nttime(&now);
|
|
} else {
|
|
secret->secret_current = NULL;
|
|
secret->secret_current_lastchange = timeval_to_nttime(&now);
|
|
}
|
|
if (sd) {
|
|
secret->sd = sd;
|
|
}
|
|
|
|
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, secret,
|
|
(ndr_push_flags_fn_t)ndr_push_lsa_secret);
|
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
|
return ndr_map_error2ntstatus(ndr_err);
|
|
}
|
|
|
|
if (!secrets_store(key, blob.data, blob.length)) {
|
|
data_blob_clear(&blob);
|
|
return NT_STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
data_blob_clear(&blob);
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
NTSTATUS lsa_secret_set(const char *secret_name,
|
|
DATA_BLOB *secret_current,
|
|
DATA_BLOB *secret_old,
|
|
struct security_descriptor *sd)
|
|
{
|
|
char *key;
|
|
struct lsa_secret secret;
|
|
NTSTATUS status;
|
|
|
|
key = lsa_secret_key(talloc_tos(), secret_name);
|
|
if (!key) {
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
status = lsa_secret_get_common(talloc_tos(), secret_name, &secret);
|
|
if (!NT_STATUS_IS_OK(status) &&
|
|
!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
|
talloc_free(key);
|
|
return status;
|
|
}
|
|
|
|
status = lsa_secret_set_common(talloc_tos(), key,
|
|
&secret,
|
|
secret_current,
|
|
secret_old,
|
|
sd);
|
|
talloc_free(key);
|
|
|
|
return status;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************/
|
|
|
|
NTSTATUS lsa_secret_delete(const char *secret_name)
|
|
{
|
|
char *key;
|
|
struct lsa_secret secret;
|
|
NTSTATUS status;
|
|
|
|
key = lsa_secret_key(talloc_tos(), secret_name);
|
|
if (!key) {
|
|
return NT_STATUS_NO_MEMORY;
|
|
}
|
|
|
|
status = lsa_secret_get_common(talloc_tos(), secret_name, &secret);
|
|
if (!NT_STATUS_IS_OK(status)) {
|
|
talloc_free(key);
|
|
return status;
|
|
}
|
|
|
|
if (!secrets_delete_entry(key)) {
|
|
talloc_free(key);
|
|
return NT_STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
talloc_free(key);
|
|
|
|
return NT_STATUS_OK;
|
|
}
|