added custom error messages (fixed existing implementation)
[iauth.git] / iauth.c
1 /*
2  * Written by David Herrmann.
3  * Dedicated to the Public Domain.
4  */
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <signal.h>
12
13 #include "iauth.h"
14
15 static unsigned int running = 1;
16
17 static void iauth_signal(int sig) {
18     iauth_flog(IAUTH_INFO, "Caught signal %d, ignoring...", sig);
19 }
20
21 /* Parses one single input line. */
22 void iauth_parse(char *line) {
23     unsigned int i, found;
24     signed int id;
25
26     /* The line has to look like:
27      * <id> X <several> <arguments>
28      */
29
30     found = 0;
31     for(i = 0; line[i]; ++i) {
32         if(line[i] == ' ') {
33             found = 1;
34             break;
35         }
36     }
37
38     /* Ignore invalid lines. */
39     if(!found) {
40         iauth_flog(IAUTH_WARNING, "Received invalid line; no subcommand specified.");
41         return;
42     }
43
44     /* Get the id. */
45     id = atoi(line);
46
47     /* Ignore invalid subcommands. */
48     if(!line[++i] || line[i] == ' ' || (line[i + 1] != ' ' && line[i + 1])) {
49         iauth_flog(IAUTH_WARNING, "Received invalid line; invalid subcommand.");
50         return;
51     }
52
53     /* Call the subcommand handler. */
54     switch(line[i]) {
55         case 'C':
56             /* Client Introduction: <id> C <remoteip> <remoteport> <localip> <localport> */
57             if(id >= 0 && id < iauth_clients_size && line[++i]) iauth_cmd_C(id, &line[++i]);
58             else iauth_flog(IAUTH_WARNING, "Received invalid C line.");
59             break;
60         case 'D':
61             /* Client Disconnect: <id> D */
62             if(id >= 0 && id < iauth_clients_size) {
63                 if(iauth_clients[id].id == id) iauth_cmd_D(&iauth_clients[id]);
64                 else /* Ignore all other disconnects. */ ;
65             }
66             else iauth_flog(IAUTH_WARNING, "Received invalid D line.");
67             break;
68         case 'L':
69             /* Login On Connect: <id> L <account>[:<accountstamp>][ <fakehost>] */
70             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_L(&iauth_clients[id], &line[++i]);
71             else iauth_flog(IAUTH_WARNING, "Received invalid L line.");
72             break;
73         case 'H':
74             /* Hurry Up: <id> H <class> */
75             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_H(&iauth_clients[id], &line[++i]);
76             else iauth_flog(IAUTH_WARNING, "Received invalid H line.");
77             break;
78         case 'M':
79             /* Server Name and Capacity: <id> M <servername> <capacity> */
80             if(id == -1 && line[++i]) iauth_cmd_M(&line[++i]);
81             else iauth_flog(IAUTH_WARNING, "Received invalid M line.");
82             break;
83         case 'N':
84             /* Hostname Received: <id> N <hostname> */
85             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_N(&iauth_clients[id], &line[++i]);
86             else iauth_flog(IAUTH_WARNING, "Received invalid N line.");
87             break;
88         case 'd':
89             /* Hostname Timeout: <id> d */
90             if(id >= 0 && id < iauth_clients_size && iauth_clients[id].id == id) iauth_cmd_d(&iauth_clients[id]);
91             else iauth_flog(IAUTH_WARNING, "Received invalid d line.");
92             break;
93         case 'P':
94             /* Client Password: <id> P :<password ...> */
95             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_P(&iauth_clients[id], &line[++i]);
96             else iauth_flog(IAUTH_WARNING, "Received invalid P line.");
97             break;
98         case 'U':
99             /* Client Username: <id> U <username> <hostname> <servername> :<userinfo ...> */
100             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_U(&iauth_clients[id], &line[++i]);
101             else iauth_flog(IAUTH_WARNING, "Received invalid U line.");
102             break;
103         case 'u':
104             /* Client Username: <id> u <username> */
105             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_u(&iauth_clients[id], &line[++i]);
106             else iauth_flog(IAUTH_WARNING, "Received invalid u line.");
107             break;
108         case 'n':
109             /* Client Nickname: <id> n <nickname> */
110             if(id >= 0 && id < iauth_clients_size && line[++i] && iauth_clients[id].id == id) iauth_cmd_n(&iauth_clients[id], &line[++i]);
111             else iauth_flog(IAUTH_WARNING, "Received invalid n line.");
112             break;
113         case 'T':
114             /* Client Registered: <id> T */
115             if(id >= 0 && id < iauth_clients_size && iauth_clients[id].id == id) iauth_cmd_T(&iauth_clients[id]);
116             else iauth_flog(IAUTH_WARNING, "Received invalid T line.");
117             break;
118         case 'E':
119             /* Error: <id> E <type> :<additional text> */
120             if(line[++i]) iauth_cmd_E(id, &line[++i]);
121             else iauth_flog(IAUTH_WARNING, "Received invalid E line.");
122             break;
123         default:
124             /* Invalid subcommand; ignore. */
125             iauth_flog(IAUTH_WARNING, "Received invalid subcommand.");
126             return;
127     }
128
129     /* Subcommand called, nothing to do; return and await next line. */
130     return;
131 }
132
133 signed int main(signed int argc, char *argv[]) {
134     char *line;
135
136     signal(SIGPIPE, SIG_IGN);
137     signal(SIGHUP, SIG_IGN);
138     signal(SIGINT, iauth_signal);
139     signal(SIGQUIT, iauth_signal);
140     signal(SIGTERM, iauth_signal);
141
142     if(argc > 1) iauth_logfile = argv[1];
143     if(argc > 2) iauth_scriptfile = argv[2];
144     if(argc > 3) iauth_debug = 1;
145
146     iauth_flog(IAUTH_INFO, "Starting IAuth");
147
148     iauth_query_version("WGN iauth"); //original from OGN
149     iauth_query_policy("ARTU");
150     iauth_stats_report();
151
152     while(running && (line = iauth_read())) {
153         iauth_parse(line);
154     }
155
156     iauth_flog(IAUTH_INFO, "Stopping IAuth");
157
158     return EXIT_SUCCESS;
159 }