s4-smbtorture: skip extended SetValue test against Samba (both dont survive).
[Samba/nascimento.git] / libcli / auth / schannel_state_tdb.c
blobd1e5ed0eccc17f101de1dd2a972a37aebb18a2af
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 <tdb.h>
27 #include "../lib/util/util_tdb.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "../libcli/auth/schannel_state.h"
30 #include "../librpc/gen_ndr/ndr_schannel.h"
31 #if _SAMBA_BUILD_ == 4
32 #include "tdb_wrap.h"
33 #endif
35 #define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
37 /******************************************************************************
38 Open or create the schannel session store tdb.
39 *******************************************************************************/
41 #define SCHANNEL_STORE_VERSION_1 1
42 #define SCHANNEL_STORE_VERSION_2 2 /* should not be used */
43 #define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_1
45 static struct tdb_wrap *open_schannel_session_store(TALLOC_CTX *mem_ctx,
46 const char *private_dir)
48 TDB_DATA vers;
49 uint32_t ver;
50 struct tdb_wrap *tdb_sc = NULL;
51 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", private_dir);
53 if (!fname) {
54 return NULL;
57 tdb_sc = tdb_wrap_open(mem_ctx, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
59 if (!tdb_sc) {
60 DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n",
61 fname, strerror(errno)));
62 TALLOC_FREE(fname);
63 return NULL;
66 again:
67 vers = tdb_fetch_bystring(tdb_sc->tdb, "SCHANNEL_STORE_VERSION");
68 if (vers.dptr == NULL) {
69 /* First opener, no version. */
70 SIVAL(&ver,0,SCHANNEL_STORE_VERSION_CURRENT);
71 vers.dptr = (uint8_t *)&ver;
72 vers.dsize = 4;
73 tdb_store_bystring(tdb_sc->tdb, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE);
74 vers.dptr = NULL;
75 } else if (vers.dsize == 4) {
76 ver = IVAL(vers.dptr,0);
77 if (ver == SCHANNEL_STORE_VERSION_2) {
78 DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
79 (int)ver, fname ));
80 tdb_wipe_all(tdb_sc->tdb);
81 goto again;
83 if (ver != SCHANNEL_STORE_VERSION_CURRENT) {
84 DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n",
85 (int)ver, fname ));
86 TALLOC_FREE(tdb_sc);
88 } else {
89 TALLOC_FREE(tdb_sc);
90 DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n",
91 (int)vers.dsize, fname ));
94 SAFE_FREE(vers.dptr);
95 TALLOC_FREE(fname);
97 return tdb_sc;
100 /********************************************************************
101 ********************************************************************/
103 static
104 NTSTATUS schannel_store_session_key_tdb(struct tdb_wrap *tdb_sc,
105 TALLOC_CTX *mem_ctx,
106 struct smb_iconv_convenience *ic,
107 struct netlogon_creds_CredentialState *creds)
109 enum ndr_err_code ndr_err;
110 DATA_BLOB blob;
111 TDB_DATA value;
112 int ret;
113 char *keystr;
114 char *name_upper;
116 name_upper = strupper_talloc(mem_ctx, creds->computer_name);
117 if (!name_upper) {
118 return NT_STATUS_NO_MEMORY;
121 keystr = talloc_asprintf(mem_ctx, "%s/%s",
122 SECRETS_SCHANNEL_STATE, name_upper);
123 TALLOC_FREE(name_upper);
124 if (!keystr) {
125 return NT_STATUS_NO_MEMORY;
128 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, ic, creds,
129 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 talloc_free(keystr);
132 return ndr_map_error2ntstatus(ndr_err);
135 value.dptr = blob.data;
136 value.dsize = blob.length;
138 ret = tdb_store_bystring(tdb_sc->tdb, keystr, value, TDB_REPLACE);
139 if (ret != TDB_SUCCESS) {
140 DEBUG(0,("Unable to add %s to session key db - %s\n",
141 keystr, tdb_errorstr(tdb_sc->tdb)));
142 talloc_free(keystr);
143 return NT_STATUS_INTERNAL_DB_CORRUPTION;
146 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
147 keystr));
149 if (DEBUGLEVEL >= 10) {
150 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
153 talloc_free(keystr);
155 return NT_STATUS_OK;
158 /********************************************************************
159 ********************************************************************/
161 static
162 NTSTATUS schannel_fetch_session_key_tdb(struct tdb_wrap *tdb_sc,
163 TALLOC_CTX *mem_ctx,
164 struct smb_iconv_convenience *ic,
165 const char *computer_name,
166 struct netlogon_creds_CredentialState **pcreds)
168 NTSTATUS status;
169 TDB_DATA value;
170 enum ndr_err_code ndr_err;
171 DATA_BLOB blob;
172 struct netlogon_creds_CredentialState *creds = NULL;
173 char *keystr = NULL;
174 char *name_upper;
176 *pcreds = NULL;
178 name_upper = strupper_talloc(mem_ctx, computer_name);
179 if (!name_upper) {
180 return NT_STATUS_NO_MEMORY;
183 keystr = talloc_asprintf(mem_ctx, "%s/%s",
184 SECRETS_SCHANNEL_STATE, name_upper);
185 TALLOC_FREE(name_upper);
186 if (!keystr) {
187 status = NT_STATUS_NO_MEMORY;
188 goto done;
191 value = tdb_fetch_bystring(tdb_sc->tdb, keystr);
192 if (!value.dptr) {
193 DEBUG(0,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
194 keystr ));
195 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
196 goto done;
199 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
200 if (!creds) {
201 status = NT_STATUS_NO_MEMORY;
202 goto done;
205 blob = data_blob_const(value.dptr, value.dsize);
207 ndr_err = ndr_pull_struct_blob(&blob, creds, ic, creds,
208 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
209 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
210 status = ndr_map_error2ntstatus(ndr_err);
211 goto done;
214 if (DEBUGLEVEL >= 10) {
215 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
218 DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
219 keystr));
221 status = NT_STATUS_OK;
223 done:
225 talloc_free(keystr);
227 if (!NT_STATUS_IS_OK(status)) {
228 talloc_free(creds);
229 return status;
232 *pcreds = creds;
234 return NT_STATUS_OK;
237 /******************************************************************************
238 Wrapper around schannel_fetch_session_key_tdb()
239 Note we must be root here.
240 *******************************************************************************/
242 NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx,
243 struct smb_iconv_convenience *ic,
244 const char *db_priv_dir,
245 const char *computer_name,
246 struct netlogon_creds_CredentialState **_creds)
248 TALLOC_CTX *tmpctx;
249 struct tdb_wrap *tdb_sc;
250 struct netlogon_creds_CredentialState *creds;
251 NTSTATUS status;
253 tmpctx = talloc_named(mem_ctx, 0, "schannel_get_creds_state");
254 if (!tmpctx) {
255 return NT_STATUS_NO_MEMORY;
258 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
259 if (!tdb_sc) {
260 return NT_STATUS_ACCESS_DENIED;
263 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, ic,
264 computer_name, &creds);
265 if (NT_STATUS_IS_OK(status)) {
266 *_creds = talloc_steal(mem_ctx, creds);
267 if (!*_creds) {
268 status = NT_STATUS_NO_MEMORY;
272 talloc_free(tmpctx);
273 return status;
276 /******************************************************************************
277 Wrapper around schannel_store_session_key_tdb()
278 Note we must be root here.
279 *******************************************************************************/
281 NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx,
282 struct smb_iconv_convenience *ic,
283 const char *db_priv_dir,
284 struct netlogon_creds_CredentialState *creds)
286 TALLOC_CTX *tmpctx;
287 struct tdb_wrap *tdb_sc;
288 NTSTATUS status;
290 tmpctx = talloc_named(mem_ctx, 0, "schannel_save_creds_state");
291 if (!tmpctx) {
292 return NT_STATUS_NO_MEMORY;
295 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
296 if (!tdb_sc) {
297 return NT_STATUS_ACCESS_DENIED;
300 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, ic, creds);
302 talloc_free(tmpctx);
303 return status;
306 /********************************************************************
307 Validate an incoming authenticator against the credentials for the
308 remote machine stored in the schannel database.
310 The credentials are (re)read and from the schannel database, and
311 written back after the caclulations are performed.
313 If the creds_out parameter is not NULL returns the credentials.
314 ********************************************************************/
316 NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
317 struct smb_iconv_convenience *ic,
318 const char *db_priv_dir,
319 const char *computer_name,
320 struct netr_Authenticator *received_authenticator,
321 struct netr_Authenticator *return_authenticator,
322 struct netlogon_creds_CredentialState **creds_out)
324 TALLOC_CTX *tmpctx;
325 struct tdb_wrap *tdb_sc;
326 struct netlogon_creds_CredentialState *creds;
327 NTSTATUS status;
328 int ret;
330 tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
331 if (!tmpctx) {
332 return NT_STATUS_NO_MEMORY;
335 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
336 if (!tdb_sc) {
337 status = NT_STATUS_ACCESS_DENIED;
338 goto done;
341 ret = tdb_transaction_start(tdb_sc->tdb);
342 if (ret != 0) {
343 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
344 goto done;
347 /* Because this is a shared structure (even across
348 * disconnects) we must update the database every time we
349 * update the structure */
351 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, ic,
352 computer_name, &creds);
353 if (!NT_STATUS_IS_OK(status)) {
354 tdb_transaction_cancel(tdb_sc->tdb);
355 goto done;
358 status = netlogon_creds_server_step_check(creds,
359 received_authenticator,
360 return_authenticator);
361 if (!NT_STATUS_IS_OK(status)) {
362 tdb_transaction_cancel(tdb_sc->tdb);
363 goto done;
366 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, ic, creds);
367 if (!NT_STATUS_IS_OK(status)) {
368 tdb_transaction_cancel(tdb_sc->tdb);
369 goto done;
372 tdb_transaction_commit(tdb_sc->tdb);
374 if (creds_out) {
375 *creds_out = talloc_steal(mem_ctx, creds);
376 if (!*creds_out) {
377 status = NT_STATUS_NO_MEMORY;
378 goto done;
382 status = NT_STATUS_OK;
384 done:
385 talloc_free(tmpctx);
386 return status;