2 Unix SMB/Netbios implementation.
4 Authenticate to a remote server
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern pstring global_myname;
27 /****************************************************************************
28 Return the client state structure.
29 ****************************************************************************/
31 struct cli_state *server_client(void)
33 static struct cli_state pw_cli;
37 /****************************************************************************
38 Support for server level security.
39 ****************************************************************************/
41 struct cli_state *server_cryptkey(void)
43 struct cli_state *cli;
45 struct in_addr dest_ip;
47 BOOL connected_ok = False;
49 cli = server_client();
51 if (!cli_initialise(cli))
54 pserver = strdup(lp_passwordserver());
57 while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
58 standard_sub_basic(desthost);
61 if(!resolve_name( desthost, &dest_ip, 0x20)) {
62 DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost));
66 if (ismyip(dest_ip)) {
67 DEBUG(1,("Password server loop - disabling password server %s\n",desthost));
71 if (cli_connect(cli, desthost, &dest_ip)) {
72 DEBUG(3,("connected to password server %s\n",desthost));
81 DEBUG(0,("password server not available\n"));
86 if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip))
89 DEBUG(3,("got session\n"));
91 if (!cli_negprot(cli)) {
92 DEBUG(1,("%s rejected the negprot\n",desthost));
97 if (cli->protocol < PROTOCOL_LANMAN2 ||
98 !(cli->sec_mode & 1)) {
99 DEBUG(1,("%s isn't in user level security mode\n",desthost));
104 DEBUG(3,("password server OK\n"));
110 /****************************************************************************
111 Check for a valid username and password in security=server mode.
112 - Validate a password with the password server.
113 ****************************************************************************/
115 NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
117 struct cli_state *cli;
118 static unsigned char badpass[24];
119 static fstring baduser;
120 static BOOL tested_password_server = False;
121 static BOOL bad_password_server = False;
122 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
124 cli = server_client();
126 if (!cli->initialised) {
127 DEBUG(1,("password server %s is not connected\n", cli->desthost));
128 return(NT_STATUS_LOGON_FAILURE);
132 memset(badpass, 0x1f, sizeof(badpass));
134 if((user_info->nt_resp.len == sizeof(badpass)) &&
135 !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) {
137 * Very unlikely, our random bad password is the same as the users
140 memset(badpass, badpass[0]+1, sizeof(badpass));
143 if(baduser[0] == 0) {
144 fstrcpy(baduser, INVALID_USER_PREFIX);
145 fstrcat(baduser, global_myname);
149 * Attempt a session setup with a totally incorrect password.
150 * If this succeeds with the guest bit *NOT* set then the password
151 * server is broken and is not correctly setting the guest bit. We
152 * need to detect this as some versions of NT4.x are broken. JRA.
155 /* I sure as hell hope that there arn't servers out there that take
156 * NTLMv2 and have this bug, as we don't test for that...
157 * - abartlet@samba.org
160 if ((!tested_password_server) && (lp_paranoid_server_security())) {
161 if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass),
162 (char *)badpass, sizeof(badpass), user_info->domain.str)) {
165 * We connected to the password server so we
166 * can say we've tested it.
168 tested_password_server = True;
170 if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) {
171 DEBUG(0,("server_validate: password server %s allows users as non-guest \
172 with a bad password.\n", cli->desthost));
173 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
174 use this machine as the password server.\n"));
178 * Password server has the bug.
180 bad_password_server = True;
181 return NT_STATUS_LOGON_FAILURE;
188 * We have already tested the password server.
189 * Fail immediately if it has the bug.
192 if(bad_password_server) {
193 DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \
194 with a bad password.\n", cli->desthost));
195 DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \
196 use this machine as the password server.\n"));
197 return NT_STATUS_LOGON_FAILURE;
202 * Now we know the password server will correctly set the guest bit, or is
203 * not guest enabled, we can try with the real password.
206 if (!cli_session_setup(cli, user_info->smb_username.str,
207 (char *)user_info->lm_resp.buffer,
208 user_info->lm_resp.len,
209 (char *)user_info->nt_resp.buffer,
210 user_info->nt_resp.len,
211 user_info->domain.str)) {
212 DEBUG(1,("password server %s rejected the password\n", cli->desthost));
213 /* Make this cli_nt_error() when the conversion is in */
214 nt_status = cli_nt_error(cli);
216 nt_status = NT_STATUS_OK;
219 /* if logged in as guest then reject */
220 if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) {
221 DEBUG(1,("password server %s gave us guest only\n", cli->desthost));
222 nt_status = NT_STATUS_LOGON_FAILURE;