blob: e681f820ec94d2363c8141f79e2921ff1fd1d2d9 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// master/network.c - UDP-Handling
4//
5// $Id: network.c 8934 2014-09-10 21:57:12Z Zesstra $
6
7#pragma strict_types
8
9#include "/secure/master.h"
10#define BBMASTER "/secure/bbmaster"
11
12/*
13#undef DEBUG
14#define DEBUG(x) if (call_sefun("find_player","zesstra")) \
15 tell_object(call_sefun("find_player","zesstra"),x);
16*/
17
18//ich will hieraus momentan kein Debug, ist zuviel. Zesstra
19
20#ifdef DEBUG
21#undef DEBUG
22#endif
23#define DEBUG(x)
24
25nosave int mails_last_hour;
26
27static string mail_normalize( string str )
28{
29 str = regreplace( str, "[^<]*<(.*)>[^>]*", "\\1", 0);
30 return regreplace( str, " *([^ ][^ ]*).*", "\\1", 0);
31}
32
33
34static string *mk_rec_list( string str )
35{
36 return map( explode( lower_case(str), "," ) - ({""}),
37 "mail_normalize", this_object() );
38}
39
40
41static int CheckPasswd( string name, string passwd ) {
42 mixed *uinf;
43
44 if (!stringp(passwd) || !sizeof(passwd))
45 return 0;
46 if ( sizeof(uinf = get_full_userinfo(name)) < 2 )
47 return 0;
48
49 string pwhash = uinf[USER_PASSWORD+1];
50 if (sizeof(pwhash) > 13) {
51 // MD5-Hash
52 passwd = md5_crypt(passwd, pwhash);
53 }
54 else if (sizeof(pwhash) > 2) {
55 // Crypt-Hash
56 passwd = crypt(passwd, pwhash[0..1]);
57 }
58 else return 0;
59
60 return (passwd == pwhash);
61}
62
63
64static void FtpAccess( string host, string message, int port )
65{
66 string *comp, reply, head;
67#if __EFUN_DEFINED__(send_udp)
68 comp = efun::explode( message, "\t" );
69#define FTP_ID 0
70#define FTP_SEQ 1
71#define FTP_TAG 2
72#define FTP_CMD 3
73#define FTP_ARG1 4
74#define FTP_ARG2 5
75#define FTP_ARG3 6
76
77 if ( sizeof(comp) <= FTP_CMD || lower_case(comp[FTP_TAG]) != "req" ){
78 log_file( "IMP_MSGS", "Host: " + host + ":" + port + " - '" +
79 message + "'\n" );
80 return;
81 }
82
83 reply = "INVALID";
84
85 head = sprintf( "%s\t%s\tRPLY\t%s\t",
86 comp[FTP_ID], comp[FTP_SEQ], comp[FTP_CMD] );
87
88 switch ( lower_case(comp[FTP_CMD]) ){
89 case "user":
90 if ( sizeof(comp) <= FTP_ARG1 )
91 break;
92
93 if ( IS_LEARNER(lower_case(comp[FTP_ARG1])) )
94 reply = "/players/" + lower_case(comp[FTP_ARG1]);
95 else
96 reply = "NONE";
97 break;
98
99 case "pass":
100 if ( sizeof(comp) <= FTP_ARG2 )
101 break;
102
103 comp[FTP_ARG1] = lower_case(comp[FTP_ARG1]);
104
105 if ( IS_LEARNER(comp[FTP_ARG1]) &&
106 !"/secure/master"->QueryTBanished(comp[FTP_ARG1]) ){
107 if ( CheckPasswd( comp[FTP_ARG1], comp[FTP_ARG2] ) )
108 reply = "OK";
109 else {
110 if ( get_wiz_level( comp[FTP_ARG1] ) < ARCH_LVL )
111 log_file( "LOGINFAIL",
112 sprintf( "PASSWORD: (FTP) %s %s\n",
113 comp[FTP_ARG1],
114 ctime(time()) ) );
115 else
116 log_file( "ARCH/LOGINFAIL",
117 sprintf( "PASSWORD: (FTP) %s %s\n",
118 comp[FTP_ARG1],
119 ctime(time()) ) );
120 }
121 }
122 else
123 reply = "FAIL";
124 break;
125
126 case "read":
127DEBUG("-FtpAccess----\nHost:"+host+"Message:\n"+message+"\n--------------\n");
128 if ( sizeof(comp) <= FTP_ARG2 )
129 break;
130
131 if ( comp[FTP_ARG2][0] == '/' &&
132 valid_read( comp[FTP_ARG2], lower_case(comp[FTP_ARG1]),
133 "read_file", 0 ) ){
134
135 BBMASTER->ftpbb( lower_case(comp[FTP_ARG1]),
136 "read " + comp[FTP_ARG2] + "\n" );
137 reply = "OK";
138 }
139 else
140 reply = "FAIL";
141 break;
142
143 case "writ":
144DEBUG("-FtpAccess----\nHost:"+host+"Message:\n"+message+"\n--------------\n");
145 if ( sizeof(comp) <= FTP_ARG2 )
146 break;
147
148 if ( comp[FTP_ARG2][0] == '/' &&
149 valid_write( comp[FTP_ARG2], lower_case(comp[FTP_ARG1]),
150 "write_file", 0 ) ){
151
152 BBMASTER->ftpbb( lower_case(comp[FTP_ARG1]),
153 "write " + comp[FTP_ARG2] + "\n" );
154 reply = "OK";
155 }
156 else
157 reply = "FAIL";
158 break;
159
160 case "list":
161DEBUG("-FtpAccess----\nHost:"+host+"Message:\n"+message+"\n--------------\n");
162 if ( sizeof(comp) <= FTP_ARG2 )
163 break;
164
165 if ( comp[FTP_ARG2][0] == '/' &&
166 valid_read( comp[FTP_ARG2], lower_case(comp[FTP_ARG1]),
167 "read_file", 0 ) )
168 reply = "OK";
169 else
170 reply = "FAIL";
171 break;
172
173 default:
174DEBUG("-FtpAccess----\nHost:"+host+"Message:\n"+message+"\n--------------\n");
175 log_file( "IMP_MSGS", "Host: " + host + ":" + port + " - '" +
176 message + "'\n" );
177 break;
178 }
179
180 send_udp( host, port, head+reply );
181#endif
182}
183
184
185static int doReadMail( string file )
186{
187 string str, *lines, *parts, *tmp;
188 mixed *message;
189 int i, j;
190
191 if ( (i = file_size(file)) > 50000 || i < 5 ){
192 rm(file);
193 DEBUG( "Mail size invalid\n" );
194 return -1;
195 }
196
197 if ( !(str = read_bytes( file, 0, 50000 )) )
198 return -1;
199
200 if ( !(j = sizeof(lines = explode( str, "\n" ))) )
201 return -2;
202
203 i = 0;
204
205 while ( i < j && lines[i] != "" )
206 i++;
207
208 if ( i == j )
209 return -2;
210
211 DEBUG( sprintf( "Have %d headerlines:\n", i ) );
212
213 message= allocate(9);
214 message[MSG_CC] = ({});
215 message[MSG_BCC] = ({});
216 message[MSG_BODY] = implode( lines[i..], "\n" );
217
218 for ( j = 0; j < i; j++ ){
219 parts = explode( lines[j], ":" );
220
221 if ( sizeof(parts) > 1 ){
222 str = lower_case(parts[0]);
223 parts[0] = implode( parts[1..], ":" );
224
225 switch (str){
226 case "subject":
227 message[MSG_SUBJECT] = parts[0];
228 break;
229
230 case "from":
231 DEBUG( "Found from\n" );
232 DEBUG( sprintf( "PARTS[0]=%s\n", parts[0] ) );
233 message[MSG_FROM] = mail_normalize(parts[0]);
234 message[MSG_SENDER] = parts[0];
235 DEBUG( sprintf( "FROM: %s\nSENDER: %s\n",
236 message[MSG_FROM],
237 message[MSG_SENDER] ) );
238 break;
239
240 case "cc":
241 DEBUG( sprintf("FOUND CC: %O\n", parts[0]) );
242 message[MSG_CC] += mk_rec_list(parts[0]);
243 break;
244
245 case "bcc":
246 DEBUG( sprintf("FOUND BCC: %O\n", parts[0]) );
247 message[MSG_BCC] += mk_rec_list(parts[0]);
248 break;
249
250 case "to":
251 DEBUG( sprintf("FOUND TO: %O\n", parts[0]) );
252 tmp = mk_rec_list(parts[0]);
253
254 if ( !message[MSG_RECIPIENT] )
255 message[MSG_RECIPIENT] = tmp[0];
256
257 message[MSG_CC] += tmp;
258 break;
259
260 // Das MUD-TO: wird vom Perlskript als erste Headerzeile eingefuegt
261 case "mud-to":
262 DEBUG( sprintf("FOUND MUD-TO: %O\n", parts[0]) );
263 message[MSG_RECIPIENT] = mail_normalize(lower_case(parts[0]));
264 break;
265 }
266 }
267 }
268
269 // Eigentlichen Empfaenger aus CC: loeschen
270 message[MSG_CC] -= ({ message[MSG_RECIPIENT],
271 message[MSG_RECIPIENT]+"@mg.mud.de",
272 message[MSG_RECIPIENT]+"@morgengrauen.mud.de" });
273
274
275 DEBUG( sprintf( "TO: %O\n", message[MSG_RECIPIENT] ) );
276 DEBUG( sprintf( "CC: %O\n", message[MSG_CC] ) );
277 DEBUG( sprintf( "BCC: %O\n", message[MSG_BCC] ) );
278
279 if ( !stringp(message[MSG_FROM]) )
280 return -2;
281
282 if ( !stringp(message[MSG_RECIPIENT]) ){
283 str = explode( file, "/" )[<1];
284 i = 0;
285 j = sizeof(str);
286
287 while ( i < j && str[i] <= '9' && str[i] >= '0' )
288 i++;
289
290 if ( i >= j )
291 return -2;
292
293 message[MSG_RECIPIENT] = str[i..];
294 DEBUG( sprintf( "EMERGENCY RECIPIENT=%s\n", str[i..] ) );
295 }
296
297 rm(file);
298
299 // Da vom Master besser nichts von ausserhalb /secure #include't wird,
300 // direkt die '5'. Normalerweise hiesse der Aufruf:
301 // DeliverMail( message, NO_USER_ALIASES|NO_CARBON_COPIES );
302 "/secure/mailer"->DeliverMail( message, 5 );
303 return 1;
304}
305
306
307public void mailread()
308{
309 string *files;
310 int i;
311
312 DEBUG( "mailread called\n" );
313
314 if ( mails_last_hour >= MAX_MAILS_PER_HOUR )
315 return;
316
317 files = (get_dir( "/mail/inbound/*" )||({})) - ({ "..", "." });
318 i = sizeof(files);
319
320 while ( i-- && mails_last_hour < MAX_MAILS_PER_HOUR ){
321 DEBUG( "FOUND FILE \"" + files[i] + "\" ...\n" );
322 mails_last_hour++;
323
324 if ( doReadMail( "/mail/inbound/" + files[i]) < -1 ){
325 mixed message;
326
327 message = allocate(9);
328 mails_last_hour++;
329 rename( "/mail/inbound/" + files[i],
330 "/secure/ARCH/MAIL/" + files[i] );
331 message[MSG_SENDER] = geteuid();
332 message[MSG_FROM] = getuid();
333 message[MSG_SUBJECT] = "Fehlerhafte Mail: /secure/ARCH/MAIL/" +
334 files[i];
335 message[MSG_RECIPIENT] = "mud@mg.mud.de";
336 message[MSG_BODY] = "Bitte Ueberpruefen!\n";
337 // NO_SYSTEM_ALIASES|NO_USER_ALIASES == 3
338 "/secure/mailer"->DeliverMail( message, 3 );
339 }
340 }
341}
342
343
344static void udp_query( string query, string host, int port )
345{
346#if __EFUN_DEFINED__(send_udp)
347 string *mess;
348 mixed *data;
349 int i, j;
350
351 mess = explode( query, " " );
352
353 switch ( mess[1] ){
354 case "wholist":
355 case "who":
356 data = (string *)"/obj/werliste"->QueryWhoListe();
357 break;
358
359 case "uptime":
360 data = ({ call_sefun("uptime") });
361 break;
362
363 case "finger":
364 if ( sizeof(mess) < 3 )
365 data = ({ "Error: Wen soll ich fingern ?" });
366 else
367 data = explode( (string)"p/daemon/finger"->
368 finger_single( lower_case(mess[2]), 0 ), "\n" );
369 break;
370
371 case "mailread":
372 data = ({ "Okay" });
373 mailread();
374 break;
375
376 default:
377 data = ({ "Error: unknown request " + mess[1] + "\n" });
378 }
379
380
381 send_udp( host, port, sprintf( "%s 0 %d", mess[0], sizeof(data) ) );
382
383 for ( i = 0, j = sizeof(data); i < j; i++ )
384 send_udp( host, port, sprintf( "%s %d %s", mess[0], i+1, data[i] ) );
385#endif
386}
387
388#define UDP_DEBUG(x)
389//#define UDP_DEBUG(x) (write_file("/log/ARCH/udp.log",(x)))
390
391void receive_udp(string host, string message, int port)
392{
393 mixed *tmp;
394 UDP_DEBUG(sprintf("%s %s:%d: %s\n",strftime(),host,port,message));
395
396 if (message[0..6]=="EXTREQ:"
397 || message[0..5]=="IPNAME"
398 || message[0..3]=="AUTH"
399 ) {
400 return;
401 }
402
403 if( message[0..8]=="IPLOOKUP\n" ) {
404 "/p/daemon/iplookup"->update( message );
405 return;
406 }
407
408 if( message[0..9]=="DNSLOOKUP\n" ) {
409 "/p/daemon/dnslookup"->update( message );
410 return;
411 }
412
413 if (message[0..4]=="NFTPD") {
414#if __HOST_NAME__==MUDHOST
415 if (host!=FTPD_IP) {
416 DEBUG(sprintf("INVALID HOST: %s\n",host));
417 return;
418 }
419#endif
420 FtpAccess(host,message,port);
421 return;
422 }
423
424 if (message[0..9]=="udp_query:") {
425 return udp_query(message[10..],host,port);
426 }
427
428 "secure/inetd"->_receive_udp(host, message);
429}
430
431