diff options
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/include/secrets.h | 14 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 14 | ||||
-rw-r--r-- | source3/passdb/secrets_lsa.c | 234 | ||||
-rwxr-xr-x | source3/wscript_build | 2 |
5 files changed, 262 insertions, 5 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index f0718cef6b..ff2d433f82 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -520,7 +520,8 @@ LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o ../auth/kerberos/ LIBADS_PRINTER_OBJ = libads/ldap_printer.o SECRETS_OBJ = passdb/secrets.o passdb/machine_account_secrets.o passdb/machine_sid.o \ - librpc/gen_ndr/ndr_secrets.o + librpc/gen_ndr/ndr_secrets.o \ + passdb/secrets_lsa.o LIBNBT_OBJ = ../libcli/nbt/nbtname.o \ ../libcli/netlogon/netlogon.o \ diff --git a/source3/include/secrets.h b/source3/include/secrets.h index 01e635c580..4c23335b58 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -125,4 +125,18 @@ bool secrets_store_generic(const char *owner, const char *key, const char *secre char *secrets_fetch_generic(const char *owner, const char *key); bool secrets_delete_generic(const char *owner, const char *key); +/* The following definitions come from passdb/secrets_lsa.c */ +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 lsa_secret_set(const char *secret_name, + DATA_BLOB *secret_current, + DATA_BLOB *secret_old, + struct security_descriptor *sd); +NTSTATUS lsa_secret_delete(const char *secret_name); + #endif /* _SECRETS_H */ 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 <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); + } + + 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; +} diff --git a/source3/wscript_build b/source3/wscript_build index 296e6b97f7..3be15ea02c 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -114,7 +114,7 @@ LIBADS_SERVER_SRC = '''libads/kerberos_verify.c libads/authdata.c''' LIBADS_PRINTER_SRC = '''libads/ldap_printer.c''' SECRETS_SRC = '''passdb/secrets.c passdb/machine_account_secrets.c - passdb/machine_sid.c''' + passdb/machine_sid.c passdb/secrets_lsa.c''' LIBNMB_SRC = '''libsmb/unexpected.c libsmb/namecache.c libsmb/nmblib.c libsmb/namequery.c libsmb/conncache.c |