/[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.2 - (hide annotations) (download) (as text)
Mon Feb 3 01:01:07 2003 UTC (16 years, 11 months ago) by stdarg
Branch: MAIN
Changes since 1.1: +14 -7 lines
File MIME type: text/x-chdr
* Let me know if there are any missing files!

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23