]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-oper.c
CONNECT, DISCONNECT: generate WALLOPS messages
[ngircd-alex.git] / src / ngircd / irc-oper.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  *
11  * IRC operator commands
12  */
13
14
15 #include "portab.h"
16
17 #include "imp.h"
18 #include <assert.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "ngircd.h"
24 #include "resolve.h"
25 #include "conn-func.h"
26 #include "conf.h"
27 #include "client.h"
28 #include "channel.h"
29 #include "irc-write.h"
30 #include "log.h"
31 #include "match.h"
32 #include "messages.h"
33 #include "parse.h"
34
35 #include <exp.h>
36 #include "irc-oper.h"
37
38
39 /**
40  * Handle invalid received OPER command.
41  * Log OPER attempt and send error message to client.
42  */
43 static bool
44 Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
45 {
46         Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s",
47             Client_Mask(Client), errtoken, errmsg);
48         IRC_SetPenalty(Client, 3);
49         return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
50                                   Client_ID(Client));
51 } /* Bad_OperPass */
52
53
54 /**
55  * Check that the client is an IRC operator allowed to administer this server.
56  */
57 static bool
58 Check_Oper(CLIENT * Client)
59 {
60         if (!Client_HasMode(Client, 'o'))
61                 return false;
62         if (!Client_OperByMe(Client) && !Conf_AllowRemoteOper)
63                 return false;
64         /* The client is an local IRC operator, or this server is configured
65          * to trust remote operators. */
66         return true;
67 } /* CheckOper */
68
69
70 /**
71  * Return and log a "no privileges" message.
72  */
73 static bool
74 No_Privileges(CLIENT * Client, REQUEST * Req)
75 {
76         Log(LOG_NOTICE, "No privileges: client \"%s\", command \"%s\"",
77             Client_Mask(Client), Req->command);
78         return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
79                                   Client_ID(Client));
80 } /* PermissionDenied */
81
82
83 GLOBAL bool
84 IRC_OPER( CLIENT *Client, REQUEST *Req )
85 {
86         unsigned int i;
87
88         assert( Client != NULL );
89         assert( Req != NULL );
90
91         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
92
93         for( i = 0; i < Conf_Oper_Count; i++)
94         {
95                 if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
96         }
97         if( i >= Conf_Oper_Count )
98                 return Bad_OperPass(Client, Req->argv[0], "not configured");
99
100         if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
101                 return Bad_OperPass(Client, Conf_Oper[i].name, "bad password");
102
103         if( Conf_Oper[i].mask && (! Match( Conf_Oper[i].mask, Client_Mask( Client ) )))
104                 return Bad_OperPass(Client, Conf_Oper[i].mask, "hostmask check failed" );
105
106         if( ! Client_HasMode( Client, 'o' ))
107         {
108                 Client_ModeAdd( Client, 'o' );
109                 if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
110                 IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
111         }
112
113         if( ! Client_OperByMe( Client )) Log( LOG_NOTICE|LOG_snotice, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
114
115         Client_SetOperByMe( Client, true);
116         return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
117 } /* IRC_OPER */
118
119
120 GLOBAL bool
121 IRC_DIE(CLIENT * Client, REQUEST * Req)
122 {
123         /* Shut down server */
124
125         CONN_ID c;
126         CLIENT *cl;
127
128         assert(Client != NULL);
129         assert(Req != NULL);
130
131         if (!Check_Oper(Client))
132                 return No_Privileges(Client, Req);
133
134         /* Bad number of parameters? */
135 #ifdef STRICT_RFC
136         if (Req->argc != 0)
137 #else
138         if (Req->argc > 1)
139 #endif
140                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
141                                           Client_ID(Client), Req->command);
142
143         /* Is a message given? */
144         if (Req->argc > 0) {
145                 c = Conn_First();
146                 while (c != NONE) {
147                         cl = Conn_GetClient(c);
148                         if (Client_Type(cl) == CLIENT_USER)
149                                 IRC_WriteStrClient(cl, "NOTICE %s :%s",
150                                                 Client_ID(cl), Req->argv[0]);
151                         c = Conn_Next(c);
152                 }
153         }
154
155         Log(LOG_NOTICE | LOG_snotice, "Got DIE command from \"%s\" ...",
156             Client_Mask(Client));
157         NGIRCd_SignalQuit = true;
158
159         return CONNECTED;
160 } /* IRC_DIE */
161
162
163 GLOBAL bool
164 IRC_REHASH( CLIENT *Client, REQUEST *Req )
165 {
166         /* Reload configuration file */
167
168         assert( Client != NULL );
169         assert( Req != NULL );
170
171         if (!Check_Oper(Client))
172                 return No_Privileges(Client, Req);
173
174         /* Bad number of parameters? */
175         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
176
177         Log( LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Client_Mask( Client ));
178         NGIRCd_SignalRehash = true;
179         
180         return CONNECTED;
181 } /* IRC_REHASH */
182
183
184 GLOBAL bool
185 IRC_RESTART( CLIENT *Client, REQUEST *Req )
186 {
187         /* Restart IRC server (fork a new process) */
188
189         assert( Client != NULL );
190         assert( Req != NULL );
191
192         if (!Check_Oper(Client))
193                 return No_Privileges(Client, Req);
194
195         /* Bad number of parameters? */
196         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
197
198         Log( LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...", Client_Mask( Client ));
199         NGIRCd_SignalRestart = true;
200         return CONNECTED;
201 } /* IRC_RESTART */
202
203
204 /**
205  * Connect configured or new server.
206  */
207 GLOBAL bool
208 IRC_CONNECT(CLIENT * Client, REQUEST * Req)
209 {
210         char msg[LINE_LEN + 64];
211
212         assert(Client != NULL);
213         assert(Req != NULL);
214
215         if (!Check_Oper(Client))
216                 return No_Privileges(Client, Req);
217
218         /* Bad number of parameters? */
219         if ((Req->argc != 1) && (Req->argc != 2) && (Req->argc != 5))
220                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
221                                           Client_ID(Client), Req->command);
222
223         /* Invalid port number? */
224         if ((Req->argc > 1) && atoi(Req->argv[1]) < 1)
225                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
226                                           Client_ID(Client), Req->command);
227
228         snprintf(msg, sizeof(msg), "Received CONNECT %s from %s",
229                  Req->argv[0], Client_ID(Client));
230         IRC_SendWallops(Client_ThisServer(), Client_ThisServer(), msg);
231
232         Log(LOG_NOTICE | LOG_snotice,
233             "Got CONNECT command from \"%s\" for \"%s\".", Client_Mask(Client),
234             Req->argv[0]);
235
236         switch (Req->argc) {
237         case 1:
238                 if (!Conf_EnablePassiveServer(Req->argv[0]))
239                         return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
240                                                   Client_ID(Client),
241                                                   Req->argv[0]);
242         break;
243         case 2:
244                 /* Connect configured server */
245                 if (!Conf_EnableServer
246                     (Req->argv[0], (UINT16) atoi(Req->argv[1])))
247                         return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
248                                                   Client_ID(Client),
249                                                   Req->argv[0]);
250         break;
251         default:
252                 /* Add server */
253                 if (!Conf_AddServer
254                     (Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2],
255                      Req->argv[3], Req->argv[4]))
256                         return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
257                                                   Client_ID(Client),
258                                                   Req->argv[0]);
259         }
260
261         return CONNECTED;
262 } /* IRC_CONNECT */
263
264
265 /**
266  * Disconnect (and disable) configured server.
267  */
268 GLOBAL bool
269 IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
270 {
271         CONN_ID my_conn;
272         char msg[LINE_LEN + 64];
273
274         assert(Client != NULL);
275         assert(Req != NULL);
276
277         if (!Check_Oper(Client))
278                 return No_Privileges(Client, Req);
279
280         /* Bad number of parameters? */
281         if (Req->argc != 1)
282                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
283                                           Client_ID(Client), Req->command);
284
285         snprintf(msg, sizeof(msg), "Received DISCONNECT %s from %s",
286                  Req->argv[0], Client_ID(Client));
287         IRC_SendWallops(Client_ThisServer(), Client_ThisServer(), msg);
288
289         Log(LOG_NOTICE | LOG_snotice,
290             "Got DISCONNECT command from \"%s\" for \"%s\".",
291             Client_Mask(Client), Req->argv[0]);
292
293         /* Save ID of this connection */
294         my_conn = Client_Conn(Client);
295
296         /* Disconnect configured server */
297         if (!Conf_DisableServer(Req->argv[0]))
298                 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
299                                           Client_ID(Client), Req->argv[0]);
300
301         /* Are we still connected or were we killed, too? */
302         if (Conn_GetClient(my_conn))
303                 return CONNECTED;
304         else
305                 return DISCONNECTED;
306 } /* IRC_DISCONNECT */
307
308
309 GLOBAL bool
310 IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
311 {
312         CLIENT *from;
313
314         assert( Client != NULL );
315         assert( Req != NULL );
316
317         if (Req->argc != 1)
318                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
319
320         switch (Client_Type(Client)) {
321         case CLIENT_USER:
322                 if (!Client_OperByMe(Client))
323                         return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client));
324                 from = Client;
325                 break;
326         case CLIENT_SERVER:
327                 from = Client_Search(Req->prefix);
328                 break;
329         default:
330                 return CONNECTED;
331         }
332
333         if (!from)
334                 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
335
336         IRC_SendWallops(Client, from, Req->argv[0]);
337         return CONNECTED;
338 } /* IRC_WALLOPS */
339
340
341 /* -eof- */