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 Validate a password with the password server.
114 ****************************************************************************/
116 static NTSTATUS server_validate(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
118 struct cli_state *cli;
119 static unsigned char badpass[24];
120 static fstring baduser;
121 static BOOL tested_password_server = False;
122 static BOOL bad_password_server = False;
123 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
125 cli = server_client();
127 if (!cli->initialised) {
128 DEBUG(1,("password server %s is not connected\n", cli->desthost));
129 return(NT_STATUS_LOGON_FAILURE);
133 memset(badpass, 0x1f, sizeof(badpass));
135 if((user_info->nt_resp.len == sizeof(badpass)) &&
136 !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) {
138 * Very unlikely, our random bad password is the same as the users
141 memset(badpass, badpass[0]+1, sizeof(badpass));
144 if(baduser[0] == 0) {
145 fstrcpy(baduser, INVALID_USER_PREFIX);
146 fstrcat(baduser, global_myname);
150 * Attempt a session setup with a totally incorrect password.
151 * If this succeeds with the guest bit *NOT* set then the password
152 * server is broken and is not correctly setting the guest bit. We
153 * need to detect this as some versions of NT4.x are broken. JRA.
156 /* I sure as hell hope that there arn't servers out there that take
157 * NTLMv2 and have this bug, as we don't test for that...
158 * - abartlet@samba.org
161 if ((!tested_password_server) && (lp_paranoid_server_security())) {
162 if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass),
163 (char *)badpass, sizeof(badpass), user_info->domain.str)) {
166 * We connected to the password server so we
167 * can say we've tested it.
169 tested_password_server = True;
171 if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) {
172 DEBUG(0,("server_validate: password server %s allows users as non-guest \
173 with a bad password.\n", cli->desthost));
174 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
175 use this machine as the password server.\n"));
179 * Password server has the bug.
181 bad_password_server = True;
182 return NT_STATUS_LOGON_FAILURE;
189 * We have already tested the password server.
190 * Fail immediately if it has the bug.
193 if(bad_password_server) {
194 DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \
195 with a bad password.\n", cli->desthost));
196 DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \
197 use this machine as the password server.\n"));
198 return NT_STATUS_LOGON_FAILURE;
203 * Now we know the password server will correctly set the guest bit, or is
204 * not guest enabled, we can try with the real password.
207 if (!cli_session_setup(cli, user_info->smb_username.str,
208 (char *)user_info->lm_resp.buffer,
209 user_info->lm_resp.len,
210 (char *)user_info->nt_resp.buffer,
211 user_info->nt_resp.len,
212 user_info->domain.str)) {
213 DEBUG(1,("password server %s rejected the password\n", cli->desthost));
214 /* Make this cli_nt_error() when the conversion is in */
215 nt_status = NT_STATUS_LOGON_FAILURE;
217 nt_status = NT_STATUS_OK;
220 /* if logged in as guest then reject */
221 if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) {
222 DEBUG(1,("password server %s gave us guest only\n", cli->desthost));
223 nt_status = NT_STATUS_LOGON_FAILURE;
231 /****************************************************************************
232 Check for a valid username and password in security=server mode.
233 ****************************************************************************/
235 NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
238 if(lp_security() != SEC_SERVER)
239 return NT_STATUS_LOGON_FAILURE;
241 return server_validate(user_info, server_info);