]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ident/Ident.cc
4 * DEBUG: section 30 Ident (RFC 931)
5 * AUTHOR: Duane Wessels
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
35 #include "squid-old.h"
40 #include "comm/Connection.h"
41 #include "comm/ConnOpener.h"
42 #include "CommCalls.h"
43 #include "comm/Write.h"
44 #include "ident/Config.h"
45 #include "ident/Ident.h"
51 #define IDENT_PORT 113
52 #define IDENT_KEY_SZ 50
53 #define IDENT_BUFSIZE 4096
55 typedef struct _IdentClient
{
59 struct _IdentClient
*next
;
62 typedef struct _IdentStateData
{
63 hash_link hash
; /* must be first */
64 Comm::ConnectionPointer conn
;
66 char buf
[IDENT_BUFSIZE
];
69 // TODO: make these all a series of Async job calls. They are self-contained callbacks now.
70 static IOCB ReadReply
;
71 static IOCB WriteFeedback
;
74 static CNCB ConnectDone
;
75 static hash_table
*ident_hash
= NULL
;
76 static void ClientAdd(IdentStateData
* state
, IDCB
* callback
, void *callback_data
);
77 static void identCallback(IdentStateData
* state
, char *result
);
81 Ident::IdentConfig
Ident::TheConfig
;
83 /**** PRIVATE FUNCTIONS ****/
86 Ident::identCallback(IdentStateData
* state
, char *result
)
90 if (result
&& *result
== '\0')
93 while ((client
= state
->clients
)) {
95 state
->clients
= client
->next
;
97 if (cbdataReferenceValidDone(client
->callback_data
, &cbdata
))
98 client
->callback(result
, cbdata
);
105 Ident::Close(const CommCloseCbParams
¶ms
)
107 IdentStateData
*state
= (IdentStateData
*)params
.data
;
108 identCallback(state
, NULL
);
109 state
->conn
->close();
110 hash_remove_link(ident_hash
, (hash_link
*) state
);
111 xfree(state
->hash
.key
);
116 Ident::Timeout(const CommTimeoutCbParams
&io
)
118 debugs(30, 3, HERE
<< io
.conn
);
123 Ident::ConnectDone(const Comm::ConnectionPointer
&conn
, comm_err_t status
, int xerrno
, void *data
)
125 IdentStateData
*state
= (IdentStateData
*)data
;
127 if (status
!= COMM_OK
) {
128 if (status
== COMM_TIMEOUT
) {
129 debugs(30, 3, "IDENT connection timeout to " << state
->conn
->remote
);
134 assert(conn
!= NULL
&& conn
== state
->conn
);
137 * see if any of our clients still care
140 for (c
= state
->clients
; c
; c
= c
->next
) {
141 if (cbdataReferenceValid(c
->callback_data
))
146 /* no clients care */
151 comm_add_close_handler(conn
->fd
, Ident::Close
, state
);
155 mb
.Printf("%d, %d\r\n",
156 conn
->remote
.GetPort(),
157 conn
->local
.GetPort());
158 AsyncCall::Pointer writeCall
= commCbCall(5,4, "Ident::WriteFeedback",
159 CommIoCbPtrFun(Ident::WriteFeedback
, state
));
160 Comm::Write(conn
, &mb
, writeCall
);
161 AsyncCall::Pointer readCall
= commCbCall(5,4, "Ident::ReadReply",
162 CommIoCbPtrFun(Ident::ReadReply
, state
));
163 comm_read(conn
, state
->buf
, IDENT_BUFSIZE
, readCall
);
164 AsyncCall::Pointer timeoutCall
= commCbCall(5,4, "Ident::Timeout",
165 CommTimeoutCbPtrFun(Ident::Timeout
, state
));
166 commSetConnTimeout(conn
, Ident::TheConfig
.timeout
, timeoutCall
);
170 Ident::WriteFeedback(const Comm::ConnectionPointer
&conn
, char *buf
, size_t len
, comm_err_t flag
, int xerrno
, void *data
)
172 debugs(30, 5, HERE
<< conn
<< ": Wrote IDENT request " << len
<< " bytes.");
174 // TODO handle write errors better. retry or abort?
175 if (flag
!= COMM_OK
) {
176 debugs(30, 2, HERE
<< conn
<< " err-flags=" << flag
<< " IDENT write error: " << xstrerr(xerrno
));
182 Ident::ReadReply(const Comm::ConnectionPointer
&conn
, char *buf
, size_t len
, comm_err_t flag
, int xerrno
, void *data
)
184 IdentStateData
*state
= (IdentStateData
*)data
;
188 assert(buf
== state
->buf
);
189 assert(conn
->fd
== state
->conn
->fd
);
191 if (flag
!= COMM_OK
|| len
<= 0) {
192 state
->conn
->close();
197 * XXX This isn't really very tolerant. It should read until EOL
198 * or EOF and then decode the answer... If the reply is fragmented
199 * then this will fail
203 if ((t
= strchr(buf
, '\r')))
206 if ((t
= strchr(buf
, '\n')))
209 debugs(30, 5, HERE
<< conn
<< ": Read '" << buf
<< "'");
211 if (strstr(buf
, "USERID")) {
212 if ((ident
= strrchr(buf
, ':'))) {
213 while (xisspace(*++ident
));
214 Ident::identCallback(state
, ident
);
218 state
->conn
->close();
222 Ident::ClientAdd(IdentStateData
* state
, IDCB
* callback
, void *callback_data
)
224 IdentClient
*c
= (IdentClient
*)xcalloc(1, sizeof(*c
));
226 c
->callback
= callback
;
227 c
->callback_data
= cbdataReference(callback_data
);
229 for (C
= &state
->clients
; *C
; C
= &(*C
)->next
);
233 CBDATA_TYPE(IdentStateData
);
235 /**** PUBLIC FUNCTIONS ****/
238 * start a TCP connection to the peer host on port 113
241 Ident::Start(const Comm::ConnectionPointer
&conn
, IDCB
* callback
, void *data
)
243 IdentStateData
*state
;
244 char key1
[IDENT_KEY_SZ
];
245 char key2
[IDENT_KEY_SZ
];
246 char key
[IDENT_KEY_SZ
];
248 conn
->local
.ToURL(key1
, IDENT_KEY_SZ
);
249 conn
->remote
.ToURL(key2
, IDENT_KEY_SZ
);
250 snprintf(key
, IDENT_KEY_SZ
, "%s,%s", key1
, key2
);
255 if ((state
= (IdentStateData
*)hash_lookup(ident_hash
, key
)) != NULL
) {
256 ClientAdd(state
, callback
, data
);
260 CBDATA_INIT_TYPE(IdentStateData
);
261 state
= cbdataAlloc(IdentStateData
);
262 state
->hash
.key
= xstrdup(key
);
264 // copy the conn details. We dont want the original FD to be re-used by IDENT.
265 state
->conn
= conn
->copyDetails();
266 // NP: use random port for secure outbound to IDENT_PORT
267 state
->conn
->local
.SetPort(0);
268 state
->conn
->remote
.SetPort(IDENT_PORT
);
270 ClientAdd(state
, callback
, data
);
271 hash_join(ident_hash
, &state
->hash
);
273 AsyncCall::Pointer call
= commCbCall(30,3, "Ident::ConnectDone", CommConnectCbPtrFun(Ident::ConnectDone
, state
));
274 AsyncJob::Start(new Comm::ConnOpener(state
->conn
, call
, Ident::TheConfig
.timeout
));
281 debugs(30, DBG_CRITICAL
, "WARNING: Ident already initialized.");
285 ident_hash
= hash_create((HASHCMP
*) strcmp
,
286 hashPrime(Squid_MaxFD
/ 8),
290 #endif /* USE_IDENT */