1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
19 /* $ModDesc: Provides support for RFC1413 ident lookups */
21 class IdentRequestSocket : public InspSocket
26 IdentRequestSocket(InspIRCd *Server, userrec *user, int timeout, const std::string &bindip)
27 : InspSocket(Server, user->GetIPString(), 113, false, timeout, bindip), user(user)
32 virtual bool OnConnected()
34 /* Both sockaddr_in and sockaddr_in6 can be safely casted to sockaddr, especially since the
35 * only members we use are in a part of the struct that should always be identical (at the
38 Instance->Log(DEBUG, "Sending ident request to %s", user->GetIPString());
41 sockaddr_in laddr, raddr;
43 sockaddr_in6 laddr, raddr;
46 socklen_t laddrsz = sizeof(laddr);
47 socklen_t raddrsz = sizeof(raddr);
49 if ((getsockname(user->GetFd(), (sockaddr*) &laddr, &laddrsz) != 0) || (getpeername(user->GetFd(), (sockaddr*) &raddr, &raddrsz) != 0))
58 snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin_port), ntohs(laddr.sin_port));
60 snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin6_port), ntohs(laddr.sin6_port));
68 virtual void OnClose()
70 /* There used to be a check against the fd table here, to make sure the user hadn't been
71 * deleted but not yet had their socket closed or something along those lines, dated june
72 * 2006. Since we added the global cull list and such, I don't *think* that is necessary
73 * anymore. If you're getting odd crashes here, that's probably why ;) -Special */
75 if (*user->ident == '~' && user->GetExt("ident_socket"))
76 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
78 user->Shrink("ident_socket");
79 Instance->next_call = Instance->Time();
82 virtual void OnError(InspSocketError e)
84 // Quick check to make sure that this hasn't been sent ;)
85 if (*user->ident == '~' && user->GetExt("ident_socket"))
86 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
88 user->Shrink("ident_socket");
89 Instance->next_call = Instance->Time();
92 virtual bool OnDataReady()
94 char *ibuf = this->Read();
98 // We don't really need to buffer for incomplete replies here, since IDENT replies are
99 // extremely short - there is *no* sane reason it'd be in more than one packet
101 irc::sepstream sep(ibuf, ':');
103 for (int i = 0; sep.GetToken(token); i++)
105 // We only really care about the 4th portion
109 char ident[IDENTMAX + 2];
111 // Truncate the ident at any characters we don't like, skip leading spaces
113 for (const char *j = token.c_str(); *j && (k < IDENTMAX + 1); j++)
118 // Rules taken from InspIRCd::IsIdent
119 if (((*j >= 'A') && (*j <= '}')) || ((*j >= '0') && (*j <= '9')) || (*j == '-') || (*j == '.'))
130 // Redundant check with IsIdent, in case that changes and this doesn't (paranoia!)
131 if (*ident && Instance->IsIdent(ident))
133 strlcpy(user->ident, ident, IDENTMAX);
134 user->WriteServ("NOTICE Auth :*** Found your ident: %s", user->ident);
135 Instance->next_call = Instance->Time();
145 class ModuleIdent : public Module
150 ModuleIdent(InspIRCd *Me)
156 virtual ~ModuleIdent()
160 virtual Version GetVersion()
162 return Version(1, 1, 1, 0, VF_VENDOR, API_VERSION);
165 virtual void Implements(char *List)
167 List[I_OnRehash] = List[I_OnUserRegister] = List[I_OnCheckReady] = List[I_OnCleanup] = List[I_OnUserDisconnect] = 1;
170 virtual void OnRehash(userrec *user, const std::string ¶m)
172 ConfigReader MyConf(ServerInstance);
174 RequestTimeout = MyConf.ReadInteger("ident", "timeout", 0, true);
179 virtual int OnUserRegister(userrec *user)
181 /* userrec::ident is currently the username field from USER; with m_ident loaded, that
182 * should be preceded by a ~. The field is actually IDENTMAX+2 characters wide. */
183 memmove(user->ident + 1, user->ident, IDENTMAX);
184 user->ident[0] = '~';
185 // Ensure that it is null terminated
186 user->ident[IDENTMAX + 1] = '\0';
188 user->WriteServ("NOTICE Auth :*** Looking up your ident...");
190 // Get the IP that the user is connected to, and bind to that for the outgoing connection
196 socklen_t laddrsz = sizeof(laddr);
198 if (getsockname(user->GetFd(), (sockaddr*) &laddr, &laddrsz) != 0)
200 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead.", user->ident);
205 const char *ip = inet_ntoa(laddr.sin_addr);
207 char ip[INET6_ADDRSTRLEN + 1];
208 inet_ntop(laddr.sin6_family, &laddr.sin6_addr, ip, INET6_ADDRSTRLEN);
211 IdentRequestSocket *isock = new IdentRequestSocket(ServerInstance, user, RequestTimeout, ip);
212 if (isock->GetFd() > -1)
213 user->Extend("ident_socket", isock);
215 if (ServerInstance->SocketCull.find(isock) == ServerInstance->SocketCull.end())
216 ServerInstance->SocketCull[isock] = isock;
220 virtual bool OnCheckReady(userrec *user)
222 return (!user->GetExt("ident_socket"));
225 virtual void OnCleanup(int target_type, void *item)
227 if (target_type == TYPE_USER)
229 IdentRequestSocket *isock;
230 userrec *user = (userrec*)item;
231 if (user->GetExt("ident_socket", isock))
236 virtual void OnUserDisconnect(userrec *user)
238 IdentRequestSocket *isock;
239 if (user->GetExt("ident_socket", isock))
244 MODULE_INIT(ModuleIdent);