s3-docs: Fix typo in man idmap_ad.
[Samba.git] / libcli / auth / schannel_state_tdb.c
blob7ec8b3fdea0e5296b67f5a985c2f16f1349a82f4
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 "../libcli/auth/libcli_auth.h"
26 #include "../libcli/auth/schannel_state.h"
27 #include "../librpc/gen_ndr/ndr_schannel.h"
29 /********************************************************************
30 ********************************************************************/
32 NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb,
33 TALLOC_CTX *mem_ctx,
34 struct netlogon_creds_CredentialState *creds)
36 enum ndr_err_code ndr_err;
37 DATA_BLOB blob;
38 TDB_DATA value;
39 int ret;
40 char *keystr;
42 keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
43 SECRETS_SCHANNEL_STATE,
44 creds->computer_name);
45 if (!keystr) {
46 return NT_STATUS_NO_MEMORY;
49 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, creds,
50 (ndr_push_flags_fn_t)ndr_push_netlogon_creds_CredentialState);
51 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
52 talloc_free(keystr);
53 return ndr_map_error2ntstatus(ndr_err);
56 value.dptr = blob.data;
57 value.dsize = blob.length;
59 ret = tdb_store_bystring(tdb, keystr, value, TDB_REPLACE);
60 if (ret != TDB_SUCCESS) {
61 DEBUG(0,("Unable to add %s to session key db - %s\n",
62 keystr, tdb_errorstr(tdb)));
63 talloc_free(keystr);
64 return NT_STATUS_INTERNAL_DB_CORRUPTION;
67 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
68 keystr));
70 if (DEBUGLEVEL >= 10) {
71 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
74 talloc_free(keystr);
76 return NT_STATUS_OK;
79 /********************************************************************
80 ********************************************************************/
82 NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb,
83 TALLOC_CTX *mem_ctx,
84 const char *computer_name,
85 struct netlogon_creds_CredentialState **pcreds)
87 NTSTATUS status;
88 TDB_DATA value;
89 enum ndr_err_code ndr_err;
90 DATA_BLOB blob;
91 struct netlogon_creds_CredentialState *creds = NULL;
92 char *keystr = NULL;
94 *pcreds = NULL;
96 keystr = talloc_asprintf_strupper_m(mem_ctx, "%s/%s",
97 SECRETS_SCHANNEL_STATE,
98 computer_name);
99 if (!keystr) {
100 status = NT_STATUS_NO_MEMORY;
101 goto done;
104 value = tdb_fetch_bystring(tdb, keystr);
105 if (!value.dptr) {
106 DEBUG(0,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
107 keystr ));
108 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
109 goto done;
112 creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
113 if (!creds) {
114 status = NT_STATUS_NO_MEMORY;
115 goto done;
118 blob = data_blob_const(value.dptr, value.dsize);
120 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, creds,
121 (ndr_pull_flags_fn_t)ndr_pull_netlogon_creds_CredentialState);
122 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
123 status = ndr_map_error2ntstatus(ndr_err);
124 goto done;
127 if (DEBUGLEVEL >= 10) {
128 NDR_PRINT_DEBUG(netlogon_creds_CredentialState, creds);
131 DEBUG(3,("schannel_fetch_session_key_tdb: restored schannel info key %s\n",
132 keystr));
134 status = NT_STATUS_OK;
136 done:
138 talloc_free(keystr);
140 if (!NT_STATUS_IS_OK(status)) {
141 talloc_free(creds);
142 return status;
145 *pcreds = creds;
147 return NT_STATUS_OK;
150 /********************************************************************
152 Validate an incoming authenticator against the credentials for the remote
153 machine.
155 The credentials are (re)read and from the schannel database, and
156 written back after the caclulations are performed.
158 The creds_out parameter (if not NULL) returns the credentials, if
159 the caller needs some of that information.
161 ********************************************************************/
163 NTSTATUS schannel_creds_server_step_check_tdb(struct tdb_context *tdb,
164 TALLOC_CTX *mem_ctx,
165 const char *computer_name,
166 bool schannel_required_for_call,
167 bool schannel_in_use,
168 struct netr_Authenticator *received_authenticator,
169 struct netr_Authenticator *return_authenticator,
170 struct netlogon_creds_CredentialState **creds_out)
172 struct netlogon_creds_CredentialState *creds;
173 NTSTATUS status;
174 int ret;
176 ret = tdb_transaction_start(tdb);
177 if (ret != 0) {
178 return NT_STATUS_INTERNAL_DB_CORRUPTION;
181 /* Because this is a shared structure (even across
182 * disconnects) we must update the database every time we
183 * update the structure */
185 status = schannel_fetch_session_key_tdb(tdb, mem_ctx, computer_name,
186 &creds);
188 /* If we are flaged that schannel is required for a call, and
189 * it is not in use, then make this an error */
191 /* It would be good to make this mandatory once schannel is
192 * negotiated, but this is not what windows does */
193 if (schannel_required_for_call && !schannel_in_use) {
194 DEBUG(0,("schannel_creds_server_step_check_tdb: "
195 "client %s not using schannel for netlogon, despite negotiating it\n",
196 creds->computer_name ));
197 tdb_transaction_cancel(tdb);
198 return NT_STATUS_ACCESS_DENIED;
201 if (NT_STATUS_IS_OK(status)) {
202 status = netlogon_creds_server_step_check(creds,
203 received_authenticator,
204 return_authenticator);
207 if (NT_STATUS_IS_OK(status)) {
208 status = schannel_store_session_key_tdb(tdb, mem_ctx, creds);
211 if (NT_STATUS_IS_OK(status)) {
212 tdb_transaction_commit(tdb);
213 if (creds_out) {
214 *creds_out = creds;
215 talloc_steal(mem_ctx, creds);
217 } else {
218 tdb_transaction_cancel(tdb);
221 return status;