]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ident.cc
SSL->HTTP gatewaying support by Benno Rice
[thirdparty/squid.git] / src / ident.cc
1
2 /*
3 * $Id: ident.cc,v 1.58 2001/04/14 00:03:23 hno Exp $
4 *
5 * DEBUG: section 30 Ident (RFC 931)
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "squid.h"
37
38 #if USE_IDENT
39
40 #define IDENT_PORT 113
41 #define IDENT_KEY_SZ 50
42
43 typedef struct _IdentClient {
44 IDCB *callback;
45 void *callback_data;
46 struct _IdentClient *next;
47 } IdentClient;
48
49 typedef struct _IdentStateData {
50 hash_link hash; /* must be first */
51 int fd; /* IDENT fd */
52 struct sockaddr_in me;
53 struct sockaddr_in my_peer;
54 IdentClient *clients;
55 } IdentStateData;
56
57 static PF identReadReply;
58 static PF identClose;
59 static PF identTimeout;
60 static CNCB identConnectDone;
61 static hash_table *ident_hash = NULL;
62 static void identClientAdd(IdentStateData *, IDCB *, void *);
63
64 /**** PRIVATE FUNCTIONS ****/
65
66 static void
67 identCallback(IdentStateData * state, char *result)
68 {
69 IdentClient *client;
70 if (result && *result == '\0')
71 result = NULL;
72 while ((client = state->clients)) {
73 state->clients = client->next;
74 if (cbdataValid(client->callback_data))
75 client->callback(result, client->callback_data);
76 cbdataUnlock(client->callback_data);
77 xfree(client);
78 }
79 }
80
81 static void
82 identClose(int fdnotused, void *data)
83 {
84 IdentStateData *state = data;
85 identCallback(state, NULL);
86 comm_close(state->fd);
87 hash_remove_link(ident_hash, (hash_link *) state);
88 cbdataFree(state);
89 }
90
91 static void
92 identTimeout(int fd, void *data)
93 {
94 IdentStateData *state = data;
95 debug(30, 3) ("identTimeout: FD %d, %s\n", fd,
96 inet_ntoa(state->my_peer.sin_addr));
97 comm_close(fd);
98 }
99
100 static void
101 identConnectDone(int fd, int status, void *data)
102 {
103 IdentStateData *state = data;
104 IdentClient *c;
105 MemBuf mb;
106 if (status != COMM_OK) {
107 /* Failed to connect */
108 comm_close(fd);
109 return;
110 }
111 /*
112 * see if our clients still care
113 */
114 for (c = state->clients; c; c = c->next) {
115 if (cbdataValid(c->callback_data))
116 break;
117 }
118 if (c == NULL) {
119 /* no clients care */
120 comm_close(fd);
121 return;
122 }
123 memBufDefInit(&mb);
124 memBufPrintf(&mb, "%d, %d\r\n",
125 ntohs(state->my_peer.sin_port),
126 ntohs(state->me.sin_port));
127 comm_write_mbuf(fd, mb, NULL, state);
128 commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
129 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
130 }
131
132 static void
133 identReadReply(int fd, void *data)
134 {
135 IdentStateData *state = data;
136 LOCAL_ARRAY(char, buf, BUFSIZ);
137 char *ident = NULL;
138 char *t = NULL;
139 int len = -1;
140 buf[0] = '\0';
141 statCounter.syscalls.sock.reads++;
142 len = FD_READ_METHOD(fd, buf, BUFSIZ - 1);
143 fd_bytes(fd, len, FD_READ);
144 if (len <= 0) {
145 comm_close(fd);
146 return;
147 }
148 /*
149 * XXX This isn't really very tolerant. It should read until EOL
150 * or EOF and then decode the answer... If the reply is fragmented
151 * then this will fail
152 */
153 buf[len] = '\0';
154 if ((t = strchr(buf, '\r')))
155 *t = '\0';
156 if ((t = strchr(buf, '\n')))
157 *t = '\0';
158 debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
159 if (strstr(buf, "USERID")) {
160 if ((ident = strrchr(buf, ':'))) {
161 while (xisspace(*++ident));
162 identCallback(state, ident);
163 }
164 }
165 comm_close(fd);
166 }
167
168
169 static void
170 identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
171 {
172 IdentClient *c = xcalloc(1, sizeof(*c));
173 IdentClient **C;
174 c->callback = callback;
175 c->callback_data = callback_data;
176 cbdataLock(callback_data);
177 for (C = &state->clients; *C; C = &(*C)->next);
178 *C = c;
179 }
180
181 CBDATA_TYPE(IdentStateData);
182
183 /**** PUBLIC FUNCTIONS ****/
184
185 /*
186 * start a TCP connection to the peer host on port 113
187 */
188 void
189 identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data)
190 {
191 IdentStateData *state;
192 int fd;
193 char key1[IDENT_KEY_SZ];
194 char key2[IDENT_KEY_SZ];
195 char key[IDENT_KEY_SZ];
196 snprintf(key1, IDENT_KEY_SZ, "%s:%d",
197 inet_ntoa(me->sin_addr),
198 ntohs(me->sin_port));
199 snprintf(key2, IDENT_KEY_SZ, "%s:%d",
200 inet_ntoa(my_peer->sin_addr),
201 ntohs(my_peer->sin_port));
202 snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
203 if ((state = hash_lookup(ident_hash, key)) != NULL) {
204 identClientAdd(state, callback, data);
205 return;
206 }
207 fd = comm_open(SOCK_STREAM,
208 0,
209 me->sin_addr,
210 0,
211 COMM_NONBLOCKING,
212 "ident");
213 if (fd == COMM_ERROR) {
214 /* Failed to get a local socket */
215 callback(NULL, data);
216 return;
217 }
218 CBDATA_INIT_TYPE(IdentStateData);
219 state = cbdataAlloc(IdentStateData);
220 state->hash.key = xstrdup(key);
221 state->fd = fd;
222 state->me = *me;
223 state->my_peer = *my_peer;
224 identClientAdd(state, callback, data);
225 hash_join(ident_hash, &state->hash);
226 comm_add_close_handler(fd,
227 identClose,
228 state);
229 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
230 commConnectStart(fd,
231 inet_ntoa(state->my_peer.sin_addr),
232 IDENT_PORT,
233 identConnectDone,
234 state);
235 }
236
237 void
238 identInit(void)
239 {
240 ident_hash = hash_create((HASHCMP *) strcmp,
241 hashPrime(Squid_MaxFD / 8),
242 hash4);
243 }
244
245 #endif