2 Unix SMB/CIFS implementation.
4 dcerpc schannel operations
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "librpc/gen_ndr/ndr_schannel.h"
26 #include "auth/auth.h"
29 get a schannel key using a netlogon challenge on a secondary pipe
31 static NTSTATUS
dcerpc_schannel_key(TALLOC_CTX
*tmp_ctx
,
32 struct dcerpc_pipe
*p
,
33 struct cli_credentials
*credentials
)
36 struct dcerpc_binding
*b
;
37 struct dcerpc_pipe
*p2
;
38 struct netr_ServerReqChallenge r
;
39 struct netr_ServerAuthenticate2 a
;
40 struct netr_Credential credentials1
, credentials2
, credentials3
;
41 const struct samr_Password
*mach_pwd
;
42 uint32_t negotiate_flags
;
43 struct creds_CredentialState
*creds
;
44 creds
= talloc(tmp_ctx
, struct creds_CredentialState
);
46 return NT_STATUS_NO_MEMORY
;
49 if (p
->conn
->flags
& DCERPC_SCHANNEL_128
) {
50 negotiate_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
52 negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
56 step 1 - establish a netlogon connection, with no authentication
59 /* Find the original binding string */
60 status
= dcerpc_parse_binding(tmp_ctx
, p
->conn
->binding_string
, &b
);
61 if (!NT_STATUS_IS_OK(status
)) {
62 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", p
->conn
->binding_string
));
66 /* Make binding string for netlogon, not the other pipe */
67 status
= dcerpc_epm_map_binding(tmp_ctx
, b
,
68 DCERPC_NETLOGON_UUID
, DCERPC_NETLOGON_VERSION
,
70 if (!NT_STATUS_IS_OK(status
)) {
71 DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
72 DCERPC_NETLOGON_UUID
, nt_errstr(status
)));
76 status
= dcerpc_secondary_connection(p
, &p2
, b
);
77 if (!NT_STATUS_IS_OK(status
)) {
81 status
= dcerpc_bind_auth_none(p2
, DCERPC_NETLOGON_UUID
,
82 DCERPC_NETLOGON_VERSION
);
83 if (!NT_STATUS_IS_OK(status
)) {
89 step 2 - request a netlogon challenge
91 r
.in
.server_name
= talloc_asprintf(tmp_ctx
, "\\\\%s", dcerpc_server_name(p
));
92 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
93 r
.in
.credentials
= &credentials1
;
94 r
.out
.credentials
= &credentials2
;
96 generate_random_buffer(credentials1
.data
, sizeof(credentials1
.data
));
98 status
= dcerpc_netr_ServerReqChallenge(p2
, tmp_ctx
, &r
);
99 if (!NT_STATUS_IS_OK(status
)) {
104 step 3 - authenticate on the netlogon pipe
106 mach_pwd
= cli_credentials_get_nt_hash(credentials
, tmp_ctx
);
108 creds_client_init(creds
, &credentials1
, &credentials2
,
109 mach_pwd
, &credentials3
,
112 a
.in
.server_name
= r
.in
.server_name
;
113 a
.in
.account_name
= cli_credentials_get_username(credentials
);
114 a
.in
.secure_channel_type
=
115 cli_credentials_get_secure_channel_type(credentials
);
116 a
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
117 a
.in
.negotiate_flags
= &negotiate_flags
;
118 a
.out
.negotiate_flags
= &negotiate_flags
;
119 a
.in
.credentials
= &credentials3
;
120 a
.out
.credentials
= &credentials3
;
122 status
= dcerpc_netr_ServerAuthenticate2(p2
, tmp_ctx
, &a
);
123 if (!NT_STATUS_IS_OK(status
)) {
127 if (!creds_client_check(creds
, a
.out
.credentials
)) {
128 return NT_STATUS_UNSUCCESSFUL
;
131 cli_credentials_set_netlogon_creds(credentials
, creds
);
134 the schannel session key is now in creds.session_key
136 we no longer need the netlogon pipe open
143 NTSTATUS
dcerpc_bind_auth_schannel(TALLOC_CTX
*tmp_ctx
,
144 struct dcerpc_pipe
*p
,
145 const char *uuid
, uint_t version
,
146 struct cli_credentials
*credentials
)
150 /* Fills in NETLOGON credentials */
151 status
= dcerpc_schannel_key(tmp_ctx
,
154 if (!NT_STATUS_IS_OK(status
)) {
155 DEBUG(1, ("Failed to setup credentials for account %s: %s\n",
156 cli_credentials_get_username(credentials
),
161 return dcerpc_bind_auth(p
, uuid
, version
,
162 credentials
, DCERPC_AUTH_TYPE_SCHANNEL
,