#define i_debug(iauth) ((iauth)->i_debug)
/** Active instance of IAuth. */
-struct IAuth *iauth;
+static struct IAuth *iauth;
+/** Freelist of AuthRequest structures. */
+static struct AuthRequest *auth_freelist;
static void iauth_sock_callback(struct Event *ev);
static void iauth_stderr_callback(struct Event *ev);
else
FlagSet(&auth->flags, AR_IAUTH_HURRY);
- destroy_auth_request(auth);
- if (!IsUserPort(auth->client))
- return 0;
- memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
- res = auth_set_username(auth);
- if (res == 0)
+ if (IsUserPort(auth->client))
+ {
+ memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
+ res = auth_set_username(auth);
+ if (res == 0)
res = register_user(auth->client, auth->client);
+ }
+ else
+ res = 0;
+ if (res == 0)
+ destroy_auth_request(auth);
return res;
}
if (t_active(&auth->timeout))
timer_del(&auth->timeout);
+
cli_auth(auth->client) = NULL;
+ auth->next = auth_freelist;
+ auth_freelist = auth;
}
/** Handle a 'ping' (authorization) timeout for a client.
auth = cli_auth(cptr);
+ /* Check whether the auth request is gone (more likely, it never
+ * existed, as in an outbound server connection). */
+ if (!auth)
+ return exit_client_msg(cptr, cptr, &me, "Registration Timeout");
+
/* Check for a user-controlled timeout. */
for (flag = 0; flag <= AR_LAST_SCAN; ++flag) {
if (FlagHas(&auth->flags, flag)) {
socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
/* Allocate the AuthRequest. */
- auth = MyCalloc(1, sizeof(*auth));
+ auth = auth_freelist;
+ if (auth)
+ auth_freelist = auth->next;
+ else
+ auth = MyMalloc(sizeof(*auth));
assert(0 != auth);
+ memset(auth, 0, sizeof(*auth));
auth->client = client;
cli_auth(client) = auth;
s_fd(&auth->socket) = -1;
/** Record a user's claimed username and userinfo.
* @param[in] auth Authorization request for client.
* @param[in] username Client's asserted username.
+ * @param[in] hostname Third argument of USER command (client's
+ * hostname, per RFC 1459).
+ * @param[in] servername Fourth argument of USER command (server's
+ * name, per RFC 1459).
* @param[in] userinfo Client's asserted self-description.
* @return Zero if client should be kept, CPTR_KILLED if rejected.
*/
-int auth_set_user(struct AuthRequest *auth, const char *username, const char *userinfo)
+int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo)
{
struct Client *cptr;
ircd_strncpy(cli_user(cptr)->username, username, USERLEN);
ircd_strncpy(cli_user(cptr)->host, cli_sockhost(cptr), HOSTLEN);
if (IAuthHas(iauth, IAUTH_UNDERNET))
- sendto_iauth(cptr, "U %s :%s", username, userinfo);
+ sendto_iauth(cptr, "U %s %s %s :%s", username, hostname, servername, userinfo);
else if (IAuthHas(iauth, IAUTH_ADDLINFO))
sendto_iauth(cptr, "U %s", username);
return check_auth_finished(auth);
*/
static void iauth_disconnect(struct IAuth *iauth)
{
- if (!i_GetConnected(iauth))
+ if (iauth == NULL)
return;
/* Close main socket. */
- close(s_fd(i_socket(iauth)));
- socket_del(i_socket(iauth));
- s_fd(i_socket(iauth)) = -1;
+ if (s_fd(i_socket(iauth)) != -1) {
+ close(s_fd(i_socket(iauth)));
+ socket_del(i_socket(iauth));
+ s_fd(i_socket(iauth)) = -1;
+ }
/* Close error socket. */
- close(s_fd(i_stderr(iauth)));
- socket_del(i_stderr(iauth));
- s_fd(i_stderr(iauth)) = -1;
+ if (s_fd(i_stderr(iauth)) != -1) {
+ close(s_fd(i_stderr(iauth)));
+ socket_del(i_stderr(iauth));
+ s_fd(i_stderr(iauth)) = -1;
+ }
}
/** Close all %IAuth connections marked as closing. */
/* Tack it onto the iauth sendq and try to write it. */
++iauth->i_sendM;
msgq_add(i_sendQ(iauth), mb, 0);
+ msgq_clean(mb);
iauth_write(iauth);
return 1;
}
return 0;
}
+/** Change a client's usermode.
+ * @param[in] iauth Active IAuth session.
+ * @param[in] cli Client referenced by command.
+ * @param[in] parc Number of parameters (at least one).
+ * @param[in] params Usermode arguments for client (with the first
+ * starting with '+').
+ * @return Zero.
+ */
+static int iauth_cmd_usermode(struct IAuth *iauth, struct Client *cli,
+ int parc, char **params)
+{
+ if (params[0][0] == '+')
+ {
+ set_user_mode(cli, cli, parc + 2, params - 2, ALLOWMODES_ANY);
+ }
+ return 0;
+}
+
+
/** Send a challenge string to the client.
* @param[in] iauth Active IAuth session.
* @param[in] cli Client referenced by command.
case 'u': handler = iauth_cmd_username_bad; has_cli = 1; break;
case 'N': handler = iauth_cmd_hostname; has_cli = 1; break;
case 'I': handler = iauth_cmd_ip_address; has_cli = 1; break;
+ case 'M': handler = iauth_cmd_usermode; has_cli = 1; break;
case 'C': handler = iauth_cmd_challenge; has_cli = 1; break;
case 'D': handler = iauth_cmd_done_client; has_cli = 1; break;
case 'R': handler = iauth_cmd_done_account; has_cli = 1; break;
} else {
/* Try to find the client associated with the request. */
id = strtol(params[0], NULL, 10);
- if (id < 0 || id > HighestFd || !(cli = LocalClientArray[id]))
+ if (parc < 3)
+ sendto_iauth(NULL, "E Missing :Need <id> <ip> <port>");
+ else if (id < 0 || id > HighestFd || !(cli = LocalClientArray[id]))
/* Client no longer exists (or never existed). */
sendto_iauth(NULL, "E Gone :[%s %s %s]", params[0], params[1],
params[2]);
assert(0 != iauth);
switch (ev_type(ev)) {
+ case ET_DESTROY:
+ /* We do not restart iauth here: the stdout handler does that for us. */
+ break;
case ET_READ:
iauth_read_stderr(iauth);
break;
case ET_ERROR:
log_write(LS_IAUTH, L_ERROR, 0, "IAuth stderr error: %s", strerror(ev_data(ev)));
- /* and fall through to the ET_EOF/ET_DESTROY case */
- case ET_DESTROY:
+ /* and fall through to the ET_EOF case */
case ET_EOF:
+ iauth_disconnect(iauth);
break;
default:
assert(0 && "Unrecognized event type");
send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":%s",
link->value.cp);
}
- send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":End of IAuth configuration.");
}
/** Report active iauth's statistics to \a cptr.
send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":%s",
link->value.cp);
}
- send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":End of IAuth statistics.");
}