Feature #2068 ยป 0037-Server-Add-logging-about-auth-progress.patch
| server/auth.c | ||
|---|---|---|
|
#define GUEST_NAME "guest"
|
||
|
#define MIN_PASSWORD_LEN 6 /* minimum length of password */
|
||
|
#define MIN_PASSWORD_CAPS 0 /* minimum number of capital letters required */
|
||
|
#define MIN_PASSWORD_NUMS 0 /* minimum number of numbers required */
|
||
|
#define MIN_PASSWORD_LEN 6 /* Minimum length of password */
|
||
|
#define MIN_PASSWORD_CAPS 0 /* Minimum number of capital letters required */
|
||
|
#define MIN_PASSWORD_NUMS 0 /* Minimum number of numbers required */
|
||
|
#define MAX_AUTH_TRIES 3
|
||
|
#define MAX_WAIT_TIME 300 /* max time we'll wait on a password */
|
||
|
/* after each wrong guess for a password, the server waits this
|
||
|
/* After each wrong guess for a password, the server waits this
|
||
|
* many seconds to reply to the client */
|
||
|
static const int auth_fail_wait[] = { 1, 1, 2, 3 };
|
||
| ... | ... | |
|
if (!script_fcdb_call("user_exists", pconn, &exists)) {
|
||
|
if (srvarg.auth_allow_guests) {
|
||
|
sz_strlcpy(tmpname, pconn->username);
|
||
|
get_unique_guest_name(tmpname); /* don't pass pconn->username here */
|
||
|
get_unique_guest_name(tmpname); /* Don't pass pconn->username here */
|
||
|
sz_strlcpy(pconn->username, tmpname);
|
||
|
log_error("Error reading database; connection -> guest");
|
||
| ... | ... | |
|
return FALSE;
|
||
|
}
|
||
|
} else if (exists) {
|
||
|
/* we found a user */
|
||
|
/* We found a user */
|
||
|
fc_snprintf(buffer, sizeof(buffer), _("Enter password for %s:"),
|
||
|
pconn->username);
|
||
|
dsend_packet_authentication_req(pconn, AUTH_LOGIN_FIRST, buffer);
|
||
|
pconn->server.auth_settime = time(NULL);
|
||
|
pconn->server.status = AS_REQUESTING_OLD_PASS;
|
||
|
log_debug("Password for %s requested.", pconn->username);
|
||
|
} else {
|
||
|
/* we couldn't find the user, they are new */
|
||
|
/* We couldn't find the user, they are new */
|
||
|
if (srvarg.auth_allow_newusers) {
|
||
|
/* TRANS: Try not to make the translation much longer than the original. */
|
||
|
sz_strlcpy(buffer, _("First time login. Set a new password and confirm it."));
|
||
|
dsend_packet_authentication_req(pconn, AUTH_NEWUSER_FIRST, buffer);
|
||
|
pconn->server.auth_settime = time(NULL);
|
||
|
pconn->server.status = AS_REQUESTING_NEW_PASS;
|
||
|
log_verbose(_("Registration for %s requested."), pconn->username);
|
||
|
} else {
|
||
|
reject_new_connection(_("This server allows only preregistered "
|
||
|
"users. Sorry."), pconn);
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
| ... | ... | |
|
if (pconn->server.status == AS_REQUESTING_NEW_PASS) {
|
||
|
/* check if the new password is acceptable */
|
||
|
/* Check if the new password is acceptable */
|
||
|
if (!is_good_password(password, msg)) {
|
||
|
if (pconn->server.auth_tries++ >= MAX_AUTH_TRIES) {
|
||
|
reject_new_connection(_("Sorry, too many wrong tries..."), pconn);
|
||
| ... | ... | |
|
notify_conn(pconn->self, NULL, E_CONNECTION, ftc_warning,
|
||
|
_("Warning: There was an error in saving to the database. "
|
||
|
"Continuing, but your stats will not be saved."));
|
||
|
log_error("Error writing to database for: %s", pconn->username);
|
||
|
log_error(_("Error writing to database for: %s"), pconn->username);
|
||
|
} else {
|
||
|
log_normal(_("%s registered."), pconn->username);
|
||
|
}
|
||
|
establish_new_connection(pconn);
|
||
| ... | ... | |
|
{
|
||
|
switch (pconn->server.status) {
|
||
|
case AS_NOT_ESTABLISHED:
|
||
|
/* nothing, we're not ready to do anything here yet. */
|
||
|
/* Nothing, we're not ready to do anything here yet. */
|
||
|
break;
|
||
|
case AS_FAILED:
|
||
|
/* the connection gave the wrong password, we kick 'em off or
|
||
|
/* The connection gave the wrong password, we kick 'em off or
|
||
|
* we're throttling the connection to avoid password guessing */
|
||
|
if (pconn->server.auth_settime > 0
|
||
|
&& time(NULL) >= pconn->server.auth_settime) {
|
||
| ... | ... | |
|
break;
|
||
|
case AS_REQUESTING_OLD_PASS:
|
||
|
case AS_REQUESTING_NEW_PASS:
|
||
|
/* waiting on the client to send us a password... don't wait too long */
|
||
|
/* Waiting on the client to send us a password... don't wait too long */
|
||
|
if (time(NULL) >= pconn->server.auth_settime + MAX_WAIT_TIME) {
|
||
|
pconn->server.status = AS_NOT_ESTABLISHED;
|
||
|
reject_new_connection(_("Sorry, your connection timed out..."), pconn);
|
||
| ... | ... | |
|
}
|
||
|
break;
|
||
|
case AS_ESTABLISHED:
|
||
|
/* this better fail bigtime */
|
||
|
/* This better fail bigtime */
|
||
|
fc_assert(pconn->server.status != AS_ESTABLISHED);
|
||
|
break;
|
||
|
}
|
||
| ... | ... | |
|
/************************************************************************//**
|
||
|
Return a unique guest name
|
||
|
WARNING: do not pass pconn->username to this function: it won't return!
|
||
|
WARNING: Do not pass pconn->username to this function: it won't return!
|
||
|
****************************************************************************/
|
||
|
static void get_unique_guest_name(char *name)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
/* first see if the given name is suitable */
|
||
|
/* First see if the given name is suitable */
|
||
|
if (is_guest_name(name) && !conn_by_user(name)) {
|
||
|
return;
|
||
|
}
|
||
|
/* next try bare guest name */
|
||
|
/* Next try bare guest name */
|
||
|
fc_strlcpy(name, GUEST_NAME, MAX_LEN_NAME);
|
||
|
if (!conn_by_user(name)) {
|
||
|
return;
|
||
|
}
|
||
|
/* bare name is taken, append numbers */
|
||
|
/* Bare name is taken, append numbers */
|
||
|
for (i = 1; ; i++) {
|
||
|
fc_snprintf(name, MAX_LEN_NAME, "%s%u", GUEST_NAME, i);
|
||
|
/* attempt to find this name; if we can't we're good to go */
|
||
|
/* Attempt to find this name; if we can't we're good to go */
|
||
|
if (!conn_by_user(name)) {
|
||
|
break;
|
||
|
}
|
||
| ... | ... | |
|
/************************************************************************//**
|
||
|
Verifies that a password is valid. Does some [very] rudimentary safety
|
||
|
checks. TODO: do we want to frown on non-printing characters?
|
||
|
checks. TODO: Do we want to frown on non-printing characters?
|
||
|
Fill the msg (length MAX_LEN_MSG) with any worthwhile information that
|
||
|
the client ought to know.
|
||
|
****************************************************************************/
|
||
| ... | ... | |
|
{
|
||
|
int i, num_caps = 0, num_nums = 0;
|
||
|
/* check password length */
|
||
|
/* Check password length */
|
||
|
if (strlen(password) < MIN_PASSWORD_LEN) {
|
||
|
fc_snprintf(msg, MAX_LEN_MSG,
|
||
|
_("Your password is too short, the minimum length is %d. "
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
/* check number of capital letters */
|
||
|
/* Check number of capital letters */
|
||
|
if (num_caps < MIN_PASSWORD_CAPS) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
/* check number of numbers */
|
||
|
/* Check number of numbers */
|
||
|
if (num_nums < MIN_PASSWORD_NUMS) {
|
||
|
return FALSE;
|
||
|
}
|
||
| server/fcdb.c | ||
|---|---|---|
|
}
|
||
|
} entry_list_iterate_end;
|
||
|
/* FIXME: we could arrange to call secfile_check_unused() and have it
|
||
|
/* FIXME: We could arrange to call secfile_check_unused() and have it
|
||
|
* complain about unused entries (e.g. those not in [fcdb]). */
|
||
|
secfile_destroy(secfile);
|
||
| ... | ... | |
|
bool fcdb_init(const char *conf_file)
|
||
|
{
|
||
|
fc_assert(fcdb_config == NULL);
|
||
|
fcdb_config = fcdb_option_hash_new();
|
||
|
if (conf_file && strcmp(conf_file, "-")) {
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void fcdb_free(void)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
#endif /* HAVE_FCDB */
|
||