source: branches/samba-3.2.x/source/auth/auth_domain.c@ 201

Last change on this file since 201 was 133, checked in by Paul Smedley, 18 years ago

Update trunk to 3.2.0pre3

File size: 14.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Authenticate against a remote domain
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23#undef DBGC_CLASS
24#define DBGC_CLASS DBGC_AUTH
25
26extern bool global_machine_password_needs_changing;
27static struct named_mutex *mutex;
28
29/**
30 * Connect to a remote server for (inter)domain security authenticaion.
31 *
32 * @param cli the cli to return containing the active connection
33 * @param server either a machine name or text IP address to
34 * connect to.
35 * @param setup_creds_as domain account to setup credentials as
36 * @param sec_chan a switch value to distinguish between domain
37 * member and interdomain authentication
38 * @param trust_passwd the trust password to establish the
39 * credentials with.
40 *
41 **/
42
43static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
44 const char *domain,
45 const char *dc_name,
46 struct sockaddr_storage *dc_ss,
47 struct rpc_pipe_client **pipe_ret,
48 bool *retry)
49{
50 NTSTATUS result;
51 struct rpc_pipe_client *netlogon_pipe = NULL;
52
53 *cli = NULL;
54
55 *pipe_ret = NULL;
56
57 /* TODO: Send a SAMLOGON request to determine whether this is a valid
58 logonserver. We can avoid a 30-second timeout if the DC is down
59 if the SAMLOGON request fails as it is only over UDP. */
60
61 /* we use a mutex to prevent two connections at once - when a
62 Win2k PDC get two connections where one hasn't completed a
63 session setup yet it will send a TCP reset to the first
64 connection (tridge) */
65
66 /*
67 * With NT4.x DC's *all* authentication must be serialized to avoid
68 * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA.
69 */
70
71 mutex = grab_named_mutex(NULL, dc_name, 10);
72 if (mutex == NULL) {
73 return NT_STATUS_NO_LOGON_SERVERS;
74 }
75
76 /* Attempt connection */
77 *retry = True;
78 result = cli_full_connection(cli, global_myname(), dc_name, dc_ss, 0,
79 "IPC$", "IPC", "", "", "", 0, Undefined, retry);
80
81 if (!NT_STATUS_IS_OK(result)) {
82 /* map to something more useful */
83 if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
84 result = NT_STATUS_NO_LOGON_SERVERS;
85 }
86
87 if (*cli) {
88 cli_shutdown(*cli);
89 *cli = NULL;
90 }
91
92 TALLOC_FREE(mutex);
93 return result;
94 }
95
96 /*
97 * We now have an anonymous connection to IPC$ on the domain password server.
98 */
99
100 /*
101 * Even if the connect succeeds we need to setup the netlogon
102 * pipe here. We do this as we may just have changed the domain
103 * account password on the PDC and yet we may be talking to
104 * a BDC that doesn't have this replicated yet. In this case
105 * a successful connect to a DC needs to take the netlogon connect
106 * into account also. This patch from "Bjart Kvarme" <[email protected]>.
107 */
108
109 /* open the netlogon pipe. */
110 if (lp_client_schannel()) {
111 /* We also setup the creds chain in the open_schannel call. */
112 netlogon_pipe = cli_rpc_pipe_open_schannel(*cli, PI_NETLOGON,
113 PIPE_AUTH_LEVEL_PRIVACY, domain, &result);
114 } else {
115 netlogon_pipe = cli_rpc_pipe_open_noauth(*cli, PI_NETLOGON, &result);
116 }
117
118 if(!netlogon_pipe) {
119 DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
120machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
121 cli_shutdown(*cli);
122 *cli = NULL;
123 TALLOC_FREE(mutex);
124 return result;
125 }
126
127 if (!lp_client_schannel()) {
128 /* We need to set up a creds chain on an unauthenticated netlogon pipe. */
129 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
130 uint32 sec_chan_type = 0;
131 unsigned char machine_pwd[16];
132 const char *account_name;
133
134 if (!get_trust_pw_hash(domain, machine_pwd, &account_name,
135 &sec_chan_type))
136 {
137 DEBUG(0, ("connect_to_domain_password_server: could not fetch "
138 "trust account password for domain '%s'\n",
139 domain));
140 cli_shutdown(*cli);
141 *cli = NULL;
142 TALLOC_FREE(mutex);
143 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
144 }
145
146 result = rpccli_netlogon_setup_creds(netlogon_pipe,
147 dc_name, /* server name */
148 domain, /* domain */
149 global_myname(), /* client name */
150 account_name, /* machine account name */
151 machine_pwd,
152 sec_chan_type,
153 &neg_flags);
154
155 if (!NT_STATUS_IS_OK(result)) {
156 cli_shutdown(*cli);
157 *cli = NULL;
158 TALLOC_FREE(mutex);
159 return result;
160 }
161 }
162
163 if(!netlogon_pipe) {
164 DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
165machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
166 cli_shutdown(*cli);
167 *cli = NULL;
168 TALLOC_FREE(mutex);
169 return NT_STATUS_NO_LOGON_SERVERS;
170 }
171
172 /* We exit here with the mutex *locked*. JRA */
173
174 *pipe_ret = netlogon_pipe;
175
176 return NT_STATUS_OK;
177}
178
179/***********************************************************************
180 Do the same as security=server, but using NT Domain calls and a session
181 key from the machine password. If the server parameter is specified
182 use it, otherwise figure out a server from the 'password server' param.
183************************************************************************/
184
185static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
186 const auth_usersupplied_info *user_info,
187 const char *domain,
188 uchar chal[8],
189 auth_serversupplied_info **server_info,
190 const char *dc_name,
191 struct sockaddr_storage *dc_ss)
192
193{
194 struct netr_SamInfo3 *info3 = NULL;
195 struct cli_state *cli = NULL;
196 struct rpc_pipe_client *netlogon_pipe = NULL;
197 NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS;
198 int i;
199 bool retry = True;
200
201 /*
202 * At this point, smb_apasswd points to the lanman response to
203 * the challenge in local_challenge, and smb_ntpasswd points to
204 * the NT response to the challenge in local_challenge. Ship
205 * these over the secure channel to a domain controller and
206 * see if they were valid.
207 */
208
209 /* rety loop for robustness */
210
211 for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) {
212 nt_status = connect_to_domain_password_server(&cli,