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/>.
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
,
34 struct netlogon_creds_CredentialState
*creds
)
36 enum ndr_err_code ndr_err
;
42 keystr
= talloc_asprintf_strupper_m(mem_ctx
, "%s/%s",
43 SECRETS_SCHANNEL_STATE
,
44 creds
->computer_name
);
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
)) {
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
)));
64 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
67 DEBUG(3,("schannel_store_session_key_tdb: stored schannel info with key %s\n",
70 if (DEBUGLEVEL
>= 10) {
71 NDR_PRINT_DEBUG(netlogon_creds_CredentialState
, creds
);
79 /********************************************************************
80 ********************************************************************/
82 NTSTATUS
schannel_fetch_session_key_tdb(struct tdb_context
*tdb
,
84 const char *computer_name
,
85 struct netlogon_creds_CredentialState
**pcreds
)
89 enum ndr_err_code ndr_err
;
91 struct netlogon_creds_CredentialState
*creds
= NULL
;
96 keystr
= talloc_asprintf_strupper_m(mem_ctx
, "%s/%s",
97 SECRETS_SCHANNEL_STATE
,
100 status
= NT_STATUS_NO_MEMORY
;
104 value
= tdb_fetch_bystring(tdb
, keystr
);
106 DEBUG(0,("schannel_fetch_session_key_tdb: Failed to find entry with key %s\n",
108 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
112 creds
= talloc_zero(mem_ctx
, struct netlogon_creds_CredentialState
);
114 status
= NT_STATUS_NO_MEMORY
;
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
);
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",
134 status
= NT_STATUS_OK
;
140 if (!NT_STATUS_IS_OK(status
)) {
150 /********************************************************************
152 Validate an incoming authenticator against the credentials for the remote
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
,
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
;
176 ret
= tdb_transaction_start(tdb
);
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
,
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
);
215 talloc_steal(mem_ctx
, creds
);
218 tdb_transaction_cancel(tdb
);