socket_wrapper: fix compiler warnings
[Samba/gbeck.git] / libcli / auth / schannel_state_tdb.c
blobc332bae8baa29e2c0db3ac255cf8dfaf120acb2c
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/schannel.h"
29 #include "../librpc/gen_ndr/ndr_schannel.h"
30 #if _SAMBA_BUILD_ == 4
31 #include "tdb_wrap.h"
32 #endif
34 #define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
36 /******************************************************************************
37 Open or create the schannel session store tdb. Non-static so it can
38 be called from parent processes to corectly handle TDB_CLEAR_IF_FIRST
39 *******************************************************************************/
41 struct tdb_wrap *open_schannel_session_store(TALLOC_CTX *mem_ctx,
42 const char *private_dir)
44 struct tdb_wrap *tdb_sc = NULL;
45 char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", private_dir);
47 if (!fname) {
48 return NULL;
51 tdb_sc = tdb_wrap_open(mem_ctx, fname, 0, TDB_CLEAR_IF_FIRST|TDB_NOSYNC, O_RDWR|O_CREAT, 0600);
53 if (!tdb_sc) {
54 DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n",
55 fname, strerror(errno)));
56 TALLOC_FREE(fname);
57 return NULL;
60 TALLOC_FREE(fname);
62 return tdb_sc;
65 /********************************************************************
66 ********************************************************************/
68 static
69 NTSTATUS schannel_store_session_key_tdb(struct tdb_wrap *tdb_sc,
70 TALLOC_CTX *mem_ctx,
71 struct netlogon_creds_CredentialState *creds)
73 enum ndr_err_code ndr_err;
74 DATA_BLOB blob;
75 TDB_DATA value;
76 int ret;
77 char *keystr;
78 char *name_upper;
80 name_upper = strupper_talloc(mem_ctx, creds->computer_name);
81 if (!name_upper) {
82 return NT_STATUS_NO_MEMORY;
85 keystr = talloc_asprintf(mem_ctx, "%s/%s",
86 SECRETS_SCHANNEL_STATE, name_upper);
87 TALLOC_FREE(name_upper);
88 if (!keystr) {
89 return NT_STATUS_NO_MEMORY;
92 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, creds,
93 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
94 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
95 talloc_free(keystr);
96 return ndr_map_error2ntstatus(ndr_err);
99 value.dptr = blob.data;
100 value.dsize = blob.length;
102 ret = tdb_store_bystring(tdb_sc->tdb, keystr, value, TDB_REPLACE);
103 if (ret != TDB_SUCCESS) {
104 DEBUG(0,("Unable to add %s to session key db - %s\n",
105 keystr, tdb_errorstr(tdb_sc->tdb)));
106 talloc_free(keystr);
107 return NT_STATUS_INTERNAL_DB_CORRUPTION;
110 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
111 keystr));
113 if (DEBUGLEVEL >= 10) {
114 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
117 talloc_free(keystr);
119 return NT_STATUS_OK;
122 /********************************************************************
123 ********************************************************************/
125 static
126 NTSTATUS schannel_fetch_session_key_tdb(struct tdb_wrap *tdb_sc,
127 TALLOC_CTX *mem_ctx,
128 const char *computer_name,
129 struct netlogon_creds_CredentialState **pcreds)
131 NTSTATUS status;
132 TDB_DATA value;
133 enum ndr_err_code ndr_err;
134 DATA_BLOB blob;
135 struct netlogon_creds_CredentialState *creds = NULL;
136 char *keystr = NULL;
137 char *name_upper;
139 *pcreds = NULL;
141 name_upper = strupper_talloc(mem_ctx, computer_name);
142 if (!name_upper) {
143 return NT_STATUS_NO_MEMORY;
146 keystr = talloc_asprintf(mem_ctx, "%s/%s",
147 SECRETS_SCHANNEL_STATE, name_upper);
148 TALLOC_FREE(name_upper);
149 if (!keystr) {
150 return NT_STATUS_NO_MEMORY;
153 value = tdb_fetch_bystring(tdb_sc->tdb, keystr);
154 if (!value.dptr) {
155 DEBUG(10,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
156 keystr ));
157 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
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);
188 SAFE_FREE(value.dptr);
190 if (!NT_STATUS_IS_OK(status)) {
191 talloc_free(creds);
192 return status;
195 *pcreds = creds;
197 return NT_STATUS_OK;
200 /******************************************************************************
201 Wrapper around schannel_fetch_session_key_tdb()
202 Note we must be root here.
203 *******************************************************************************/
205 NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx,
206 const char *db_priv_dir,
207 const char *computer_name,
208 struct netlogon_creds_CredentialState **_creds)
210 TALLOC_CTX *tmpctx;
211 struct tdb_wrap *tdb_sc;
212 struct netlogon_creds_CredentialState *creds;
213 NTSTATUS status;
215 tmpctx = talloc_named(mem_ctx, 0, "schannel_get_creds_state");
216 if (!tmpctx) {
217 return NT_STATUS_NO_MEMORY;
220 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
221 if (!tdb_sc) {
222 return NT_STATUS_ACCESS_DENIED;
225 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx,
226 computer_name, &creds);
227 if (NT_STATUS_IS_OK(status)) {
228 *_creds = talloc_steal(mem_ctx, creds);
229 if (!*_creds) {
230 status = NT_STATUS_NO_MEMORY;
234 talloc_free(tmpctx);
235 return status;
238 /******************************************************************************
239 Wrapper around schannel_store_session_key_tdb()
240 Note we must be root here.
241 *******************************************************************************/
243 NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx,
244 const char *db_priv_dir,
245 struct netlogon_creds_CredentialState *creds)
247 TALLOC_CTX *tmpctx;
248 struct tdb_wrap *tdb_sc;
249 NTSTATUS status;
251 tmpctx = talloc_named(mem_ctx, 0, "schannel_save_creds_state");
252 if (!tmpctx) {
253 return NT_STATUS_NO_MEMORY;
256 tdb_sc = open_schannel_session_store(tmpctx, db_priv_dir);
257 if (!tdb_sc) {
258 return NT_STATUS_ACCESS_DENIED;
261 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
263 talloc_free(tmpctx);
264 return status;
267 /********************************************************************
268 Validate an incoming authenticator against the credentials for the
269 remote machine stored in the schannel database.
271 The credentials are (re)read and from the schannel database, and
272 written back after the caclulations are performed.
274 If the creds_out parameter is not NULL returns the credentials.
275 ********************************************************************/
277 NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
278 const char *db_priv_dir,
279 const char *computer_name,
280 struct netr_Authenticator *received_authenticator,
281 struct netr_Authenticator *return_authenticator,
282 struct netlogon_creds_CredentialState **creds_out)
284 TALLOC_CTX *tmpctx;
285 struct tdb_wrap *tdb_sc;
286 struct netlogon_creds_CredentialState *creds;
287 NTSTATUS status;
288 int ret;
290 tmpctx = talloc_named(mem_ctx, 0, "schannel_check_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 status = NT_STATUS_ACCESS_DENIED;
298 goto done;
301 ret = tdb_transaction_start(tdb_sc->tdb);
302 if (ret != 0) {
303 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
304 goto done;
307 /* Because this is a shared structure (even across
308 * disconnects) we must update the database every time we
309 * update the structure */
311 status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx,
312 computer_name, &creds);
313 if (!NT_STATUS_IS_OK(status)) {
314 tdb_transaction_cancel(tdb_sc->tdb);
315 goto done;
318 status = netlogon_creds_server_step_check(creds,
319 received_authenticator,
320 return_authenticator);
321 if (!NT_STATUS_IS_OK(status)) {
322 tdb_transaction_cancel(tdb_sc->tdb);
323 goto done;
326 status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
327 if (!NT_STATUS_IS_OK(status)) {
328 tdb_transaction_cancel(tdb_sc->tdb);
329 goto done;
332 tdb_transaction_commit(tdb_sc->tdb);
334 if (creds_out) {
335 *creds_out = talloc_steal(mem_ctx, creds);
336 if (!*creds_out) {
337 status = NT_STATUS_NO_MEMORY;
338 goto done;
342 status = NT_STATUS_OK;
344 done:
345 talloc_free(tmpctx);
346 return status;