From 51481c5912288368fd9c8ed4aebbe22a2a330ddc Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 17 Feb 2011 16:10:28 +0100 Subject: s3-secrets: add lsa_secret passdb api. Guenther --- source3/passdb/pdb_interface.c | 14 ++- source3/passdb/secrets_lsa.c | 234 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 source3/passdb/secrets_lsa.c (limited to 'source3/passdb') diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 11c186a398..c92b22ae99 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -2328,7 +2328,12 @@ static NTSTATUS pdb_default_get_secret(struct pdb_methods *methods, NTTIME *secret_old_lastchange, struct security_descriptor **sd) { - return NT_STATUS_NOT_SUPPORTED; + return lsa_secret_get(mem_ctx, secret_name, + secret_current, + secret_current_lastchange, + secret_old, + secret_old_lastchange, + sd); } static NTSTATUS pdb_default_set_secret(struct pdb_methods *methods, @@ -2337,13 +2342,16 @@ static NTSTATUS pdb_default_set_secret(struct pdb_methods *methods, DATA_BLOB *secret_old, struct security_descriptor *sd) { - return NT_STATUS_NOT_SUPPORTED; + return lsa_secret_set(secret_name, + secret_current, + secret_old, + sd); } static NTSTATUS pdb_default_delete_secret(struct pdb_methods *methods, const char *secret_name) { - return NT_STATUS_NOT_SUPPORTED; + return lsa_secret_delete(secret_name); } /******************************************************************* diff --git a/source3/passdb/secrets_lsa.c b/source3/passdb/secrets_lsa.c new file mode 100644 index 0000000000..a40942cf7b --- /dev/null +++ b/source3/passdb/secrets_lsa.c @@ -0,0 +1,234 @@ +/* + 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 . +*/ + +#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); + } + + SAFE_FREE(blob.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)) { + return NT_STATUS_ACCESS_DENIED; + } + + 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(key)) { + talloc_free(key); + return NT_STATUS_ACCESS_DENIED; + } + + talloc_free(key); + + return NT_STATUS_OK; +} -- cgit