ldb: move struct ldb_debug_ops to ldb_private.h
[samba.git] / source3 / passdb / secrets_lsa.c
1 /*
2    Unix SMB/CIFS implementation.
3    Copyright (C) Guenther Deschner    2009
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "includes.h"
20 #include "librpc/gen_ndr/ndr_secrets.h"
21 #include "secrets.h"
22
23 /******************************************************************************
24 *******************************************************************************/
25
26 static char *lsa_secret_key(TALLOC_CTX *mem_ctx,
27                             const char *secret_name)
28 {
29         return talloc_asprintf_strupper_m(mem_ctx, "SECRETS/LSA/%s",
30                                           secret_name);
31 }
32
33 /******************************************************************************
34 *******************************************************************************/
35
36 static NTSTATUS lsa_secret_get_common(TALLOC_CTX *mem_ctx,
37                                       const char *secret_name,
38                                       struct lsa_secret *secret)
39 {
40         char *key;
41         DATA_BLOB blob;
42         enum ndr_err_code ndr_err;
43
44         ZERO_STRUCTP(secret);
45
46         key = lsa_secret_key(mem_ctx, secret_name);
47         if (!key) {
48                 return NT_STATUS_NO_MEMORY;
49         }
50
51         blob.data = (uint8_t *)secrets_fetch(key, &blob.length);
52         talloc_free(key);
53
54         if (!blob.data) {
55                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
56         }
57
58         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, secret,
59                                 (ndr_pull_flags_fn_t)ndr_pull_lsa_secret);
60         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
61                 SAFE_FREE(blob.data);
62                 return ndr_map_error2ntstatus(ndr_err);
63         }
64
65         /* This is NOT a talloc blob */
66         BURN_FREE(blob.data, blob.length);
67
68         if (secret->secret_current != NULL &&
69             secret->secret_current->data != NULL) {
70                 talloc_keep_secret(secret->secret_current->data);
71         }
72         if (secret->secret_old != NULL && secret->secret_old->data != NULL) {
73                 talloc_keep_secret(secret->secret_old->data);
74         }
75
76         return NT_STATUS_OK;
77 }
78
79 /******************************************************************************
80 *******************************************************************************/
81
82 NTSTATUS lsa_secret_get(TALLOC_CTX *mem_ctx,
83                         const char *secret_name,
84                         DATA_BLOB *secret_current,
85                         NTTIME *secret_current_lastchange,
86                         DATA_BLOB *secret_old,
87                         NTTIME *secret_old_lastchange,
88                         struct security_descriptor **sd)
89 {
90         NTSTATUS status;
91         struct lsa_secret secret;
92
93         status = lsa_secret_get_common(mem_ctx, secret_name, &secret);
94         if (!NT_STATUS_IS_OK(status)) {
95                 return status;
96         }
97
98         if (secret_current) {
99                 *secret_current = data_blob_null;
100                 if (secret.secret_current) {
101                         *secret_current = *secret.secret_current;
102                 }
103         }
104         if (secret_current_lastchange) {
105                 *secret_current_lastchange = secret.secret_current_lastchange;
106         }
107         if (secret_old) {
108                 *secret_old = data_blob_null;
109                 if (secret.secret_old) {
110                         *secret_old = *secret.secret_old;
111                 }
112         }
113         if (secret_old_lastchange) {
114                 *secret_old_lastchange = secret.secret_old_lastchange;
115         }
116         if (sd) {
117                 *sd = secret.sd;
118         }
119
120         return NT_STATUS_OK;
121 }
122
123 /******************************************************************************
124 *******************************************************************************/
125
126 static NTSTATUS lsa_secret_set_common(TALLOC_CTX *mem_ctx,
127                                       const char *key,
128                                       struct lsa_secret *secret,
129                                       DATA_BLOB *secret_current,
130                                       DATA_BLOB *secret_old,
131                                       struct security_descriptor *sd)
132 {
133         enum ndr_err_code ndr_err;
134         DATA_BLOB blob;
135         struct timeval now = timeval_current();
136
137         if (!secret) {
138                 secret = talloc_zero(mem_ctx, struct lsa_secret);
139         }
140
141         if (!secret) {
142                 return NT_STATUS_NO_MEMORY;
143         }
144
145         if (secret_old) {
146                 secret->secret_old = secret_old;
147                 secret->secret_old_lastchange = timeval_to_nttime(&now);
148         } else {
149                 if (secret->secret_current) {
150                         secret->secret_old = secret->secret_current;
151                         secret->secret_old_lastchange = secret->secret_current_lastchange;
152                 } else {
153                         secret->secret_old = NULL;
154                         secret->secret_old_lastchange = timeval_to_nttime(&now);
155                 }
156         }
157         if (secret_current) {
158                 secret->secret_current = secret_current;
159                 secret->secret_current_lastchange = timeval_to_nttime(&now);
160         } else {
161                 secret->secret_current = NULL;
162                 secret->secret_current_lastchange = timeval_to_nttime(&now);
163         }
164         if (sd) {
165                 secret->sd = sd;
166         }
167
168         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, secret,
169                                 (ndr_push_flags_fn_t)ndr_push_lsa_secret);
170         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
171                 return ndr_map_error2ntstatus(ndr_err);
172         }
173
174         if (!secrets_store(key, blob.data, blob.length)) {
175                 data_blob_clear(&blob);
176                 return NT_STATUS_ACCESS_DENIED;
177         }
178
179         data_blob_clear(&blob);
180         return NT_STATUS_OK;
181 }
182
183 /******************************************************************************
184 *******************************************************************************/
185
186 NTSTATUS lsa_secret_set(const char *secret_name,
187                         DATA_BLOB *secret_current,
188                         DATA_BLOB *secret_old,
189                         struct security_descriptor *sd)
190 {
191         char *key;
192         struct lsa_secret secret;
193         NTSTATUS status;
194
195         key = lsa_secret_key(talloc_tos(), secret_name);
196         if (!key) {
197                 return NT_STATUS_NO_MEMORY;
198         }
199
200         status = lsa_secret_get_common(talloc_tos(), secret_name, &secret);
201         if (!NT_STATUS_IS_OK(status) &&
202             !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
203                 talloc_free(key);
204                 return status;
205         }
206
207         status = lsa_secret_set_common(talloc_tos(), key,
208                                        &secret,
209                                        secret_current,
210                                        secret_old,
211                                        sd);
212         talloc_free(key);
213
214         return status;
215 }
216
217 /******************************************************************************
218 *******************************************************************************/
219
220 NTSTATUS lsa_secret_delete(const char *secret_name)
221 {
222         char *key;
223         struct lsa_secret secret;
224         NTSTATUS status;
225
226         key = lsa_secret_key(talloc_tos(), secret_name);
227         if (!key) {
228                 return NT_STATUS_NO_MEMORY;
229         }
230
231         status = lsa_secret_get_common(talloc_tos(), secret_name, &secret);
232         if (!NT_STATUS_IS_OK(status)) {
233                 talloc_free(key);
234                 return status;
235         }
236
237         if (!secrets_delete_entry(key)) {
238                 talloc_free(key);
239                 return NT_STATUS_ACCESS_DENIED;
240         }
241
242         talloc_free(key);
243
244         return NT_STATUS_OK;
245 }