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
149 std::string IdentBindIP;
151 ModuleIdent(InspIRCd *Me)
157 virtual ~ModuleIdent()
161 virtual Version GetVersion()
163 return Version(1, 1, 1, 0, VF_VENDOR, API_VERSION);
166 virtual void Implements(char *List)
168 List[I_OnRehash] = List[I_OnUserRegister] = List[I_OnCheckReady] = List[I_OnCleanup] = List[I_OnUserDisconnect] = 1;
171 virtual void OnRehash(userrec *user, const std::string ¶m)
173 ConfigReader MyConf(ServerInstance);
175 RequestTimeout = MyConf.ReadInteger("ident", "timeout", 0, true);
178 IdentBindIP = MyConf.ReadValue("ident", "bind", 0);
181 virtual int OnUserRegister(userrec *user)
183 /* userrec::ident is currently the username field from USER; with m_ident loaded, that
184 * should be preceded by a ~. The field is actually IDENTMAX+2 characters wide. */
185 memmove(user->ident + 1, user->ident, IDENTMAX);
186 user->ident[0] = '~';
187 // Ensure that it is null terminated
188 user->ident[IDENTMAX + 1] = '\0';
190 user->WriteServ("NOTICE Auth :*** Looking up your ident...");
192 IdentRequestSocket *isock = new IdentRequestSocket(ServerInstance, user, RequestTimeout, IdentBindIP);
193 user->Extend("ident_socket", isock);
197 virtual bool OnCheckReady(userrec *user)
199 return (!user->GetExt("ident_socket"));
202 virtual void OnCleanup(int target_type, void *item)
204 if (target_type == TYPE_USER)
206 IdentRequestSocket *isock;
207 userrec *user = (userrec*)item;
208 if (user->GetExt("ident_socket", isock))
213 virtual void OnUserDisconnect(userrec *user)
215 IdentRequestSocket *isock;
216 if (user->GetExt("ident_socket", isock))
221 MODULE_INIT(ModuleIdent);