]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ident/Ident.cc
1st try to fix "make check" linking errors after "Configurable SSL error details...
[thirdparty/squid.git] / src / ident / Ident.cc
CommitLineData
f1443bd9 1/*
262a0e14 2 * $Id$
632e2027 3 *
3c66d057 4 * DEBUG: section 30 Ident (RFC 931)
632e2027 5 * AUTHOR: Duane Wessels
6 *
2b6662ba 7 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 8 * ----------------------------------------------------------
632e2027 9 *
2b6662ba 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.
632e2027 18 *
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.
26ac0430 23 *
632e2027 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.
26ac0430 28 *
632e2027 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
cbdec147 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 32 *
f1443bd9 33 */
34
35#include "squid.h"
4daaf3cb
AJ
36
37#if USE_IDENT
38
a46d2c0e 39#include "comm.h"
55cbb02b 40#include "comm/Connection.h"
aed188fd 41#include "comm/ConnOpener.h"
cfd66529 42#include "CommCalls.h"
ec41b64c 43#include "comm/Write.h"
4daaf3cb
AJ
44#include "ident/Config.h"
45#include "ident/Ident.h"
0eb49b6d 46#include "MemBuf.h"
f1443bd9 47
04f7fd38
AJ
48namespace Ident
49{
4daaf3cb 50
f1443bd9 51#define IDENT_PORT 113
05832ae1 52#define IDENT_KEY_SZ 50
abd8f140 53#define IDENT_BUFSIZE 4096
05832ae1 54
26ac0430 55typedef struct _IdentClient {
05832ae1 56 IDCB *callback;
57 void *callback_data;
62e76326 58
05832ae1 59 struct _IdentClient *next;
2fadd50d 60} IdentClient;
05832ae1 61
26ac0430 62typedef struct _IdentStateData {
186477c1 63 hash_link hash; /* must be first */
aed188fd 64 Comm::ConnectionPointer conn;
05832ae1 65 IdentClient *clients;
abd8f140 66 char buf[IDENT_BUFSIZE];
2fadd50d 67} IdentStateData;
f1443bd9 68
e0d28505 69// TODO: make these all a series of Async job calls. They are self-contained callbacks now.
4daaf3cb
AJ
70static IOCB ReadReply;
71static PF Close;
8d77a37c 72static CTCB Timeout;
4daaf3cb 73static CNCB ConnectDone;
05832ae1 74static hash_table *ident_hash = NULL;
4daaf3cb
AJ
75static void ClientAdd(IdentStateData * state, IDCB * callback, void *callback_data);
76static void identCallback(IdentStateData * state, char *result);
77
e5519212 78} // namespace Ident
4daaf3cb
AJ
79
80Ident::IdentConfig Ident::TheConfig;
05832ae1 81
82/**** PRIVATE FUNCTIONS ****/
83
52631ccc 84void
4daaf3cb 85Ident::identCallback(IdentStateData * state, char *result)
05832ae1 86{
87 IdentClient *client;
62e76326 88
05832ae1 89 if (result && *result == '\0')
62e76326 90 result = NULL;
91
05832ae1 92 while ((client = state->clients)) {
62e76326 93 void *cbdata;
94 state->clients = client->next;
95
96 if (cbdataReferenceValidDone(client->callback_data, &cbdata))
97 client->callback(result, cbdata);
98
99 xfree(client);
05832ae1 100 }
101}
f1443bd9 102
52631ccc 103void
4daaf3cb 104Ident::Close(int fdnotused, void *data)
f1443bd9 105{
be005338 106 IdentStateData *state = (IdentStateData *)data;
05832ae1 107 identCallback(state, NULL);
aed188fd 108 state->conn->close();
05832ae1 109 hash_remove_link(ident_hash, (hash_link *) state);
6fa85d6f 110 xfree(state->hash.key);
05832ae1 111 cbdataFree(state);
f1443bd9 112}
113
52631ccc 114void
8d77a37c 115Ident::Timeout(const CommTimeoutCbParams &io)
86cf9987 116{
8d77a37c
AJ
117 debugs(30, 3, HERE << io.conn);
118 io.conn->close();
86cf9987 119}
120
52631ccc 121void
f01d4b80 122Ident::ConnectDone(const Comm::ConnectionPointer &conn, comm_err_t status, int xerrno, void *data)
e5f6c5c2 123{
be005338 124 IdentStateData *state = (IdentStateData *)data;
62e76326 125
9e975e4e 126 if (status != COMM_OK) {
cfd66529 127 if (status == COMM_TIMEOUT) {
aed188fd 128 debugs(30, 3, "IDENT connection timeout to " << state->conn->remote);
cfd66529 129 }
62e76326 130 return;
f1443bd9 131 }
62e76326 132
aed188fd 133 assert(conn != NULL && conn == state->conn);
cfd66529 134
05832ae1 135 /*
fa80a8ef 136 * see if any of our clients still care
05832ae1 137 */
cfd66529 138 IdentClient *c;
05832ae1 139 for (c = state->clients; c; c = c->next) {
62e76326 140 if (cbdataReferenceValid(c->callback_data))
141 break;
05832ae1 142 }
62e76326 143
ac2a30fc 144 if (c == NULL) {
62e76326 145 /* no clients care */
80463bb4 146 conn->close();
62e76326 147 return;
ac2a30fc 148 }
62e76326 149
cfd66529
AJ
150 comm_add_close_handler(conn->fd, Ident::Close, state);
151
032785bf 152 MemBuf mb;
2fe7eff9 153 mb.init();
154 mb.Printf("%d, %d\r\n",
cfd66529
AJ
155 conn->remote.GetPort(),
156 conn->local.GetPort());
ec41b64c 157 AsyncCall::Pointer nil;
b0388924 158 Comm::Write(conn, &mb, nil);
8d77a37c
AJ
159 AsyncCall::Pointer readCall = commCbCall(5,4, "Ident::ReadReply",
160 CommIoCbPtrFun(Ident::ReadReply, state));
161 comm_read(conn, state->buf, IDENT_BUFSIZE, readCall);
162 AsyncCall::Pointer timeoutCall = commCbCall(5,4, "Ident::Timeout",
163 CommTimeoutCbPtrFun(Ident::Timeout, state));
164 commSetConnTimeout(conn, Ident::TheConfig.timeout, timeoutCall);
f1443bd9 165}
166
52631ccc 167void
e0d28505 168Ident::ReadReply(const Comm::ConnectionPointer &conn, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
f1443bd9 169{
be005338 170 IdentStateData *state = (IdentStateData *)data;
05832ae1 171 char *ident = NULL;
f1443bd9 172 char *t = NULL;
c4b7a5a9 173
cfd66529 174 assert(buf == state->buf);
e0d28505 175 assert(conn->fd == state->conn->fd);
62e76326 176
be005338 177 if (flag != COMM_OK || len <= 0) {
aed188fd 178 state->conn->close();
62e76326 179 return;
05832ae1 180 }
62e76326 181
05832ae1 182 /*
183 * XXX This isn't really very tolerant. It should read until EOL
184 * or EOF and then decode the answer... If the reply is fragmented
185 * then this will fail
186 */
187 buf[len] = '\0';
62e76326 188
05832ae1 189 if ((t = strchr(buf, '\r')))
62e76326 190 *t = '\0';
191
05832ae1 192 if ((t = strchr(buf, '\n')))
62e76326 193 *t = '\0';
194
e0d28505 195 debugs(30, 5, HERE << conn << ": Read '" << buf << "'");
62e76326 196
05832ae1 197 if (strstr(buf, "USERID")) {
62e76326 198 if ((ident = strrchr(buf, ':'))) {
3d0ac046 199 while (xisspace(*++ident));
4daaf3cb 200 Ident::identCallback(state, ident);
62e76326 201 }
f1443bd9 202 }
62e76326 203
aed188fd 204 state->conn->close();
ba1d2afa 205}
206
52631ccc 207void
4daaf3cb 208Ident::ClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
05832ae1 209{
be005338 210 IdentClient *c = (IdentClient *)xcalloc(1, sizeof(*c));
05832ae1 211 IdentClient **C;
212 c->callback = callback;
fa80a8ef 213 c->callback_data = cbdataReference(callback_data);
62e76326 214
3d0ac046 215 for (C = &state->clients; *C; C = &(*C)->next);
05832ae1 216 *C = c;
217}
218
28c60158 219CBDATA_TYPE(IdentStateData);
220
05832ae1 221/**** PUBLIC FUNCTIONS ****/
222
223/*
224 * start a TCP connection to the peer host on port 113
225 */
226void
00406b24 227Ident::Start(const Comm::ConnectionPointer &conn, IDCB * callback, void *data)
05832ae1 228{
229 IdentStateData *state;
05832ae1 230 char key1[IDENT_KEY_SZ];
231 char key2[IDENT_KEY_SZ];
232 char key[IDENT_KEY_SZ];
cc192b50 233
cfd66529
AJ
234 conn->local.ToURL(key1, IDENT_KEY_SZ);
235 conn->remote.ToURL(key2, IDENT_KEY_SZ);
05832ae1 236 snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
62e76326 237
4daaf3cb
AJ
238 if (!ident_hash) {
239 Init();
240 }
26ac0430 241 if ((state = (IdentStateData *)hash_lookup(ident_hash, key)) != NULL) {
4daaf3cb 242 ClientAdd(state, callback, data);
62e76326 243 return;
05832ae1 244 }
62e76326 245
28c60158 246 CBDATA_INIT_TYPE(IdentStateData);
72711e31 247 state = cbdataAlloc(IdentStateData);
186477c1 248 state->hash.key = xstrdup(key);
aed188fd
AJ
249
250 // copy the conn details. We dont want the original FD to be re-used by IDENT.
251 state->conn = conn->copyDetails();
252 // NP: use random port for secure outbound to IDENT_PORT
253 state->conn->local.SetPort(0);
cfd66529 254
4daaf3cb 255 ClientAdd(state, callback, data);
186477c1 256 hash_join(ident_hash, &state->hash);
cfd66529
AJ
257
258 AsyncCall::Pointer call = commCbCall(30,3, "Ident::ConnectDone", CommConnectCbPtrFun(Ident::ConnectDone, state));
855150a4 259 AsyncJob::Start(new Comm::ConnOpener(state->conn, call, Ident::TheConfig.timeout));
05832ae1 260}
261
262void
4daaf3cb 263Ident::Init(void)
ba1d2afa 264{
04f7fd38 265 if (ident_hash) {
4daaf3cb
AJ
266 debugs(30, DBG_CRITICAL, "WARNING: Ident already initialized.");
267 return;
268 }
269
30abd221 270 ident_hash = hash_create((HASHCMP *) strcmp,
62e76326 271 hashPrime(Squid_MaxFD / 8),
272 hash4);
f1443bd9 273}
4daaf3cb
AJ
274
275#endif /* USE_IDENT */