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
27 IdentRequestSocket(InspIRCd *Server, userrec *user, int timeout, const std::string &bindip)
28 : InspSocket(Server, user->GetIPString(), 113, false, timeout, bindip), user(user)
30 original_fd = user->GetFd();
31 Instance->Log(DEBUG, "Ident request against user with fd %d", original_fd);
34 virtual bool OnConnected()
36 if (Instance->SE->GetRef(original_fd) == user)
38 Instance->Log(DEBUG,"Oh dear, our user has gone AWOL on fd %d", original_fd);
42 /* Both sockaddr_in and sockaddr_in6 can be safely casted to sockaddr, especially since the
43 * only members we use are in a part of the struct that should always be identical (at the
46 Instance->Log(DEBUG, "Sending ident request to %s", user->GetIPString());
49 sockaddr_in laddr, raddr;
51 sockaddr_in6 laddr, raddr;
54 socklen_t laddrsz = sizeof(laddr);
55 socklen_t raddrsz = sizeof(raddr);
57 if ((getsockname(user->GetFd(), (sockaddr*) &laddr, &laddrsz) != 0) || (getpeername(user->GetFd(), (sockaddr*) &raddr, &raddrsz) != 0))
66 snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin_port), ntohs(laddr.sin_port));
68 snprintf(req, sizeof(req), "%d,%d\r\n", ntohs(raddr.sin6_port), ntohs(laddr.sin6_port));
76 virtual void OnClose()
78 /* There used to be a check against the fd table here, to make sure the user hadn't been
79 * deleted but not yet had their socket closed or something along those lines, dated june
80 * 2006. Since we added the global cull list and such, I don't *think* that is necessary
82 * -- YES IT IS!!!! DO NOT REMOVE IT, THIS IS WHAT THE WARNING ABOVE THE OLD CODE SAID :P
84 if (Instance->SE->GetRef(original_fd) == user)
86 Instance->Log(DEBUG,"Oh dear, our user has gone AWOL on fd %d", original_fd);
90 if (*user->ident == '~' && user->GetExt("ident_socket"))
91 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
93 user->Shrink("ident_socket");
94 Instance->next_call = Instance->Time();
97 virtual void OnError(InspSocketError e)
99 if (Instance->SE->GetRef(original_fd) == user)
101 Instance->Log(DEBUG,"Oh dear, our user has gone AWOL on fd %d", original_fd);
105 // Quick check to make sure that this hasn't been sent ;)
106 if (*user->ident == '~' && user->GetExt("ident_socket"))
107 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead", user->ident);
109 user->Shrink("ident_socket");
110 Instance->next_call = Instance->Time();
113 virtual bool OnDataReady()
115 if (Instance->SE->GetRef(original_fd) == user)
117 Instance->Log(DEBUG,"Oh dear, our user has gone AWOL on fd %d", original_fd);
121 char *ibuf = this->Read();
125 // We don't really need to buffer for incomplete replies here, since IDENT replies are
126 // extremely short - there is *no* sane reason it'd be in more than one packet
128 irc::sepstream sep(ibuf, ':');
130 for (int i = 0; sep.GetToken(token); i++)
132 // We only really care about the 4th portion
136 char ident[IDENTMAX + 2];
138 // Truncate the ident at any characters we don't like, skip leading spaces
140 for (const char *j = token.c_str(); *j && (k < IDENTMAX + 1); j++)
145 // Rules taken from InspIRCd::IsIdent
146 if (((*j >= 'A') && (*j <= '}')) || ((*j >= '0') && (*j <= '9')) || (*j == '-') || (*j == '.'))
157 // Redundant check with IsIdent, in case that changes and this doesn't (paranoia!)
158 if (*ident && Instance->IsIdent(ident))
160 strlcpy(user->ident, ident, IDENTMAX);
161 user->WriteServ("NOTICE Auth :*** Found your ident: %s", user->ident);
162 Instance->next_call = Instance->Time();
172 class ModuleIdent : public Module
177 ModuleIdent(InspIRCd *Me)
183 virtual ~ModuleIdent()
187 virtual Version GetVersion()
189 return Version(1, 1, 1, 0, VF_VENDOR, API_VERSION);
192 virtual void Implements(char *List)
194 List[I_OnRehash] = List[I_OnUserRegister] = List[I_OnCheckReady] = List[I_OnCleanup] = List[I_OnUserDisconnect] = 1;
197 virtual void OnRehash(userrec *user, const std::string ¶m)
199 ConfigReader MyConf(ServerInstance);
201 RequestTimeout = MyConf.ReadInteger("ident", "timeout", 0, true);
206 virtual int OnUserRegister(userrec *user)
208 /* userrec::ident is currently the username field from USER; with m_ident loaded, that
209 * should be preceded by a ~. The field is actually IDENTMAX+2 characters wide. */
210 memmove(user->ident + 1, user->ident, IDENTMAX);
211 user->ident[0] = '~';
212 // Ensure that it is null terminated
213 user->ident[IDENTMAX + 1] = '\0';
215 user->WriteServ("NOTICE Auth :*** Looking up your ident...");
217 // Get the IP that the user is connected to, and bind to that for the outgoing connection
223 socklen_t laddrsz = sizeof(laddr);
225 if (getsockname(user->GetFd(), (sockaddr*) &laddr, &laddrsz) != 0)
227 user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead.", user->ident);
232 const char *ip = inet_ntoa(laddr.sin_addr);
234 char ip[INET6_ADDRSTRLEN + 1];
235 inet_ntop(laddr.sin6_family, &laddr.sin6_addr, ip, INET6_ADDRSTRLEN);
238 IdentRequestSocket *isock = new IdentRequestSocket(ServerInstance, user, RequestTimeout, ip);
239 if (isock->GetFd() > -1)
240 user->Extend("ident_socket", isock);
242 if (ServerInstance->SocketCull.find(isock) == ServerInstance->SocketCull.end())
243 ServerInstance->SocketCull[isock] = isock;
247 virtual bool OnCheckReady(userrec *user)
249 return (!user->GetExt("ident_socket"));
252 virtual void OnCleanup(int target_type, void *item)
254 if (target_type == TYPE_USER)
256 IdentRequestSocket *isock;
257 userrec *user = (userrec*)item;
258 if (user->GetExt("ident_socket", isock))
263 virtual void OnUserDisconnect(userrec *user)
265 IdentRequestSocket *isock;
266 if (user->GetExt("ident_socket", isock))
271 MODULE_INIT(ModuleIdent);