/[cvs]/eggdrop1.9/src/telnet.c
ViewVC logotype

Annotation of /eggdrop1.9/src/telnet.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (hide annotations) (download) (as text)
Wed Apr 9 02:01:14 2003 UTC (16 years, 9 months ago) by stdarg
Branch: MAIN
Changes since 1.4: +1 -0 lines
File MIME type: text/x-chdr
* Support for ipv6 reverse dns

1 stdarg 1.1 #include <eggdrop/eggdrop.h>
2 stdarg 1.3 #include "core_config.h"
3 stdarg 1.1
4     /* Possible states of the connection. */
5     #define STATE_RESOLVE 0
6     #define STATE_NICKNAME 1
7     #define STATE_PASSWORD 2
8     #define STATE_PARTYLINE 3
9    
10     /* Telnet strings for controlling echo behavior. */
11     #define TELNET_ECHO 1
12     #define TELNET_AYT 246
13     #define TELNET_WILL 251
14     #define TELNET_WONT 252
15     #define TELNET_DO 253
16     #define TELNET_DONT 254
17     #define TELNET_CMD 255
18    
19     #define TELNET_ECHO_OFF "\377\373\001"
20     #define TELNET_ECHO_ON "\377\374\001"
21    
22     #define TFLAG_ECHO 1
23    
24     /* Flags for sessions. */
25     #define STEALTH_LOGIN 1
26    
27     typedef struct {
28     /* Who we're connected to. */
29     user_t *user;
30     char *nick, *ident, *host, *ip;
31     int port;
32     int idx;
33     int pid;
34    
35     /* Flags for this connection. */
36     int flags;
37    
38     /* Connection state we're in. */
39     int state, count;
40     } telnet_session_t;
41    
42     static int telnet_idx = -1;
43     static int telnet_port = 0;
44    
45     static void kill_session(telnet_session_t *session);
46    
47     static int telnet_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port);
48     static int telnet_on_read(void *client_data, int idx, char *data, int len);
49     static int telnet_on_eof(void *client_data, int idx, int err, const char *errmsg);
50     static int telnet_filter_read(void *client_data, int idx, char *data, int len);
51     static int telnet_filter_write(void *client_data, int idx, const char *data, int len);
52     static int telnet_filter_delete(void *client_data, int idx);
53    
54     static int ident_result(void *client_data, const char *ip, int port, const char *reply);
55     static int dns_result(void *client_data, const char *ip, const char *host);
56     static int process_results(telnet_session_t *session);
57    
58     static sockbuf_handler_t server_handler = {
59     "telnet server",
60     NULL, NULL, telnet_on_newclient,
61     NULL, NULL
62     };
63    
64     #define TELNET_FILTER_LEVEL SOCKBUF_LEVEL_TEXT_ALTERATION
65    
66     static sockbuf_filter_t telnet_filter = {
67     "telnet filter", TELNET_FILTER_LEVEL,
68     NULL, NULL, NULL,
69     telnet_filter_read, telnet_filter_write, NULL,
70     NULL, telnet_filter_delete
71     };
72    
73     static sockbuf_handler_t client_handler = {
74     "telnet",
75     NULL, telnet_on_eof, NULL,
76     telnet_on_read, NULL
77     };
78    
79     int telnet_init()
80     {
81     /* Open our listening socket. */
82 stdarg 1.3 telnet_idx = egg_server(core_config.telnet_vhost, core_config.telnet_port, &telnet_port);
83 stdarg 1.1 sockbuf_set_handler(telnet_idx, &server_handler, NULL);
84     return(0);
85     }
86    
87     static void kill_session(telnet_session_t *session)
88     {
89     sockbuf_delete(session->idx);
90     if (session->ip) free(session->ip);
91     if (session->host) free(session->host);
92     if (session->ident) free(session->ident);
93     if (session->nick) free(session->nick);
94     free(session);
95     }
96    
97     static int telnet_on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
98     {
99     telnet_session_t *session;
100     int *flags;
101    
102     session = calloc(1, sizeof(*session));
103     session->ip = strdup(peer_ip);
104     session->port = peer_port;
105     session->idx = newidx;
106    
107     sockbuf_set_handler(newidx, &client_handler, session);
108     flags = calloc(1, sizeof(*flags));
109     sockbuf_attach_filter(newidx, &telnet_filter, flags);
110     linemode_on(newidx);
111    
112 stdarg 1.5 egg_iprintf(newidx, "Hello %s/%d!\r\n", peer_ip, peer_port);
113 stdarg 1.1 /* Stealth logins are where we don't say anything until we know they
114     * are a valid user. */
115 stdarg 1.3 if (core_config.telnet_stealth) {
116 stdarg 1.1 session->state = STATE_RESOLVE;
117     }
118     else {
119 stdarg 1.2 sockbuf_write(newidx, "\r\nPlease enter your nickname.\r\n", -1);
120 stdarg 1.1 session->state = STATE_NICKNAME;
121     session->count = 0;
122     }
123    
124     /* Start lookups. */
125 stdarg 1.3 egg_ident_lookup(peer_ip, peer_port, telnet_port, -1, ident_result, session);
126 stdarg 1.2 egg_dns_reverse(peer_ip, -1, dns_result, session);
127 stdarg 1.1
128     return(0);
129     }
130    
131     static int ident_result(void *client_data, const char *ip, int port, const char *reply)
132     {
133     telnet_session_t *session = client_data;
134    
135     if (reply) session->ident = strdup(reply);
136     else session->ident = strdup("~telnet");
137     process_results(session);
138     return(0);
139     }
140    
141 stdarg 1.2 static int dns_result(void *client_data, const char *ip, const char *host)
142 stdarg 1.1 {
143     telnet_session_t *session = client_data;
144    
145 stdarg 1.4 if (!host) host = ip;
146 stdarg 1.1 session->host = strdup(host);
147     process_results(session);
148     return(0);
149     }
150    
151     static int process_results(telnet_session_t *session)
152     {
153     char *fakehost;
154    
155     if (!session->ident || !session->host) return(0);
156    
157     if (session->state == STATE_PARTYLINE) {
158     partyline_update_info(session->pid, session->ident, session->host);
159     return(0);
160     }
161     if (session->flags & STEALTH_LOGIN) {
162     fakehost = msprintf("-telnet!%s@%s", session->ident, session->host);
163     if (!user_lookup_by_irchost(fakehost)) {
164     kill_session(session);
165     return(0);
166     }
167 stdarg 1.2 sockbuf_write(session->idx, "\r\nPlease enter your nickname.\r\n", -1);
168 stdarg 1.1 session->state = STATE_NICKNAME;
169     }
170     return(0);
171     }
172    
173     static int telnet_on_read(void *client_data, int idx, char *data, int len)
174     {
175     telnet_session_t *session = client_data;
176    
177     switch (session->state) {
178     case STATE_PARTYLINE:
179     partyline_on_input(session->pid, data, len);
180     break;
181     case STATE_NICKNAME:
182     session->nick = strdup(data);
183     session->state = STATE_PASSWORD;
184     sockbuf_write(session->idx, TELNET_ECHO_OFF, -1);
185     sockbuf_write(session->idx, "Please enter your password.\r\n", -1);
186     break;
187     case STATE_PASSWORD:
188     sockbuf_write(session->idx, TELNET_ECHO_ON, -1);
189     session->user = user_lookup_authed(session->nick, data);
190     if (!session->user) {
191     sockbuf_write(session->idx, "Invalid username/password.\r\n\r\n", -1);
192     session->count++;
193 stdarg 1.3 if (session->count > core_config.telnet_max_retries) {
194 stdarg 1.1 kill_session(session);
195     break;
196     }
197     free(session->nick);
198     session->nick = NULL;
199     sockbuf_write(session->idx, "Please enter your nickname.\r\n", -1);
200     session->state = STATE_NICKNAME;
201     }
202     else {
203 stdarg 1.2 session->pid = partyline_connect(session->idx, -1, session->user, session->nick, session->ident ? session->ident : "~telnet", session->host ? session->host : session->ip);
204 stdarg 1.1 session->state = STATE_PARTYLINE;
205 stdarg 1.2 egg_iprintf(idx, "\r\nWelcome to the telnet partyline interface!\r\n");
206     if (session->ident) egg_iprintf(idx, "Your ident is: %s\r\n", session->ident);
207     if (session->host) egg_iprintf(idx, "Your hostname is: %s\r\n", session->host);
208 stdarg 1.1 }
209     break;
210     }
211     return(0);
212     }
213    
214     static int telnet_on_eof(void *client_data, int idx, int err, const char *errmsg)
215     {
216     telnet_session_t *session = client_data;
217    
218 stdarg 1.2 if (session->state == STATE_PARTYLINE) partyline_disconnect(session->pid, err ? errmsg : NULL);
219 stdarg 1.1 kill_session(session);
220     return(0);
221     }
222    
223     static int telnet_filter_read(void *client_data, int idx, char *data, int len)
224     {
225     char *cmd;
226     int type, arg, remove, flags;
227    
228     flags = *(int *)client_data;
229     cmd = data;
230     while ((cmd = memchr(cmd, TELNET_CMD, len))) {
231     type = *(unsigned char *)(cmd+1);
232     if (type == TELNET_CMD) remove = 1;
233     else if (type == TELNET_DO) {
234     arg = *(cmd+2);
235     if (arg == TELNET_ECHO) flags |= TFLAG_ECHO;
236     remove = 3;
237     }
238     else if (type == TELNET_DONT) {
239     arg = *(cmd+2);
240     if (arg == TELNET_ECHO) flags &= ~TFLAG_ECHO;
241     remove = 3;
242     }
243     else if (type == TELNET_WILL || type == TELNET_WONT) {
244     remove = 3;
245     }
246     else {
247     remove = 2;
248     }
249     memmove(cmd, cmd+remove, len - (cmd - data) - remove + 1);
250     len -= remove;
251     }
252     if (len) {
253     if (flags & TFLAG_ECHO) sockbuf_on_write(idx, TELNET_FILTER_LEVEL, data, len);
254     sockbuf_on_read(idx, TELNET_FILTER_LEVEL, data, len);
255     }
256     return(0);
257     }
258    
259     /* We replace \n with \r\n and \255 with \255\255. */
260     static int telnet_filter_write(void *client_data, int idx, const char *data, int len)
261     {
262     const char *newline;
263 stdarg 1.2 int left, linelen, r, r2;
264 stdarg 1.1
265     newline = data;
266     r = 0;
267 stdarg 1.2 left = len;
268     while ((newline = memchr(newline, '\n', left))) {
269 stdarg 1.1 linelen = newline - data;
270     if (linelen > 0 && newline[-1] == '\r') {
271     newline++;
272 stdarg 1.2 left = len - linelen - 1;
273 stdarg 1.1 continue;
274     }
275    
276     r2 = sockbuf_on_write(idx, TELNET_FILTER_LEVEL, data, linelen);
277     if (r2 < 0) return(r2);
278     r += r2;
279     r2 = sockbuf_on_write(idx, TELNET_FILTER_LEVEL, "\r\n", 2);
280     if (r2 < 0) return(r2);
281     r += r2;
282     data = newline+1;
283     newline = data;
284     len -= linelen+1;
285 stdarg 1.2 left = len;
286 stdarg 1.1 }
287     if (len > 0) {
288     r2 = sockbuf_on_write(idx, TELNET_FILTER_LEVEL, data, len);
289     if (r2 < 0) return(r2);
290     r += r2;
291     }
292     return(r);
293     }
294    
295     static int telnet_filter_delete(void *client_data, int idx)
296     {
297     free(client_data);
298     return(0);
299     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23