added custom error messages (fixed existing implementation)
[iauth.git] / iauth_cmd.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 <string.h>
9 #include <errno.h>
10
11 #include "iauth.h"
12
13 char iauth_servname[IAUTH_DATALEN + 1];
14
15 static char *iauth_next_data(char **arg) {
16     char *sep, *ret;
17     unsigned int len;
18
19     while(**arg == ' ') ++*arg;
20     if(!**arg) return NULL;
21     if(**arg == ':' || !(sep = strchr(*arg, ' '))) {
22         if(**arg == ':') ++*arg;
23         len = strlen(*arg);
24         ret = iauth_malloc(len + 1);
25         strcpy(ret, *arg);
26         *arg += len;
27         if(len > IAUTH_DATALEN) ret[IAUTH_DATALEN] = 0;
28         else ret[len] = 0;
29         return ret;
30     }
31     else {
32         *sep = 0;
33         len = strlen(*arg);
34         ret = iauth_malloc(len + 1);
35         strcpy(ret, *arg);
36         if(len > IAUTH_DATALEN) ret[IAUTH_DATALEN] = 0;
37         else ret[len] = 0;
38         *sep = ' ';
39         *arg = sep + 1;
40         return ret;
41     }
42 }
43
44 /* Client Introduction: <id> C <remoteip> <remoteport> <localip> <localport> */
45 void iauth_cmd_C(signed int id, char *arg) {
46     char *str;
47     struct iauth_client *cli;
48
49     iauth_delid(id);
50     iauth_addid(id);
51     cli = &iauth_clients[id];
52
53     str = iauth_next_data(&arg);
54     if(!str) goto parse_error;
55     iauth_set(cli->ip, str);
56
57     str = iauth_next_data(&arg);
58     if(!str) goto parse_error;
59     cli->port = atoi(str);
60     iauth_free(str);
61
62     str = iauth_next_data(&arg);
63     if(!str) goto parse_error;
64     iauth_set(cli->lo_ip, str);
65
66     str = iauth_next_data(&arg);
67     if(!str) goto parse_error;
68     cli->lo_port = atoi(str);
69     iauth_free(str);
70
71     iauth_flog(IAUTH_INFO, "New client (%d) from '%s':%hu to '%s':%hu.", id, cli->ip, cli->port, cli->lo_ip, cli->lo_port);
72
73     return;
74     parse_error:
75     iauth_flog(IAUTH_WARNING, "Parse error: Invalid C line.");
76     iauth_delid(id);
77     return;
78 }
79
80 /* Client Disconnect: <id> D */
81 void iauth_cmd_D(struct iauth_client *client) {
82     iauth_delid(client->id);
83 }
84
85 /* Login On Connect: <id> L <account>[:<accountstamp>][ <fakehost>] */
86 void iauth_cmd_L(struct iauth_client *client, char *arg) {
87     char *str;
88     const struct iauth_result *res;
89
90     str = iauth_next_data(&arg);
91     if(!str) goto parse_error;
92     iauth_set(client->account, str);
93
94     str = iauth_next_data(&arg);
95     if(str) iauth_set(client->fakehost, str);
96
97     /* Query database for account query. */
98     res = iauth_query(client);
99     if(!res) {
100         iauth_query_reject(client->id, "Access denied.");
101         iauth_stats_loc_deny();
102     }
103     else {
104      if(strcmp(res->cclass, "error") == 0) {
105             iauth_query_reject(client->id, res->str);
106         iauth_stats_loc_deny();
107          } else {
108         if(*res->ident) iauth_query_set_username(client->id, res->ident);
109         if(*res->host) iauth_query_sethost(client->id, res->host);
110         if(*res->ip) iauth_query_setip(client->id, res->ip);
111         if(*res->modes) iauth_query_setmodes(client->id, res->modes);
112         iauth_query_assign(client->id, (*res->cclass)?res->cclass:NULL);
113         iauth_stats_loc_allow();
114      }
115     }
116
117     iauth_delid(client->id);
118
119     return;
120     parse_error:
121     iauth_flog(IAUTH_WARNING, "Parse error: Invalid L line.");
122     return;
123 }
124
125 /* Hurry Up: <id> H <class> */
126 void iauth_cmd_H(struct iauth_client *client, char *arg) {
127     char *str;
128     const struct iauth_result *res;
129
130     str = iauth_next_data(&arg);
131     if(!str) goto parse_error;
132     iauth_set(client->cclass, str);
133     client->state_h = 1;
134
135     /* Query database for account query. */
136     res = iauth_query(client);
137     if(!res) {
138         iauth_query_reject(client->id, "Access denied.");
139         iauth_stats_def_deny();
140     }
141     else {
142      if(strcmp(res->cclass, "error") == 0) {
143             iauth_query_reject(client->id, res->str);
144         iauth_stats_loc_deny();
145          } else {
146         if(*res->ident) iauth_query_set_username(client->id, res->ident);
147         if(*res->host) iauth_query_sethost(client->id, res->host);
148         if(*res->ip) iauth_query_setip(client->id, res->ip);
149         if(*res->modes) iauth_query_setmodes(client->id, res->modes);
150         iauth_query_assign(client->id, (*res->cclass)?res->cclass:NULL);
151         iauth_stats_def_allow();
152      }
153     }
154     iauth_delid(client->id);
155
156     return;
157     parse_error:
158     iauth_flog(IAUTH_WARNING, "Parse error: Invalid H line.");
159     return;
160 }
161
162 /* Server Name and Capacity: <id> M <servername> <capacity> */
163 void iauth_cmd_M(char *arg) {
164     char *server = NULL, *str = NULL;
165     unsigned int cap;
166
167     server = iauth_next_data(&arg);
168     if(!server) goto parse_error;
169
170     str = iauth_next_data(&arg);
171     if(!str || !*str || (cap = atoi(str)) == 0) goto parse_error;
172     iauth_setcap(cap);
173     iauth_flog(IAUTH_INFO, "Setting server (%s) capacity to: %u.", server, cap);
174     strcpy(iauth_servname, server);
175     iauth_free(str);
176     iauth_free(server);
177
178     return;
179     parse_error:
180     iauth_flog(IAUTH_WARNING, "Parse error: Invalid M line.");
181     iauth_free(server);
182     iauth_free(str);
183     return;
184 }
185
186 /* Hostname Received: <id> N <hostname> */
187 void iauth_cmd_N(struct iauth_client *client, char *arg) {
188     char *str;
189
190     str = iauth_next_data(&arg);
191     if(!str) goto parse_error;
192     iauth_set(client->host, str);
193
194     return;
195     parse_error:
196     iauth_flog(IAUTH_WARNING, "Parse error: Invalid N line.");
197     return;
198 }
199
200 /* Hostname Timeout: <id> d */
201 void iauth_cmd_d(struct iauth_client *client) {
202     char *str;
203
204     str = iauth_malloc(1);
205     iauth_set(client->host, str);
206
207     return;
208 }
209
210 /* Client Password: <id> P :<password ...> */
211 void iauth_cmd_P(struct iauth_client *client, char *arg) {
212     char *str;
213
214     str = iauth_next_data(&arg);
215     if(!str) goto parse_error;
216     iauth_set(client->password, str);
217
218     return;
219     parse_error:
220     iauth_flog(IAUTH_WARNING, "Parse error: Invalid P line.");
221     return;
222 }
223
224 /* Client Username: <id> U <username> <hostname> <servername> :<userinfo ...> */
225 void iauth_cmd_U(struct iauth_client *client, char *arg) {
226     char *str;
227
228     str = iauth_next_data(&arg);
229     if(!str) goto parse_error;
230     iauth_set(client->username, str);
231
232     str = iauth_next_data(&arg);
233     if(!str) goto parse_error;
234     iauth_set(client->c_host, str);
235
236     str = iauth_next_data(&arg);
237     if(!str) goto parse_error;
238     iauth_set(client->c_serv, str);
239
240     str = iauth_next_data(&arg);
241     if(!str) goto parse_error;
242     iauth_set(client->realname, str);
243
244     return;
245     parse_error:
246     iauth_flog(IAUTH_WARNING, "Parse error: Invalid U line.");
247     return;
248 }
249
250 /* Client Username: <id> u <username> */
251 void iauth_cmd_u(struct iauth_client *client, char *arg) {
252     char *str;
253
254     str = iauth_next_data(&arg);
255     if(!str) goto parse_error;
256     iauth_set(client->ident, str);
257
258     return;
259     parse_error:
260     iauth_flog(IAUTH_WARNING, "Parse error: Invalid u line.");
261     return;
262 }
263
264 /* Client Nickname: <id> n <nickname> */
265 void iauth_cmd_n(struct iauth_client *client, char *arg) {
266     char *str;
267
268     str = iauth_next_data(&arg);
269     if(!str) goto parse_error;
270     iauth_set(client->nick, str);
271
272     return;
273     parse_error:
274     iauth_flog(IAUTH_WARNING, "Parse error: Invalid n line.");
275     return;
276 }
277
278 /* Client Registered: <id> T */
279 void iauth_cmd_T(struct iauth_client *client) {
280     iauth_flog(IAUTH_INFO, "Client %d was registered without IAuth answer.", client->id);
281     iauth_delid(client->id);
282 }
283
284 /* Error: <id> E <type> :<additional text> */
285 void iauth_cmd_E(signed int id, char *arg) {
286     iauth_flog(IAUTH_WARNING, "Received IRCd error: %s", arg);
287 }
288