AR_IAUTH_HURRY, /**< we told iauth to hurry up */
AR_IAUTH_USERNAME, /**< iauth sent a username (preferred or forced) */
AR_IAUTH_FUSERNAME, /**< iauth sent a forced username */
+ AR_PASSWORD_CHECKED, /**< client password already checked */
AR_NUM_FLAGS
};
MSG("NOTICE AUTH :*** Checking Ident\r\n"),
MSG("NOTICE AUTH :*** Got ident response\r\n"),
MSG("NOTICE AUTH :*** No ident response\r\n"),
+ MSG("NOTICE AUTH :*** \r\n"),
MSG("NOTICE AUTH :*** Your forward and reverse DNS do not match, "
"ignoring hostname.\r\n"),
MSG("NOTICE AUTH :*** Invalid hostname\r\n")
REPORT_DO_ID,
REPORT_FIN_ID,
REPORT_FAIL_ID,
+ REPORT_FAIL_IAUTH,
REPORT_IP_MISMATCH,
REPORT_INVAL_DNS
} ReportType;
* destroy \a auth, clear the password, set the username, and register
* the client.
* @param[in] auth Authorization request to check.
- * @param[in] send_reports Passed to destroy_auth_request() if \a auth
- * is complete.
* @return Zero if client is kept, CPTR_KILLED if client rejected.
*/
-static int check_auth_finished(struct AuthRequest *auth, int send_reports)
+static int check_auth_finished(struct AuthRequest *auth)
{
enum AuthRequestFlag flag;
int res;
&& preregister_user(auth->client))
return CPTR_KILLED;
+ /* If we have not done so, check client password. Do this as soon
+ * as possible so that iauth's challenge/response (which uses PASS
+ * for responses) is not confused with the client's password.
+ */
+ if (!FlagHas(&auth->flags, AR_PASSWORD_CHECKED))
+ {
+ struct ConfItem *aconf;
+
+ aconf = cli_confs(auth->client)->value.aconf;
+ if (!EmptyString(aconf->passwd)
+ && strcmp(cli_passwd(auth->client), aconf->passwd))
+ {
+ ServerStats->is_ref++;
+ send_reply(auth->client, ERR_PASSWDMISMATCH);
+ return exit_client(auth->client, auth->client, &me, "Bad Password");
+ }
+ FlagSet(&auth->flags, AR_PASSWORD_CHECKED);
+ }
+
/* Check if iauth is done. */
if (FlagHas(&auth->flags, AR_IAUTH_PENDING))
{
/* Switch auth request to hurry-up state. */
if (!FlagHas(&auth->flags, AR_IAUTH_HURRY))
{
- struct ConfItem* aconf;
-
/* Set "hurry" flag in auth request. */
FlagSet(&auth->flags, AR_IAUTH_HURRY);
- /* Check password now (to avoid challenge/response conflicts). */
- aconf = cli_confs(auth->client)->value.aconf;
- if (!EmptyString(aconf->passwd)
- && strcmp(cli_passwd(auth->client), aconf->passwd))
- {
- ServerStats->is_ref++;
- send_reply(auth->client, ERR_PASSWDMISMATCH);
- return exit_client(auth->client, auth->client, &me, "Bad Password");
- }
-
/* If iauth wants it, send notification. */
if (IAuthHas(iauth, IAUTH_UNDERNET))
- sendto_iauth(auth->client, "H %s", ConfClass(aconf));
+ sendto_iauth(auth->client, "H %s", get_client_class(auth->client));
/* If iauth wants it, give client more time. */
if (IAuthHas(iauth, IAUTH_EXTRAWAIT))
else
FlagSet(&auth->flags, AR_IAUTH_HURRY);
- destroy_auth_request(auth, send_reports);
+ destroy_auth_request(auth);
if (!IsUserPort(auth->client))
return 0;
memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
if (IsUserPort(auth->client))
sendheader(auth->client, REPORT_FAIL_ID);
FlagClr(&auth->flags, AR_AUTH_PENDING);
- check_auth_finished(auth, 0);
+ check_auth_finished(auth);
}
}
}
FlagClr(&auth->flags, AR_AUTH_PENDING);
- check_auth_finished(auth, 0);
+ check_auth_finished(auth);
}
/** Handle socket I/O activity.
/** Stop an auth request completely.
* @param[in] auth The struct AuthRequest to cancel.
- * @param[in] send_reports If non-zero, report the failure to the user.
*/
-void destroy_auth_request(struct AuthRequest* auth, int send_reports)
+void destroy_auth_request(struct AuthRequest* auth)
{
Debug((DEBUG_INFO, "Deleting auth request for %p", auth->client));
- if (FlagHas(&auth->flags, AR_AUTH_PENDING)) {
- if (send_reports && IsUserPort(auth->client))
- sendheader(auth->client, REPORT_FAIL_ID);
- }
-
if (FlagHas(&auth->flags, AR_DNS_PENDING)) {
delete_resolver_queries(auth);
- if (send_reports && IsUserPort(auth->client))
- sendheader(auth->client, REPORT_FAIL_DNS);
}
if (-1 < s_fd(&auth->socket)) {
cli_auth(auth->client) = NULL;
}
+/** Handle a 'ping' (authorization) timeout for a client.
+ * @param[in] cptr The client whose session authorization has timed out.
+ * @return Zero if client is kept, CPTR_KILLED if client rejected.
+ */
+int auth_ping_timeout(struct Client *cptr)
+{
+ struct AuthRequest *auth;
+ enum AuthRequestFlag flag;
+
+ auth = cli_auth(cptr);
+
+ /* Check for a user-controlled timeout. */
+ for (flag = 0; flag < AR_LAST_SCAN; ++flag) {
+ if (FlagHas(&auth->flags, flag)) {
+ /* Display message if they have sent a NICK and a USER but no
+ * nospoof PONG.
+ */
+ if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username) {
+ send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
+ ":Your client may not be compatible with this server.");
+ send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
+ ":Compatible clients are available at %s",
+ feature_str(FEAT_URL_CLIENTS));
+ }
+ return exit_client_msg(cptr, cptr, &me, "Registration Timeout");
+ }
+ }
+
+ /* Check for iauth timeout. */
+ if (FlagHas(&auth->flags, AR_IAUTH_PENDING)) {
+ sendto_iauth(cptr, "T");
+ if (IAuthHas(iauth, IAUTH_REQUIRED)) {
+ sendheader(cptr, REPORT_FAIL_IAUTH);
+ return exit_client_msg(cptr, cptr, &me, "Authorization Timeout");
+ }
+ FlagClr(&auth->flags, AR_IAUTH_PENDING);
+ return check_auth_finished(auth);
+ }
+
+ assert(0 && "Unexpectedly reached end of auth_ping_timeout()");
+ return 0;
+}
+
/** Timeout a given auth request.
* @param[in] ev A timer event whose associated data is the expired
* struct AuthRequest.
/* Report the timeout in the log. */
log_write(LS_RESOLVER, L_INFO, 0, "Registration timeout %s",
get_client_name(auth->client, HIDE_IP));
- /* Tell iauth if we will let the client on. */
- if (FlagHas(&auth->flags, AR_IAUTH_PENDING)
- && !IAuthHas(iauth, IAUTH_REQUIRED))
- {
- sendto_iauth(auth->client, "T");
- FlagClr(&auth->flags , AR_IAUTH_PENDING);
+
+ /* Notify client if ident lookup failed. */
+ if (FlagHas(&auth->flags, AR_AUTH_PENDING)) {
+ FlagClr(&auth->flags, AR_AUTH_PENDING);
+ if (IsUserPort(auth->client))
+ sendheader(auth->client, REPORT_FAIL_ID);
+ }
+
+ /* Likewise if dns lookup failed. */
+ if (FlagHas(&auth->flags, AR_DNS_PENDING)) {
+ delete_resolver_queries(auth);
+ if (IsUserPort(auth->client))
+ sendheader(auth->client, REPORT_FAIL_DNS);
}
+
/* Try to register the client. */
- check_auth_finished(auth, 1);
+ check_auth_finished(auth);
}
}
ircd_strncpy(cli_sockhost(auth->client), h_name, HOSTLEN);
sendto_iauth(auth->client, "N %s", h_name);
}
- check_auth_finished(auth, 0);
+ check_auth_finished(auth);
}
/** Flag the client to show an attempt to contact the ident server on
add_client_to_list(client);
/* Check which auth events remain pending. */
- check_auth_finished(auth, 0);
+ check_auth_finished(auth);
}
/** Mark that a user has PONGed while unregistered.
return 0;
}
FlagClr(&auth->flags, AR_NEEDS_PONG);
- return check_auth_finished(auth, 0);
+ return check_auth_finished(auth);
}
/** Record a user's claimed username and userinfo.
sendto_iauth(cptr, "U %s :%s", username, userinfo);
else if (IAuthHas(iauth, IAUTH_ADDLINFO))
sendto_iauth(cptr, "U %s", username);
- return check_auth_finished(auth, 0);
+ return check_auth_finished(auth);
}
/** Handle authorization-related aspects of initial nickname selection.
}
if (IAuthHas(iauth, IAUTH_UNDERNET))
sendto_iauth(auth->client, "n %s", nickname);
- return check_auth_finished(auth, 0);
+ return check_auth_finished(auth);
}
/** Record a user's password.
{
assert(auth != NULL);
FlagClr(&auth->flags, AR_CAP_PENDING);
- return check_auth_finished(auth, 0);
+ return check_auth_finished(auth);
}
/** Attempt to spawn the process for an IAuth instance.
ircd_ntoa(&cli_ip(cli)));
else if (handler(iauth, cli, parc - 3, params + 3))
/* Handler indicated a possible state change. */
- check_auth_finished(auth, 0);
+ check_auth_finished(auth);
}
}
}