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 /* security = server just can't function with spnego */
55 cli->use_spnego = False;
57 pserver = strdup(lp_passwordserver());
60 while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
61 standard_sub_basic(desthost);
64 if(!resolve_name( desthost, &dest_ip, 0x20)) {
65 DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost));
69 if (ismyip(dest_ip)) {
70 DEBUG(1,("Password server loop - disabling password server %s\n",desthost));
74 if (cli_connect(cli, desthost, &dest_ip)) {
75 DEBUG(3,("connected to password server %s\n",desthost));
84 DEBUG(0,("password server not available\n"));
89 if (!attempt_netbios_session_request(cli, global_myname, desthost, &dest_ip))
92 DEBUG(3,("got session\n"));
94 if (!cli_negprot(cli)) {
95 DEBUG(1,("%s rejected the negprot\n",desthost));
100 if (cli->protocol < PROTOCOL_LANMAN2 ||
101 !(cli->sec_mode & 1)) {
102 DEBUG(1,("%s isn't in user level security mode\n",desthost));
107 DEBUG(3,("password server OK\n"));
113 /****************************************************************************
114 Check for a valid username and password in security=server mode.
115 - Validate a password with the password server.
116 ****************************************************************************/
118 NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
120 struct cli_state *cli;
121 static unsigned char badpass[24];
122 static fstring baduser;
123 static BOOL tested_password_server = False;
124 static BOOL bad_password_server = False;
125 NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
127 cli = server_client();
129 if (!cli->initialised) {
130 DEBUG(1,("password server %s is not connected\n", cli->desthost));
131 return(NT_STATUS_LOGON_FAILURE);
135 memset(badpass, 0x1f, sizeof(badpass));
137 if((user_info->nt_resp.len == sizeof(badpass)) &&
138 !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) {
140 * Very unlikely, our random bad password is the same as the users
143 memset(badpass, badpass[0]+1, sizeof(badpass));
146 if(baduser[0] == 0) {
147 fstrcpy(baduser, INVALID_USER_PREFIX);
148 fstrcat(baduser, global_myname);
152 * Attempt a session setup with a totally incorrect password.
153 * If this succeeds with the guest bit *NOT* set then the password
154 * server is broken and is not correctly setting the guest bit. We
155 * need to detect this as some versions of NT4.x are broken. JRA.
158 /* I sure as hell hope that there arn't servers out there that take
159 * NTLMv2 and have this bug, as we don't test for that...
160 * - abartlet@samba.org
163 if ((!tested_password_server) && (lp_paranoid_server_security())) {
164 if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass),
165 (char *)badpass, sizeof(badpass), user_info->domain.str)) {
168 * We connected to the password server so we
169 * can say we've tested it.
171 tested_password_server = True;
173 if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) {
174 DEBUG(0,("server_validate: password server %s allows users as non-guest \
175 with a bad password.\n", cli->desthost));
176 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
177 use this machine as the password server.\n"));
181 * Password server has the bug.
183 bad_password_server = True;
184 return NT_STATUS_LOGON_FAILURE;
191 * We have already tested the password server.
192 * Fail immediately if it has the bug.
195 if(bad_password_server) {
196 DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \
197 with a bad password.\n", cli->desthost));
198 DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \
199 use this machine as the password server.\n"));
200 return NT_STATUS_LOGON_FAILURE;
205 * Now we know the password server will correctly set the guest bit, or is
206 * not guest enabled, we can try with the real password.
209 if (!cli_session_setup(cli, user_info->smb_username.str,
210 (char *)user_info->lm_resp.buffer,
211 user_info->lm_resp.len,
212 (char *)user_info->nt_resp.buffer,
213 user_info->nt_resp.len,
214 user_info->domain.str)) {
215 DEBUG(1,("password server %s rejected the password\n", cli->desthost));
216 /* Make this cli_nt_error() when the conversion is in */
217 nt_status = cli_nt_error(cli);
219 nt_status = NT_STATUS_OK;
222 /* if logged in as guest then reject */
223 if ((SVAL(cli->inbuf,smb_vwv2) & 1) != 0) {
224 DEBUG(1,("password server %s gave us guest only\n", cli->desthost));
225 nt_status = NT_STATUS_LOGON_FAILURE;