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 int DEBUGLEVEL;
27 extern pstring global_myname;
29 /****************************************************************************
30 Return the client state structure.
31 ****************************************************************************/
33 struct cli_state *server_client(void)
35 static struct cli_state pw_cli;
39 /****************************************************************************
40 Support for server level security.
41 ****************************************************************************/
43 struct cli_state *server_cryptkey(void)
45 struct cli_state *cli;
47 struct in_addr dest_ip;
49 BOOL connected_ok = False;
51 cli = server_client();
53 if (!cli_initialise(cli))
56 pserver = strdup(lp_passwordserver());
59 while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
60 standard_sub_basic(desthost);
63 if(!resolve_name( desthost, &dest_ip, 0x20)) {
64 DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost));
68 if (ismyip(dest_ip)) {
69 DEBUG(1,("Password server loop - disabling password server %s\n",desthost));
73 if (cli_connect(cli, desthost, &dest_ip)) {
74 DEBUG(3,("connected to password server %s\n",desthost));
83 DEBUG(0,("password server not available\n"));
88 if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip))
91 DEBUG(3,("got session\n"));
93 if (!cli_negprot(cli)) {
94 DEBUG(1,("%s rejected the negprot\n",desthost));
99 if (cli->protocol < PROTOCOL_LANMAN2 ||
100 !(cli->sec_mode & 1)) {
101 DEBUG(1,("%s isn't in user level security mode\n",desthost));
106 DEBUG(3,("password server OK\n"));
112 /****************************************************************************
113 Check for a valid username and password in security=server mode.
114 - Validate a password with the password server.
115 ****************************************************************************/
117 NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
119 struct cli_state *cli;
120 static unsigned char badpass[24];
121 static fstring baduser;
122 static BOOL tested_password_server = False;
123 static BOOL bad_password_server = False;
124 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
126 cli = server_client();
128 if (!cli->initialised) {
129 DEBUG(1,("password server %s is not connected\n", cli->desthost));
130 return(NT_STATUS_LOGON_FAILURE);
134 memset(badpass, 0x1f, sizeof(badpass));
136 if((user_info->nt_resp.len == sizeof(badpass)) &&
137 !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) {
139 * Very unlikely, our random bad password is the same as the users
142 memset(badpass, badpass[0]+1, sizeof(badpass));
145 if(baduser[0] == 0) {
146 fstrcpy(baduser, INVALID_USER_PREFIX);
147 fstrcat(baduser, global_myname);
151 * Attempt a session setup with a totally incorrect password.
152 * If this succeeds with the guest bit *NOT* set then the password
153 * server is broken and is not correctly setting the guest bit. We
154 * need to detect this as some versions of NT4.x are broken. JRA.
157 /* I sure as hell hope that there arn't servers out there that take
158 * NTLMv2 and have this bug, as we don't test for that...
159 * - abartlet@samba.org
162 if ((!tested_password_server) && (lp_paranoid_server_security())) {
163 if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass),
164 (char *)badpass, sizeof(badpass), user_info->domain.str)) {
167 * We connected to the password server so we
168 * can say we've tested it.
170 tested_password_server = True;
172 if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) {
173 DEBUG(0,("server_validate: password server %s allows users as non-guest \
174 with a bad password.\n", cli->desthost));
175 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
176 use this machine as the password server.\n"));
180 * Password server has the bug.
182 bad_password_server = True;
183 return NT_STATUS_LOGON_FAILURE;
190 * We have already tested the password server.
191 * Fail immediately if it has the bug.
194 if(bad_password_server) {
195 DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \
196 with a bad password.\n", cli->desthost));
197 DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \
198 use this machine as the password server.\n"));
199 return NT_STATUS_LOGON_FAILURE;
204 * Now we know the password server will correctly set the guest bit, or is
205 * not guest enabled, we can try with the real password.
208 if (!cli_session_setup(cli, user_info->smb_username.str,
209 (char *)user_info->lm_resp.buffer,
210 user_info->lm_resp.len,
211 (char *)user_info->nt_resp.buffer,
212 user_info->nt_resp.len,
213 user_info->domain.str)) {
214 DEBUG(1,("password server %s rejected the password\n", cli->desthost));
215 /* Make this cli_nt_error() when the conversion is in */
216 nt_status = cli_nt_error(cli);
218 nt_status = NT_STATUS_OK;
221 /* if logged in as guest then reject */
222 if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) {
223 DEBUG(1,("password server %s gave us guest only\n", cli->desthost));
224 nt_status = NT_STATUS_LOGON_FAILURE;