build: list winbindd sources in definition and remove vars=locals()
[Samba.git] / libcli / auth / schannel_state_tdb.c
blob8c893ee08eedc726ac4870bf1ccccf3ddfd9ce95
1 /*
2 Unix SMB/CIFS implementation.
4 module to store/fetch session keys for the schannel server
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2009
8 Copyright (C) Guenther Deschner 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "system/filesys.h"
26 #include "../lib/tdb/include/tdb.h"
27 #include "../lib/util/util_tdb.h"
28 #include "../lib/param/param.h"
29 #include "../libcli/auth/schannel.h"
30 #include "../librpc/gen_ndr/ndr_schannel.h"
31 #include "lib/dbwrap/dbwrap.h"
33 #define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
35 /******************************************************************************
36 Open or create the schannel session store tdb. Non-static so it can
37 be called from parent processes to corectly handle TDB_CLEAR_IF_FIRST
38 *******************************************************************************/
40 struct db_context *open_schannel_session_store(TALLOC_CTX *mem_ctx,
41 struct loadparm_context *lp_ctx)
43 struct db_context *db_sc = NULL;
44 char *fname = lpcfg_private_db_path(mem_ctx, lp_ctx, "schannel_store");
46 if (!fname) {
47 return NULL;
50 db_sc = dbwrap_local_open(mem_ctx, lp_ctx, fname, 0,
51 TDB_CLEAR_IF_FIRST|TDB_NOSYNC, O_RDWR|O_CREAT,
52 0600, 0);
54 if (!db_sc) {
55 DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n",
56 fname, strerror(errno)));
57 TALLOC_FREE(fname);
58 return NULL;
61 TALLOC_FREE(fname);
63 return db_sc;
66 /********************************************************************
67 ********************************************************************/
69 static
70 NTSTATUS schannel_store_session_key_tdb(struct db_context *db_sc,
71 TALLOC_CTX *mem_ctx,
72 struct netlogon_creds_CredentialState *creds)
74 enum ndr_err_code ndr_err;
75 DATA_BLOB blob;
76 TDB_DATA value;
77 char *keystr;
78 char *name_upper;
79 NTSTATUS status;
81 name_upper = strupper_talloc(mem_ctx, creds->computer_name);
82 if (!name_upper) {
83 return NT_STATUS_NO_MEMORY;
86 keystr = talloc_asprintf(mem_ctx, "%s/%s",
87 SECRETS_SCHANNEL_STATE, name_upper);
88 TALLOC_FREE(name_upper);
89 if (!keystr) {
90 return NT_STATUS_NO_MEMORY;
93 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, creds,
94 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
95 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
96 talloc_free(keystr);
97 return ndr_map_error2ntstatus(ndr_err);
100 value.dptr = blob.data;
101 value.dsize = blob.length;
103 status = dbwrap_store_bystring(db_sc, keystr, value, TDB_REPLACE);
104 if (!NT_STATUS_IS_OK(status)) {
105 DEBUG(0,("Unable to add %s to session key db - %s\n",
106 keystr, nt_errstr(status)));
107 talloc_free(keystr);
108 return status;
111 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
112 keystr));
114 if (DEBUGLEVEL >= 10) {
115 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
118 talloc_free(keystr);
120 return NT_STATUS_OK;
123 /********************************************************************
124 ********************************************************************/
126 static
127 NTSTATUS schannel_fetch_session_key_tdb(struct db_context *db_sc,
128 TALLOC_CTX *mem_ctx,
129 const char *computer_name,
130 struct netlogon_creds_CredentialState **pcreds)
132 NTSTATUS status;
133 TDB_DATA value;
134 enum ndr_err_code ndr_err;
135 DATA_BLOB blob;
136 struct netlogon_creds_CredentialState *creds = NULL;
137 char *keystr = NULL;
138 char *name_upper;
140 *pcreds = NULL;
142 name_upper = strupper_talloc(mem_ctx, computer_name);
143 if (!name_upper) {
144 return NT_STATUS_NO_MEMORY;
147 keystr = talloc_asprintf(mem_ctx, "%s/%s",
148 SECRETS_SCHANNEL_STATE, name_upper);
149 TALLOC_FREE(name_upper);
150 if (!keystr) {
151 return NT_STATUS_NO_MEMORY;
154 status = dbwrap_fetch_bystring(db_sc, keystr, keystr, &value);
155 if (!NT_STATUS_IS_OK(status)) {
156 DEBUG(10,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
157 keystr ));
158 goto done;
161 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
162 if (!creds) {
163 status = NT_STATUS_NO_MEMORY;
164 goto done;
167 blob = data_blob_const(value.dptr, value.dsize);
169 ndr_err = ndr_pull_struct_blob(&blob, creds, creds,
170 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
171 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
172 status = ndr_map_error2ntstatus(ndr_err);
173 goto done;
176 if (DEBUGLEVEL >= 10) {
177 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
180 DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
181 keystr));
183 status = NT_STATUS_OK;
185 done:
187 talloc_free(keystr);
189 if (!NT_STATUS_IS_OK(status)) {
190 talloc_free(creds);
191 return status;
194 *pcreds = creds;
196 return NT_STATUS_OK;
199 /******************************************************************************
200 Wrapper around schannel_fetch_session_key_tdb()
201 Note we must be root here.
202 *******************************************************************************/
204 NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx,
205 struct loadparm_context *lp_ctx,
206 const char *computer_name,
207 struct netlogon_creds_CredentialState **_creds)
209 TALLOC_CTX *tmpctx;
210 struct db_context *db_sc;
211 struct netlogon_creds_CredentialState *creds;
212 NTSTATUS status;
214 tmpctx = talloc_named(mem_ctx, 0, "schannel_get_creds_state");
215 if (!tmpctx) {
216 return NT_STATUS_NO_MEMORY;
219 db_sc = open_schannel_session_store(tmpctx, lp_ctx);
220 if (!db_sc) {
221 return NT_STATUS_ACCESS_DENIED;
224 status = schannel_fetch_session_key_tdb(db_sc, tmpctx,
225 computer_name, &creds);
226 if (NT_STATUS_IS_OK(status)) {
227 *_creds = talloc_steal(mem_ctx, creds);
228 if (!*_creds) {
229 status = NT_STATUS_NO_MEMORY;
233 talloc_free(tmpctx);
234 return status;
237 /******************************************************************************
238 Wrapper around schannel_store_session_key_tdb()
239 Note we must be root here.
240 *******************************************************************************/
242 NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx,
243 struct loadparm_context *lp_ctx,
244 struct netlogon_creds_CredentialState *creds)
246 TALLOC_CTX *tmpctx;
247 struct db_context *db_sc;
248 NTSTATUS status;
250 tmpctx = talloc_named(mem_ctx, 0, "schannel_save_creds_state");
251 if (!tmpctx) {
252 return NT_STATUS_NO_MEMORY;
255 db_sc = open_schannel_session_store(tmpctx, lp_ctx);
256 if (!db_sc) {
257 return NT_STATUS_ACCESS_DENIED;
260 status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
262 talloc_free(tmpctx);
263 return status;
266 /********************************************************************
267 Validate an incoming authenticator against the credentials for the
268 remote machine stored in the schannel database.
270 The credentials are (re)read and from the schannel database, and
271 written back after the caclulations are performed.
273 If the creds_out parameter is not NULL returns the credentials.
274 ********************************************************************/
276 NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
277 struct loadparm_context *lp_ctx,
278 const char *computer_name,
279 struct netr_Authenticator *received_authenticator,
280 struct netr_Authenticator *return_authenticator,
281 struct netlogon_creds_CredentialState **creds_out)
283 TALLOC_CTX *tmpctx;
284 struct db_context *db_sc;
285 struct netlogon_creds_CredentialState *creds;
286 NTSTATUS status;
287 char *name_upper = NULL;
288 char *keystr = NULL;
289 struct db_record *record;
290 TDB_DATA key;
292 if (creds_out != NULL) {
293 *creds_out = NULL;
296 tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
297 if (!tmpctx) {
298 return NT_STATUS_NO_MEMORY;
301 name_upper = strupper_talloc(tmpctx, computer_name);
302 if (!name_upper) {
303 status = NT_STATUS_NO_MEMORY;
304 goto done;
307 keystr = talloc_asprintf(tmpctx, "%s/%s",
308 SECRETS_SCHANNEL_STATE, name_upper);
309 if (!keystr) {
310 status = NT_STATUS_NO_MEMORY;
311 goto done;
314 key = string_term_tdb_data(keystr);
316 db_sc = open_schannel_session_store(tmpctx, lp_ctx);
317 if (!db_sc) {
318 status = NT_STATUS_ACCESS_DENIED;
319 goto done;
322 record = dbwrap_fetch_locked(db_sc, tmpctx, key);
323 if (!record) {
324 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
325 goto done;
328 /* Because this is a shared structure (even across
329 * disconnects) we must update the database every time we
330 * update the structure */
332 status = schannel_fetch_session_key_tdb(db_sc, tmpctx,
333 computer_name, &creds);
334 if (!NT_STATUS_IS_OK(status)) {
335 goto done;
338 status = netlogon_creds_server_step_check(creds,
339 received_authenticator,
340 return_authenticator);
341 if (!NT_STATUS_IS_OK(status)) {
342 goto done;
345 status = schannel_store_session_key_tdb(db_sc, tmpctx, creds);
346 if (!NT_STATUS_IS_OK(status)) {
347 goto done;
350 if (creds_out) {
351 *creds_out = talloc_steal(mem_ctx, creds);
352 if (!*creds_out) {
353 status = NT_STATUS_NO_MEMORY;
354 goto done;
358 status = NT_STATUS_OK;
360 done:
361 talloc_free(tmpctx);
362 return status;