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
,
37 struct dcerpc_binding
*b
;
38 struct dcerpc_pipe
*p2
;
39 struct netr_ServerReqChallenge r
;
40 struct netr_ServerAuthenticate2 a
;
41 struct netr_Credential credentials1
, credentials2
, credentials3
;
42 struct samr_Password mach_pwd
;
43 uint32_t negotiate_flags
;
44 struct creds_CredentialState
*creds
;
45 creds
= talloc(tmp_ctx
, struct creds_CredentialState
);
47 return NT_STATUS_NO_MEMORY
;
50 if (p
->conn
->flags
& DCERPC_SCHANNEL_128
) {
51 negotiate_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
53 negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
57 step 1 - establish a netlogon connection, with no authentication
60 /* Find the original binding string */
61 status
= dcerpc_parse_binding(tmp_ctx
, p
->conn
->binding_string
, &b
);
62 if (!NT_STATUS_IS_OK(status
)) {
63 DEBUG(0,("Failed to parse dcerpc binding '%s'\n", p
->conn
->binding_string
));
67 /* Make binding string for netlogon, not the other pipe */
68 status
= dcerpc_epm_map_binding(tmp_ctx
, b
, DCERPC_NETLOGON_UUID
, DCERPC_NETLOGON_VERSION
);
69 if (!NT_STATUS_IS_OK(status
)) {
70 DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
71 DCERPC_NETLOGON_UUID
, nt_errstr(status
)));
75 status
= dcerpc_secondary_connection(p
, &p2
, b
);
76 if (!NT_STATUS_IS_OK(status
)) {
80 status
= dcerpc_bind_auth_none(p2
, DCERPC_NETLOGON_UUID
,
81 DCERPC_NETLOGON_VERSION
);
82 if (!NT_STATUS_IS_OK(status
)) {
88 step 2 - request a netlogon challenge
90 r
.in
.server_name
= talloc_asprintf(tmp_ctx
, "\\\\%s", dcerpc_server_name(p
));
91 r
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
92 r
.in
.credentials
= &credentials1
;
93 r
.out
.credentials
= &credentials2
;
95 generate_random_buffer(credentials1
.data
, sizeof(credentials1
.data
));
97 status
= dcerpc_netr_ServerReqChallenge(p2
, tmp_ctx
, &r
);
98 if (!NT_STATUS_IS_OK(status
)) {
103 step 3 - authenticate on the netlogon pipe
105 E_md4hash(cli_credentials_get_password(credentials
), mach_pwd
.hash
);
106 creds_client_init(creds
, &credentials1
, &credentials2
,
107 &mach_pwd
, &credentials3
,
110 a
.in
.server_name
= r
.in
.server_name
;
111 a
.in
.account_name
= cli_credentials_get_username(credentials
);
112 a
.in
.secure_channel_type
= chan_type
;
113 a
.in
.computer_name
= cli_credentials_get_workstation(credentials
);
114 a
.in
.negotiate_flags
= &negotiate_flags
;
115 a
.out
.negotiate_flags
= &negotiate_flags
;
116 a
.in
.credentials
= &credentials3
;
117 a
.out
.credentials
= &credentials3
;
119 status
= dcerpc_netr_ServerAuthenticate2(p2
, tmp_ctx
, &a
);
120 if (!NT_STATUS_IS_OK(status
)) {
124 if (!creds_client_check(creds
, a
.out
.credentials
)) {
125 return NT_STATUS_UNSUCCESSFUL
;
128 cli_credentials_set_netlogon_creds(credentials
, creds
);
131 the schannel session key is now in creds.session_key
133 we no longer need the netlogon pipe open
140 NTSTATUS
dcerpc_bind_auth_schannel(TALLOC_CTX
*tmp_ctx
,
141 struct dcerpc_pipe
*p
,
142 const char *uuid
, uint_t version
,
143 struct cli_credentials
*credentials
)
148 if (p
->conn
->flags
& DCERPC_SCHANNEL_BDC
) {
149 chan_type
= SEC_CHAN_BDC
;
150 } else if (p
->conn
->flags
& DCERPC_SCHANNEL_WORKSTATION
) {
151 chan_type
= SEC_CHAN_WKSTA
;
152 } else if (p
->conn
->flags
& DCERPC_SCHANNEL_DOMAIN
) {
153 chan_type
= SEC_CHAN_DOMAIN
;
156 /* Fills in NETLOGON credentials */
157 status
= dcerpc_schannel_key(tmp_ctx
,
161 if (!NT_STATUS_IS_OK(status
)) {
162 DEBUG(1, ("Failed to setup credentials for account %s: %s\n",
163 cli_credentials_get_username(credentials
),
168 return dcerpc_bind_auth_password(p
, uuid
, version
,
169 credentials
, DCERPC_AUTH_TYPE_SCHANNEL
,