2 Unix SMB/CIFS implementation.
3 Authenticate against a netlogon pipe listening on a unix domain socket
4 Copyright (C) Volker Lendecke 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "../libcli/auth/libcli_auth.h"
22 #include "../librpc/gen_ndr/ndr_netlogon.h"
23 #include "librpc/gen_ndr/ndr_schannel.h"
24 #include "rpc_client/cli_pipe.h"
25 #include "rpc_client/cli_netlogon.h"
28 #include "tldap_util.h"
31 #define DBGC_CLASS DBGC_AUTH
33 static bool secrets_store_local_schannel_creds(
34 const struct netlogon_creds_CredentialState
*creds
)
37 enum ndr_err_code ndr_err
;
40 ndr_err
= ndr_push_struct_blob(
41 &blob
, talloc_tos(), creds
,
42 (ndr_push_flags_fn_t
)ndr_push_netlogon_creds_CredentialState
);
43 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
44 DEBUG(10, ("ndr_push_netlogon_creds_CredentialState failed: "
45 "%s\n", ndr_errstr(ndr_err
)));
48 ret
= secrets_store(SECRETS_LOCAL_SCHANNEL_KEY
,
49 blob
.data
, blob
.length
);
50 data_blob_free(&blob
);
54 static struct netlogon_creds_CredentialState
*
55 secrets_fetch_local_schannel_creds(TALLOC_CTX
*mem_ctx
)
57 struct netlogon_creds_CredentialState
*creds
;
58 enum ndr_err_code ndr_err
;
61 blob
.data
= (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY
,
63 if (blob
.data
== NULL
) {
64 DEBUG(10, ("secrets_fetch failed\n"));
68 creds
= talloc(mem_ctx
, struct netlogon_creds_CredentialState
);
70 DEBUG(10, ("talloc failed\n"));
74 ndr_err
= ndr_pull_struct_blob(
76 (ndr_pull_flags_fn_t
)ndr_pull_netlogon_creds_CredentialState
);
78 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
79 DEBUG(10, ("ndr_pull_netlogon_creds_CredentialState failed: "
80 "%s\n", ndr_errstr(ndr_err
)));
88 static NTSTATUS
netlogond_validate(TALLOC_CTX
*mem_ctx
,
89 const struct auth_context
*auth_context
,
90 const char *ncalrpc_sockname
,
91 struct netlogon_creds_CredentialState
*creds
,
92 const struct auth_usersupplied_info
*user_info
,
93 struct netr_SamInfo3
**pinfo3
,
94 NTSTATUS
*schannel_bind_result
)
96 struct rpc_pipe_client
*p
= NULL
;
97 struct pipe_auth_data
*auth
= NULL
;
98 struct netr_SamInfo3
*info3
= NULL
;
101 *schannel_bind_result
= NT_STATUS_OK
;
103 status
= rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpc_sockname
,
104 &ndr_table_netlogon
.syntax_id
, &p
);
105 if (!NT_STATUS_IS_OK(status
)) {
106 DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
113 status
= rpccli_schannel_bind_data(p
, lp_workgroup(),
114 DCERPC_AUTH_LEVEL_PRIVACY
,
116 if (!NT_STATUS_IS_OK(status
)) {
117 DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n",
123 status
= rpc_pipe_bind(p
, auth
);
124 if (!NT_STATUS_IS_OK(status
)) {
125 DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status
)));
127 *schannel_bind_result
= status
;
131 status
= rpccli_netlogon_sam_network_logon_ex(
133 user_info
->logon_parameters
, /* flags such as 'allow
134 * workstation logon' */
135 global_myname(), /* server name */
136 user_info
->client
.account_name
, /* user name logging on. */
137 user_info
->client
.domain_name
, /* domain name */
138 user_info
->workstation_name
, /* workstation name */
139 (uchar
*)auth_context
->challenge
.data
, /* 8 byte challenge. */
140 3, /* validation level */
141 user_info
->password
.response
.lanman
, /* lanman 24 byte response */
142 user_info
->password
.response
.nt
, /* nt 24 byte response */
143 &info3
); /* info3 out */
145 DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n",
148 if (!NT_STATUS_IS_OK(status
)) {
153 *pinfo3
= talloc_move(mem_ctx
, &info3
);
159 static NTSTATUS
get_ldapi_ctx(TALLOC_CTX
*mem_ctx
, struct tldap_context
**pld
)
161 struct tldap_context
*ld
;
162 struct sockaddr_un addr
;
168 sockaddr
= talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
170 if (sockaddr
== NULL
) {
171 DEBUG(10, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY
;
176 addr
.sun_family
= AF_UNIX
;
177 strncpy(addr
.sun_path
, sockaddr
, sizeof(addr
.sun_path
));
178 TALLOC_FREE(sockaddr
);
180 status
= open_socket_out((struct sockaddr_storage
*)(void *)&addr
,
182 if (!NT_STATUS_IS_OK(status
)) {
183 DEBUG(10, ("Could not connect to %s: %s\n", addr
.sun_path
,
187 set_blocking(fd
, false);
189 ld
= tldap_context_create(mem_ctx
, fd
);
192 return NT_STATUS_NO_MEMORY
;
194 res
= tldap_fetch_rootdse(ld
);
195 if (res
!= TLDAP_SUCCESS
) {
196 DEBUG(10, ("tldap_fetch_rootdse failed: %s\n",
197 tldap_errstr(talloc_tos(), ld
, res
)));
199 return NT_STATUS_LDAP(res
);
202 return NT_STATUS_OK
;;
205 static NTSTATUS
mymachinepw(uint8_t pwd
[16])
207 TALLOC_CTX
*frame
= talloc_stackframe();
208 struct tldap_context
*ld
;
209 struct tldap_message
*rootdse
, **msg
;
210 const char *attrs
[1] = { "unicodePwd" };
211 char *default_nc
, *myname
;
216 status
= get_ldapi_ctx(talloc_tos(), &ld
);
217 if (!NT_STATUS_IS_OK(status
)) {
220 rootdse
= tldap_rootdse(ld
);
221 if (rootdse
== NULL
) {
222 DEBUG(10, ("Could not get rootdse\n"));
223 status
= NT_STATUS_INTERNAL_ERROR
;
226 default_nc
= tldap_talloc_single_attribute(
227 rootdse
, "defaultNamingContext", talloc_tos());
228 if (default_nc
== NULL
) {
229 DEBUG(10, ("Could not get defaultNamingContext\n"));
230 status
= NT_STATUS_NO_MEMORY
;
233 DEBUG(10, ("default_nc = %s\n", default_nc
));
235 myname
= talloc_asprintf_strupper_m(talloc_tos(), "%s$",
237 if (myname
== NULL
) {
238 DEBUG(10, ("talloc failed\n"));
239 status
= NT_STATUS_NO_MEMORY
;
243 rc
= tldap_search_fmt(
244 ld
, default_nc
, TLDAP_SCOPE_SUB
, attrs
, ARRAY_SIZE(attrs
), 0,
246 "(&(sAMAccountName=%s)(objectClass=computer))", myname
);
247 if (rc
!= TLDAP_SUCCESS
) {
248 DEBUG(10, ("Could not retrieve our account: %s\n",
249 tldap_errstr(talloc_tos(), ld
, rc
)));
250 status
= NT_STATUS_LDAP(rc
);
253 num_msg
= talloc_array_length(msg
);
255 DEBUG(10, ("Got %d accounts, expected one\n", num_msg
));
256 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
259 if (!tldap_get_single_valueblob(msg
[0], "unicodePwd", &pwdblob
)) {
261 tldap_entry_dn(msg
[0], &dn
);
262 DEBUG(10, ("No unicodePwd attribute in %s\n",
263 dn
? dn
: "<unknown DN>"));
264 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
267 if (pwdblob
.length
!= 16) {
268 DEBUG(10, ("Password hash hash has length %d, expected 16\n",
269 (int)pwdblob
.length
));
270 status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
273 memcpy(pwd
, pwdblob
.data
, 16);
280 static NTSTATUS
check_netlogond_security(const struct auth_context
*auth_context
,
281 void *my_private_data
,
283 const struct auth_usersupplied_info
*user_info
,
284 struct auth_serversupplied_info
**server_info
)
286 TALLOC_CTX
*frame
= talloc_stackframe();
287 struct netr_SamInfo3
*info3
= NULL
;
288 struct rpc_pipe_client
*p
= NULL
;
289 struct pipe_auth_data
*auth
= NULL
;
290 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
291 uint8_t machine_password
[16];
292 struct netlogon_creds_CredentialState
*creds
;
293 NTSTATUS schannel_bind_result
, status
;
294 struct named_mutex
*mutex
= NULL
;
295 const char *ncalrpcsock
;
297 DEBUG(10, ("Check auth for: [%s]\n", user_info
->mapped
.account_name
));
299 ncalrpcsock
= lp_parm_const_string(
300 GLOBAL_SECTION_SNUM
, "auth_netlogond", "socket", NULL
);
302 if (ncalrpcsock
== NULL
) {
303 ncalrpcsock
= talloc_asprintf(talloc_tos(), "%s/%s",
304 get_dyn_NCALRPCDIR(), "DEFAULT");
307 if (ncalrpcsock
== NULL
) {
308 status
= NT_STATUS_NO_MEMORY
;
312 creds
= secrets_fetch_local_schannel_creds(talloc_tos());
317 status
= netlogond_validate(talloc_tos(), auth_context
, ncalrpcsock
,
318 creds
, user_info
, &info3
,
319 &schannel_bind_result
);
321 DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status
)));
323 if (NT_STATUS_IS_OK(status
)) {
327 if (NT_STATUS_IS_OK(schannel_bind_result
)) {
329 * This is a real failure from the DC
336 mutex
= grab_named_mutex(talloc_tos(), "LOCAL_SCHANNEL_KEY", 60);
338 DEBUG(10, ("Could not get mutex LOCAL_SCHANNEL_KEY\n"));
339 status
= NT_STATUS_ACCESS_DENIED
;
343 DEBUG(10, ("schannel bind failed, setting up new key\n"));
345 status
= rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpcsock
,
346 &ndr_table_netlogon
.syntax_id
, &p
);
348 if (!NT_STATUS_IS_OK(status
)) {
349 DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
354 status
= rpccli_anon_bind_data(p
, &auth
);
355 if (!NT_STATUS_IS_OK(status
)) {
356 DEBUG(10, ("rpccli_anon_bind_data failed: %s\n",
361 status
= rpc_pipe_bind(p
, auth
);
362 if (!NT_STATUS_IS_OK(status
)) {
363 DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status
)));
367 status
= mymachinepw(machine_password
);
368 if (!NT_STATUS_IS_OK(status
)) {
369 DEBUG(10, ("mymachinepw failed: %s\n", nt_errstr(status
)));
373 DEBUG(10, ("machinepw "));
374 dump_data(10, machine_password
, 16);
376 status
= rpccli_netlogon_setup_creds(
377 p
, global_myname(), lp_workgroup(), global_myname(),
378 global_myname(), machine_password
, SEC_CHAN_BDC
, &neg_flags
);
380 if (!NT_STATUS_IS_OK(status
)) {
381 DEBUG(10, ("rpccli_netlogon_setup_creds failed: %s\n",
386 secrets_store_local_schannel_creds(p
->dc
);
389 * Retry the authentication with the mutex held. This way nobody else
390 * can step on our toes.
393 status
= netlogond_validate(talloc_tos(), auth_context
, ncalrpcsock
,
394 p
->dc
, user_info
, &info3
,
395 &schannel_bind_result
);
399 DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status
)));
401 if (!NT_STATUS_IS_OK(status
)) {
407 status
= make_server_info_info3(mem_ctx
, user_info
->client
.account_name
,
408 user_info
->mapped
.domain_name
, server_info
,
410 if (!NT_STATUS_IS_OK(status
)) {
411 DEBUG(10, ("make_server_info_info3 failed: %s\n",
417 status
= NT_STATUS_OK
;
424 /* module initialisation */
425 static NTSTATUS
auth_init_netlogond(struct auth_context
*auth_context
,
427 auth_methods
**auth_method
)
429 struct auth_methods
*result
;
431 result
= TALLOC_ZERO_P(auth_context
, struct auth_methods
);
432 if (result
== NULL
) {
433 return NT_STATUS_NO_MEMORY
;
435 result
->name
= "netlogond";
436 result
->auth
= check_netlogond_security
;
438 *auth_method
= result
;
442 NTSTATUS
auth_netlogond_init(void)
444 smb_register_auth(AUTH_INTERFACE_VERSION
, "netlogond",
445 auth_init_netlogond
);