/** * Kill an client identified by its nick name. * * Please note that after killig a client, its CLIENT cond CONNECTION * structures are invalid. So the caller must make sure on its own not to * access data of probably killed clients after calling this function! * * @param Client The client from which the command leading to the KILL has * been received, or NULL. The KILL will no be forwarded in this * direction. Only relevant when From is set, too. * @param From The client from which the command originated, or NULL for the local server. * @param Nick The nick name to kill. * @param Reason Text to send as reason to the client and other servers. */ GLOBAL bool IRC_KillClient(CLIENT *Client, CLIENT *From, const char *Nick, const char *Reason) { const char *msg; CONN_ID my_conn, conn; CLIENT *c; /* Do we know such a client in the network? */ c = Client_Search(Nick); if (!c) { LogDebug("Client with nick \"%s\" is unknown, not forwaring.", Nick); return CONNECTED; } /* Inform other servers */ IRC_WriteStrServersPrefix(From ? Client : NULL, From ? From : Client_ThisServer(), "KILL %s :%s", Nick, Reason); if (Client_Type(c) != CLIENT_USER && Client_Type(c) != CLIENT_GOTNICK) { /* Target of this KILL is not a regular user, this is * invalid! So we ignore this case if we received a * regular KILL from the network and try to kill the * client/connection anyway (but log an error!) if the * origin is the local server. */ if (Client != Client_ThisServer()) { /* Invalid KILL received from remote */ if (Client_Type(c) == CLIENT_SERVER) msg = ERR_CANTKILLSERVER_MSG; else msg = ERR_NOPRIVILEGES_MSG; return IRC_WriteErrClient(Client, msg, Client_ID(Client)); } Log(LOG_ERR, "Got KILL for invalid client type: %d, \"%s\"!", Client_Type(c), Nick); } /* Save ID of this connection */ my_conn = Client_Conn(Client); /* Kill the client NOW: * - Close the local connection (if there is one), * - Destroy the CLIENT structure for remote clients. * Note: Conn_Close() removes the CLIENT structure as well. */ conn = Client_Conn(c); if(conn > NONE) Conn_Close(conn, NULL, Reason, true); else Client_Destroy(c, NULL, Reason, false); /* Are we still connected or were we killed, too? */ if (my_conn > NONE && Conn_GetClient(my_conn)) return CONNECTED; else return DISCONNECTED; }
/** * Read result of the authenticator sub-process from pipe * * @param r_fd File descriptor of the pipe. * @param events (ignored IO specification) */ static void cb_Read_Auth_Result(int r_fd, UNUSED short events) { char user[CLIENT_USER_LEN], *ptr; CONN_ID conn; CLIENT *client; int result; size_t len; PROC_STAT *proc; LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events); conn = Conn_GetFromProc(r_fd); if (conn == NONE) { /* Ops, none found? Probably the connection has already * been closed!? We'll ignore that ... */ io_close(r_fd); LogDebug("Auth: Got callback for unknown connection!?"); return; } proc = Conn_GetProcStat(conn); client = Conn_GetClient(conn); /* Read result from pipe */ len = Proc_Read(proc, &result, sizeof(result)); Proc_Close(proc); if (len == 0) return; if (len != sizeof(result)) { Log(LOG_CRIT, "Auth: Got malformed result!"); Client_Reject(client, "Internal error", false); return; } if (result == true) { /* Authentication succeeded, now set the correct user name * supplied by the client (without prepended '~' for exmaple), * but cut it at the first '@' character: */ strlcpy(user, Client_OrigUser(client), sizeof(user)); ptr = strchr(user, '@'); if (ptr) *ptr = '\0'; Client_SetUser(client, user, true); (void)Login_User_PostAuth(client); } else Client_Reject(client, "Bad password", false); }
/** * Handler for the IRC "KILL" command. * * This function implements the IRC command "KILL" wich is used to selectively * disconnect clients. It can be used by IRC operators and servers, for example * to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1. * * Please note that this function is also called internally, without a real * KILL command being received over the network! Client is Client_ThisServer() * in this case, and the prefix in Req is NULL. * * @param Client The client from which this command has been received * or Client_ThisServer() when generated interanlly. * @param Req Request structure with prefix and all parameters. * @returns CONNECTED or DISCONNECTED. */ GLOBAL bool IRC_KILL( CLIENT *Client, REQUEST *Req ) { CLIENT *prefix, *c; char reason[COMMAND_LEN], *msg; CONN_ID my_conn, conn; assert (Client != NULL); assert (Req != NULL); if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client)) return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client)); if (Req->argc != 2) return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command); /* Get prefix (origin); use the client if no prefix is given. */ if (Req->prefix) prefix = Client_Search(Req->prefix); else prefix = Client; /* Log a warning message and use this server as origin when the * prefix (origin) is invalid. */ if (!prefix) { Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Req->prefix ); prefix = Client_ThisServer(); } if (Client != Client_ThisServer()) Log(LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask(prefix), Req->argv[0], Req->argv[1]); /* Build reason string: Prefix the "reason" if the originator is a * regular user, so users can't spoof KILLs of servers. */ if (Client_Type(Client) == CLIENT_USER) snprintf(reason, sizeof(reason), "KILLed by %s: %s", Client_ID(Client), Req->argv[1]); else strlcpy(reason, Req->argv[1], sizeof(reason)); /* Inform other servers */ IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s", Req->argv[0], reason); /* Save ID of this connection */ my_conn = Client_Conn( Client ); /* Do we host such a client? */ c = Client_Search( Req->argv[0] ); if( c ) { if(( Client_Type( c ) != CLIENT_USER ) && ( Client_Type( c ) != CLIENT_GOTNICK )) { /* Target of this KILL is not a regular user, this is * invalid! So we ignore this case if we received a * regular KILL from the network and try to kill the * client/connection anyway (but log an error!) if the * origin is the local server. */ if( Client != Client_ThisServer( )) { /* Invalid KILL received from remote */ if( Client_Type( c ) == CLIENT_SERVER ) msg = ERR_CANTKILLSERVER_MSG; else msg = ERR_NOPRIVILEGES_MSG; return IRC_WriteStrClient( Client, msg, Client_ID( Client )); } Log( LOG_ERR, "Got KILL for invalid client type: %d, \"%s\"!", Client_Type( c ), Req->argv[0] ); } /* Kill the client NOW: * - Close the local connection (if there is one), * - Destroy the CLIENT structure for remote clients. * Note: Conn_Close() removes the CLIENT structure as well. */ conn = Client_Conn( c ); if(conn > NONE) Conn_Close(conn, NULL, reason, true); else Client_Destroy(c, NULL, reason, false); } else Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] ); /* Are we still connected or were we killed, too? */ if(( my_conn > NONE ) && ( Conn_GetClient( my_conn ))) return CONNECTED; else return DISCONNECTED; } /* IRC_KILL */