/**************************************************************************** validate a password with the password server ****************************************************************************/ BOOL server_validate(char *user, char *domain, char *pass, int passlen, char *ntpass, int ntpasslen) { extern fstring local_machine; static unsigned char badpass[24]; if (!cli.initialised) { DEBUG(1,("password server %s is not connected\n", cli.desthost)); return(False); } if(badpass[0] == 0) { memset(badpass, 0x1f, sizeof(badpass)); } if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) { /* Very unlikely, our random bad password is the same as the users password. */ memset(badpass, badpass[0]+1, sizeof(badpass)); } /* * Attempt a session setup with a totally incorrect password. * If this succeeds with the guest bit *NOT* set then the password * server is broken and is not correctly setting the guest bit. We * need to detect this as some versions of NT4.x are broken. JRA. */ if (cli_session_setup(&cli, user, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), domain)) { if ((SVAL(cli.inbuf,smb_vwv2) & 1) == 0) { DEBUG(0,("server_validate: password server %s allows users as non-guest \ with a bad password.\n", cli.desthost)); DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); cli_ulogoff(&cli); return False; } cli_ulogoff(&cli); }
static void reconnect(struct cli_state *cli[NSERVERS][NCONNECTIONS], uint16_t fnum[NSERVERS][NCONNECTIONS][NFILES], char *share[NSERVERS]) { int server, conn, f; for (server=0;server<NSERVERS;server++) for (conn=0;conn<NCONNECTIONS;conn++) { if (cli[server][conn]) { for (f=0;f<NFILES;f++) { if (fnum[server][conn][f] != (uint16_t)-1) { cli_close(cli[server][conn], fnum[server][conn][f]); fnum[server][conn][f] = (uint16_t)-1; } } cli_ulogoff(cli[server][conn]); cli_shutdown(cli[server][conn]); } cli[server][conn] = connect_one(share[server], server); if (!cli[server][conn]) { DEBUG(0,("Failed to connect to %s\n", share[server])); exit(1); } } }
static NTSTATUS check_smbserver_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { struct cli_state *cli; static unsigned char badpass[24]; static fstring baduser; static BOOL tested_password_server = False; static BOOL bad_password_server = False; NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; BOOL locally_made_cli = False; cli = (struct cli_state *)my_private_data; if (cli) { } else { cli = server_cryptkey(mem_ctx); locally_made_cli = True; } if (!cli || !cli->initialised) { DEBUG(1,("password server is not connected (cli not initilised)\n")); return NT_STATUS_LOGON_FAILURE; } if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) { if (user_info->encrypted) { DEBUG(1,("password server %s is plaintext, but we are encrypted. This just can't work :-(\n", cli->desthost)); return NT_STATUS_LOGON_FAILURE; } } else { if (memcmp(cli->secblob.data, auth_context->challenge.data, 8) != 0) { DEBUG(1,("the challenge that the password server (%s) supplied us is not the one we gave our client. This just can't work :-(\n", cli->desthost)); return NT_STATUS_LOGON_FAILURE; } } if(badpass[0] == 0) memset(badpass, 0x1f, sizeof(badpass)); if((user_info->nt_resp.length == sizeof(badpass)) && !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) { /* * Very unlikely, our random bad password is the same as the users * password. */ memset(badpass, badpass[0]+1, sizeof(badpass)); } if(baduser[0] == 0) { fstrcpy(baduser, INVALID_USER_PREFIX); fstrcat(baduser, global_myname()); } /* * Attempt a session setup with a totally incorrect password. * If this succeeds with the guest bit *NOT* set then the password * server is broken and is not correctly setting the guest bit. We * need to detect this as some versions of NT4.x are broken. JRA. */ /* I sure as hell hope that there aren't servers out there that take * NTLMv2 and have this bug, as we don't test for that... * - [email protected] */ if ((!tested_password_server) && (lp_paranoid_server_security())) { if (NT_STATUS_IS_OK(cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), (char *)badpass, sizeof(badpass), user_info->domain))) { /* * We connected to the password server so we * can say we've tested it. */ tested_password_server = True; if ((SVAL(cli->inbuf,smb_vwv2) & 1) == 0) { DEBUG(0,("server_validate: password server %s allows users as non-guest \ with a bad password.\n", cli->desthost)); DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \ use this machine as the password server.\n")); cli_ulogoff(cli); /* * Password server has the bug. */ bad_password_server = True; return NT_STATUS_LOGON_FAILURE; } cli_ulogoff(cli); }
static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, const char *domain, const char *dc_name, struct in_addr dc_ip, const char *setup_creds_as, uint16 sec_chan, const unsigned char *trust_passwd, BOOL *retry) { NTSTATUS result; /* TODO: Send a SAMLOGON request to determine whether this is a valid logonserver. We can avoid a 30-second timeout if the DC is down if the SAMLOGON request fails as it is only over UDP. */ /* we use a mutex to prevent two connections at once - when a Win2k PDC get two connections where one hasn't completed a session setup yet it will send a TCP reset to the first connection (tridge) */ /* * With NT4.x DC's *all* authentication must be serialized to avoid * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA. */ if (!grab_server_mutex(dc_name)) return NT_STATUS_NO_LOGON_SERVERS; /* Attempt connection */ *retry = True; result = cli_full_connection(cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", "", "", "", 0, Undefined, retry); if (!NT_STATUS_IS_OK(result)) { /* map to something more useful */ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) { result = NT_STATUS_NO_LOGON_SERVERS; } release_server_mutex(); return result; } /* * We now have an anonymous connection to IPC$ on the domain password server. */ /* * Even if the connect succeeds we need to setup the netlogon * pipe here. We do this as we may just have changed the domain * account password on the PDC and yet we may be talking to * a BDC that doesn't have this replicated yet. In this case * a successful connect to a DC needs to take the netlogon connect * into account also. This patch from "Bjart Kvarme" <*****@*****.**>. */ if(cli_nt_session_open(*cli, PI_NETLOGON) == False) { DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); cli_nt_session_close(*cli); cli_ulogoff(*cli); cli_shutdown(*cli); release_server_mutex(); return NT_STATUS_NO_LOGON_SERVERS; }
NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct in_addr pdc_ip; fstring dc_name; struct cli_state *cli; DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", domain)); if (remote_machine == NULL || !strcmp(remote_machine, "*")) { /* Use the PDC *only* for this */ if ( !get_pdc_ip(domain, &pdc_ip) ) { DEBUG(0,("Can't get IP for PDC for domain %s\n", domain)); goto failed; } if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) goto failed; } else { /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ fstrcpy( dc_name, remote_machine ); } /* if this next call fails, then give up. We can't do password changes on BDC's --jerry */ if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), dc_name, NULL, 0, "IPC$", "IPC", "", "", "", 0, Undefined, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name)); nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } /* * Ok - we have an anonymous connection to the IPC$ share. * Now start the NT Domain stuff :-). */ if(cli_nt_session_open(cli, PI_NETLOGON) == False) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", dc_name, cli_errstr(cli))); cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain); cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); failed: if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", timestring(False), domain)); } else DEBUG(5,("change_trust_account_password: sucess!\n")); return nt_status; }