2 ===================================================================
3 RCS file: /home/coder-com/cvs/ircu2.10/ChangeLog,v
4 retrieving revision 1.340
5 diff -u -r1.340 ChangeLog
6 --- ChangeLog 2002/04/12 00:19:52 1.340
7 +++ ChangeLog 2002/04/12 13:17:10
9 2002-04-12 Alex Badea <vampire@p16.pub.ro>
11 + * include/ircd_features.h: new feature LOGIN_ON_CONNECT
13 + * ircd/ircd_features.c: new feature LOGIN_ON_CONNECT
15 + * include/client.h (struct Client): new fields for storing
16 + bot name, username and password for login-on-connect
18 + * ircd/m_account.c: extensions for login-on-connect: route
19 + and process auth-request and auth-reply messages
21 + * ircd/m_pass.c: store bot name, username and password for
24 + * ircd/m_user.c: store username/hostname for the client
25 + even if he finished registration, as register_user may not
28 + * ircd/s_user.c (register_user): if the client specified
29 + a service login in the PASS command, attempt to log him in;
30 + also, don't set his hostname if it was set remotely by a
33 + * doc/example.conf: default value for FEAT_LOGIN_ON_CONNECT
35 + * doc/readme.features: documented FEAT_LOGIN_ON_CONNECT
37 +2002-04-12 Alex Badea <vampire@p16.pub.ro>
39 * ircd/m_invite.c: don't propagate invites for local channels
41 * include/patchlevel.h (PATCHLEVEL): bump patchlevel
42 Index: doc/example.conf
43 ===================================================================
44 RCS file: /home/coder-com/cvs/ircu2.10/doc/example.conf,v
45 retrieving revision 1.20
46 diff -u -r1.20 example.conf
47 --- doc/example.conf 2002/04/03 15:23:47 1.20
48 +++ doc/example.conf 2002/04/12 13:17:10
50 # "HOST_HIDING"="FALSE";
51 # "HIDDEN_HOST"="users.undernet.org";
52 # "HIDDEN_IP"="127.0.0.1";
53 +# "LOGIN_ON_CONNECT"="FALSE";
54 # "KILLCHASETIMELIMIT"="30";
55 # "MAXCHANNELSPERUSER"="10";
57 Index: doc/readme.features
58 ===================================================================
59 RCS file: /home/coder-com/cvs/ircu2.10/doc/readme.features,v
60 retrieving revision 1.5
61 diff -u -r1.5 readme.features
62 --- doc/readme.features 2002/04/03 15:23:47 1.5
63 +++ doc/readme.features 2002/04/12 13:17:10
65 This selects a fake IP to be shown on /USERIP and /WHO %i when the
66 target has a hidden host (see HOST_HIDING).
72 +This selects whether local clients can use specify a service bot login
73 +in the connection phase. Read readme.login-on-connect for more details.
78 Index: include/client.h
79 ===================================================================
80 RCS file: /home/coder-com/cvs/ircu2.10/include/client.h,v
81 retrieving revision 1.26
82 diff -u -r1.26 client.h
83 --- include/client.h 2002/04/05 11:36:58 1.26
84 +++ include/client.h 2002/04/12 13:17:10
86 char cli_name[HOSTLEN + 1]; /* Unique name of the client, nick or host */
87 char cli_username[USERLEN + 1]; /* username here now for auth stuff */
88 char cli_info[REALLEN + 1]; /* Free form additional client information */
90 + char *cli_cs_user; /* channel service authentication (user)... */
91 + char *cli_cs_pass; /* ...and password... */
92 + char *cli_cs_service; /* ...and the service bot's nick */
95 #define CLIENT_MAGIC 0x4ca08286
96 Index: include/ircd_features.h
97 ===================================================================
98 RCS file: /home/coder-com/cvs/ircu2.10/include/ircd_features.h,v
99 retrieving revision 1.15
100 diff -u -r1.15 ircd_features.h
101 --- include/ircd_features.h 2002/04/03 15:23:47 1.15
102 +++ include/ircd_features.h 2002/04/12 13:17:10
107 + FEAT_LOGIN_ON_CONNECT,
109 /* features that probably should not be touched */
110 FEAT_KILLCHASETIMELIMIT,
111 Index: ircd/ircd_features.c
112 ===================================================================
113 RCS file: /home/coder-com/cvs/ircu2.10/ircd/ircd_features.c,v
114 retrieving revision 1.19
115 diff -u -r1.19 ircd_features.c
116 --- ircd/ircd_features.c 2002/04/03 15:23:48 1.19
117 +++ ircd/ircd_features.c 2002/04/12 13:17:10
119 F_B(HOST_HIDING, 0, 0, 0),
120 F_S(HIDDEN_HOST, FEAT_CASE, "users.undernet.org", 0),
121 F_S(HIDDEN_IP, 0, "127.0.0.1", 0),
122 + F_B(LOGIN_ON_CONNECT, 0, 0, 0),
124 /* features that probably should not be touched */
125 F_I(KILLCHASETIMELIMIT, 0, 30, 0),
126 Index: ircd/m_account.c
127 ===================================================================
128 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_account.c,v
129 retrieving revision 1.2
130 diff -u -r1.2 m_account.c
131 --- ircd/m_account.c 2002/02/14 00:20:42 1.2
132 +++ ircd/m_account.c 2002/04/12 13:17:10
135 #include "ircd_reply.h"
136 #include "ircd_string.h"
137 +#include "ircd_alloc.h"
139 #include "numnicks.h"
141 +#include "s_debug.h"
147 * parv[0] = sender prefix
148 * parv[1] = numeric of client to act on
149 - * parv[2] = account name (12 characters or less)
150 + * parv[2] = message type
152 + * for *parv[2] == 'R' (remote auth):
153 + * parv[3] = account name (12 characters or less)
155 + * for *parv[2] == 'C' (auth check):
156 + * parv[3] = numeric of client to check
157 + * parv[4] = username
158 + * parv[parc-1] = password
160 + * for *parv[2] == 'A' (auth ok) or
161 + * for *parv[2] == 'D' (auth denied) or
162 + * parv[3] = numeric of client to check
164 int ms_account(struct Client* cptr, struct Client* sptr, int parc,
167 struct Client *acptr;
171 return need_more_params(sptr, "ACCOUNT");
174 + /* old-style message, remap it */
181 return protocol_violation(cptr, "ACCOUNT from non-server %s",
184 - if (!(acptr = findNUser(parv[1])))
185 - return 0; /* Ignore ACCOUNT for a user that QUIT; probably crossed */
187 - if (IsAccount(acptr))
188 - return protocol_violation(cptr, "ACCOUNT for already registered user %s "
189 - "(%s -> %s)", cli_name(acptr),
190 - cli_user(acptr)->account, parv[2]);
192 - assert(0 == cli_user(acptr)->account[0]);
194 - ircd_strncpy(cli_user(acptr)->account, parv[2], ACCOUNTLEN);
195 - hide_hostmask(acptr, FLAGS_ACCOUNT);
197 - sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C %s", acptr,
198 - cli_user(acptr)->account);
201 + if (!(acptr = findNUser(parv[1])))
202 + return 0; /* Ignore ACCOUNT for a user that QUIT; probably crossed */
204 + if (IsAccount(acptr))
205 + return protocol_violation(cptr, "ACCOUNT for already registered user %s "
206 + "(%s -> %s)", cli_name(acptr),
207 + cli_user(acptr)->account, parv[3]);
209 + assert(0 == cli_user(acptr)->account[0]);
211 + ircd_strncpy(cli_user(acptr)->account, parv[3], ACCOUNTLEN);
212 + hide_hostmask(acptr, FLAGS_ACCOUNT);
215 + /* XXX Enable this when all servers speak the same language */
216 + sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C R %s", acptr,
217 + cli_user(acptr)->account);
219 + sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, "%C %s", acptr,
220 + cli_user(acptr)->account);
223 + if (!(acptr = findNUser(parv[1])) && !(acptr = FindNServer(parv[1])))
226 + if (type == 'C' && parc < 6)
227 + return need_more_params(sptr, "ACCOUNT");
229 + if (!IsMe(acptr)) {
230 + /* in-transit message, forward it */
231 + sendcmdto_one(sptr, CMD_ACCOUNT, acptr,
232 + type == 'C' ? "%C %s %s %s :%s" : "%C %s %s",
233 + acptr, parv[2], parv[3], parv[4], parv[parc-1]);
237 + /* the message is for me, process it */
239 + return protocol_violation(cptr, "ACCOUNT check (%s %s %s)", parv[3], parv[4], parv[parc-1]);
241 + if (!(acptr = findNUser(parv[3])))
243 + if (IsRegistered(acptr) || !acptr->cli_cs_service)
244 + return protocol_violation(cptr, "Invalid ACCOUNT %s for %s", parv[2], cli_name(acptr));
247 + ircd_strncpy(cli_user(acptr)->account, acptr->cli_cs_user, ACCOUNTLEN);
248 + hide_hostmask(acptr, FLAGS_ACCOUNT | FLAGS_HIDDENHOST);
251 + sendcmdto_one(&me, CMD_NOTICE, acptr, "%C :AUTHENTICATION %s as %s", acptr,
252 + type == 'A' ? "SUCCESSFUL" : "FAILED",
253 + acptr->cli_cs_user);
255 + MyFree(acptr->cli_cs_service);
256 + MyFree(acptr->cli_cs_user);
257 + MyFree(acptr->cli_cs_pass);
258 + acptr->cli_cs_service = acptr->cli_cs_user = acptr->cli_cs_pass = NULL;
261 + sendcmdto_one(&me, CMD_NOTICE, acptr, "%C :Type /QUOTE PASS to connect anyway", acptr);
265 + return register_user(acptr, acptr, cli_name(acptr), cli_user(acptr)->username);
271 ===================================================================
272 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_pass.c,v
273 retrieving revision 1.7
274 diff -u -r1.7 m_pass.c
275 --- ircd/m_pass.c 2001/06/29 15:51:02 1.7
276 +++ ircd/m_pass.c 2002/04/12 13:17:10
279 #include "ircd_reply.h"
280 #include "ircd_string.h"
281 +#include "ircd_alloc.h"
282 +#include "ircd_features.h"
290 assert(cptr == sptr);
291 assert(!IsRegistered(sptr));
293 - if (EmptyString(password))
294 - return need_more_params(cptr, "PASS");
296 /* TODO: For protocol negotiation */
298 if (ircd_strcmp(password,"PROT")==0) {
299 /* Do something here */
302 - ircd_strncpy(cli_passwd(cptr), password, PASSWDLEN);
304 + if (!EmptyString(password))
305 + ircd_strncpy(cli_passwd(cptr), password, PASSWDLEN);
307 + if (!feature_bool(FEAT_LOGIN_ON_CONNECT) || cptr->cli_cs_service)
311 + DupString(cptr->cli_cs_service, parv[parc-3]);
312 + DupString(cptr->cli_cs_user, parv[parc-2]);
313 + DupString(cptr->cli_cs_pass, parv[parc-1]);
316 + /* Deal with password retries */
317 + if ((cli_name(cptr))[0] && cli_cookie(cptr) == COOKIE_VERIFIED)
318 + return register_user(cptr, cptr, cli_name(cptr), cli_user(cptr)->username);
323 ===================================================================
324 RCS file: /home/coder-com/cvs/ircu2.10/ircd/m_user.c,v
325 retrieving revision 1.7
326 diff -u -r1.7 m_user.c
327 --- ircd/m_user.c 2001/06/08 23:12:17 1.7
328 +++ ircd/m_user.c 2002/04/12 13:17:10
329 @@ -142,16 +142,14 @@
332 ircd_strncpy(cli_info(cptr), info, REALLEN);
333 + ircd_strncpy(user->username, username, USERLEN);
334 + ircd_strncpy(user->host, cli_sockhost(cptr), HOSTLEN);
336 if ((cli_name(cptr))[0] && cli_cookie(cptr) == COOKIE_VERIFIED) {
338 * NICK and PONG already received, now we have USER...
340 return register_user(cptr, sptr, cli_name(sptr), username);
343 - ircd_strncpy(user->username, username, USERLEN);
344 - ircd_strncpy(user->host, cli_sockhost(cptr), HOSTLEN);
349 ===================================================================
350 RCS file: /home/coder-com/cvs/ircu2.10/ircd/s_user.c,v
351 retrieving revision 1.58
352 diff -u -r1.58 s_user.c
353 --- ircd/s_user.c 2002/04/05 11:36:59 1.58
354 +++ ircd/s_user.c 2002/04/12 13:17:10
356 parv[0] = cli_name(sptr);
357 parv[1] = parv[2] = NULL;
359 + if (MyConnect(sptr) && sptr->cli_cs_service && sptr->cli_cs_user && sptr->cli_cs_pass) {
360 + struct Client *acptr;
362 + if (!(acptr = FindUser(sptr->cli_cs_service)) || !IsChannelService(acptr)) {
363 + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Service '%s' is not available", sptr, sptr->cli_cs_service);
364 + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Type /QUOTE PASS to connect anyway", sptr);
365 + MyFree(sptr->cli_cs_service);
366 + MyFree(sptr->cli_cs_user);
367 + MyFree(sptr->cli_cs_pass);
368 + sptr->cli_cs_service = sptr->cli_cs_user = sptr->cli_cs_pass = NULL;
370 + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Attempting service login to %s",
371 + sptr, cli_name(acptr));
372 + sendcmdto_one(&me, CMD_ACCOUNT, acptr, "%C C %s%s %s :%s", acptr,
373 + NumNick(sptr), sptr->cli_cs_user, sptr->cli_cs_pass);
380 static time_t last_too_many1;
382 IPcheck_connect_fail(cli_ip(sptr));
383 return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
385 - ircd_strncpy(user->host, cli_sockhost(sptr), HOSTLEN);
386 + /* The host might be already set from login-on-connect */
387 + if (!HasHiddenHost(sptr))
388 + ircd_strncpy(user->host, cli_sockhost(sptr), HOSTLEN);
389 ircd_strncpy(user->realhost, cli_sockhost(sptr), HOSTLEN);
390 aconf = cli_confs(sptr)->value.aconf;
392 --- /dev/null Thu Aug 24 12:00:32 2000
393 +++ doc/readme.login-on-connect Fri Apr 12 16:16:56 2002
395 +1. This feature is experimental.
397 +2. The main point is to allow clients to log in to a service bot (i.e., X)
398 +*before* being announced to the network. Otherwise, a combination of a
399 +malicious user, /ISON, /USERIP and low latency can reveal it's real host/IP
400 +before he gets a chance to log in and set himself +x
402 +3. Client<->Server changes:
403 +~~~~~~~~~~~~~~~~~~~~~~~~~~~
404 +The PASS command now has the following syntax:
406 +PASS [optional Client block password] <bot nick> <username> :<passphrase>
408 +If the client specifies sends such a password message, after sending NICK,
409 +USER and PONG, it's username/passphrase are sent to the specified bot
410 +for validation, while holding the client in the 'registration' state.
411 +If the authentication succeeds, the client's account and umode +x are set,
412 +after which he is introduced to the network, continuing the regular connect
413 +phase. If authentication fails (or the bot is not on the network), the user
414 +is given a chance to retry (he can do this by sending another PASS command),
415 +or to disconnect from the server. If he wishes to connect without a hidden
416 +hostmask, he can send a PASS command with no parameters.
418 +4. Server<->Server changes:
419 +~~~~~~~~~~~~~~~~~~~~~~~~~~~
420 +The ACCOUNT message now has the following syntax:
423 +<client's server numeric> AC <bot's numeric> C <client's numeric> <username> :<passphrase>
424 +Servers send this message to request a service bot to authenticate the client.
425 +Note that <client's numeric> will only be used by the originating server for
426 +matching auth replies, as the user has not yet been announced to the network.
427 +Hubs will have to propagate this message as-is towards the service bot,
428 +much like they do for PRIVMSGs.
431 +<bot's server numeric> AC <client's server numeric> A|D <client's numeric>
432 +Service bots send this in reply to an 'auth check' message from a server.
433 +"A" stands for "accepted", "D" for "denied". Again, hubs will have
434 +to proagate this message back to the client's server.
437 +<bot's server numeric> AC <client numeric> R <account>
438 +This is the current message used by service bots to announce the network
439 +that a user has logged in. The old format is still supported:
440 +<bot's server numeric> AC <client numeric> <account>
442 +5. ircu code changes
443 +~~~~~~~~~~~~~~~~~~~~
444 +A new feature, FEAT_LOGIN_ON_CONNECT (default FALSE) will specify whether
445 +ircu will honour the login scheme as specified above for the PASS command.
446 +ircu will route ACCOUNT messages anyway, regardless of this feature's value.
450 +A patch follows that will implement auth checks and replies.
452 +Index: mod.cservice/cservice.cc
453 +===================================================================
454 +RCS file: /cvsroot/gnuworld/gnuworld/mod.cservice/cservice.cc,v
455 +retrieving revision 1.213
456 +diff -u -r1.213 cservice.cc
457 +--- mod.cservice/cservice.cc 10 Apr 2002 19:00:10 -0000 1.213
458 ++++ mod.cservice/cservice.cc 12 Apr 2002 12:33:45 -0000
459 +@@ -2491,15 +2491,45 @@
463 +- iClient* tmpUser = static_cast< iClient* >( data1 ) ;
464 +- networkData* tmpData = static_cast< networkData* >(tmpUser->getCustomData(this) ) ;
465 +- /* Lookup this user account, if its not there.. trouble */
466 +- sqlUser* theUser = getUserRecord(tmpUser->getAccount());
469 +- tmpData->currentUser = theUser;
470 +- theUser->addAuthedClient(tmpUser);
471 ++ char *ac_type = static_cast <char *> (data1);
472 ++ if (*ac_type == 'R') {
473 ++ iClient* tmpUser = static_cast< iClient* >( data2 ) ;
474 ++ networkData* tmpData = static_cast< networkData* >(tmpUser->getCustomData(this) ) ;
475 ++ /* Lookup this user account, if its not there.. trouble */
476 ++ sqlUser* theUser = getUserRecord(tmpUser->getAccount());
479 ++ tmpData->currentUser = theUser;
480 ++ theUser->addAuthedClient(tmpUser);
482 ++ } else if (*ac_type == 'C') {
483 ++ // server prefix, client prefix, username, password
484 ++ char **param_list = static_cast <char **> (data2);
485 ++ sqlUser* theUser = getUserRecord(param_list[2]);
488 ++ LogDebugMessage("Checking account: user=%s pass=%s ok=%d susp=%d maxlog=%d/%d",
491 ++ isPasswordRight(theUser, param_list[3]),
492 ++ theUser->getFlag(sqlUser::F_GLOBAL_SUSPEND),
493 ++ theUser->networkClientList.size() + 1,
494 ++ theUser->getMaxLogins());
496 ++ ac << getCharYY() << " AC " << param_list[0];
498 ++ if (theUser && !theUser->getFlag(sqlUser::F_GLOBAL_SUSPEND) &&
499 ++ isPasswordRight(theUser, param_list[3]) &&
500 ++ theUser->networkClientList.size() + 1 <= theUser->getMaxLogins()) {
506 ++ ac << param_list[1] << ends;
508 ++ delete[] ac.str();
512 + case EVT_BURST_ACK:
513 +Index: src/msg_AC.cc
514 +===================================================================
515 +RCS file: /cvsroot/gnuworld/gnuworld/src/msg_AC.cc,v
516 +retrieving revision 1.1
517 +diff -u -r1.1 msg_AC.cc
518 +--- src/msg_AC.cc 12 Jan 2002 21:42:17 -0000 1.1
519 ++++ src/msg_AC.cc 12 Apr 2002 12:33:46 -0000
521 + * SOURCE AC TARGET ACCOUNT
523 + * AXAAA AC BQrTd Gte
525 ++ * AX AC BQrTd R Gte
526 ++ * BQ AC AX C BqrTd Gte :Gte's Pass
528 +-int xServer::MSG_AC( xParameters& Param )
529 ++int xServer::MSG_AC(xParameters &Param)
532 + * First, update this users information.
535 +-iClient* theClient = Network->findClient(Param[1]);
540 ++const char *numeric = NULL, *account = NULL;
541 ++static char *ac_type_C = "C";
542 ++static char *ac_type_R = "R";
544 +-theClient->setAccount(Param[2]);
545 ++if (Param.size() < 4) {
546 ++ numeric = Param[1];
547 ++ account = Param[2];
548 ++} else if (Param[2][0] == 'R') {
549 ++ numeric = Param[1];
550 ++ account = Param[3];
551 ++} else if (Param[2][0] == 'C') {
552 ++ const char *param_list[4];
553 ++ param_list[0] = Param[0];
554 ++ param_list[1] = Param[3];
555 ++ param_list[2] = Param[4];
556 ++ param_list[3] = Param[5];
557 ++ PostEvent(EVT_ACCOUNT, static_cast <void *> (ac_type_C), static_cast <void *> (param_list));
561 ++if (!numeric || !account)
564 ++iClient *theClient = Network->findClient(numeric);
568 ++theClient->setAccount(account);
569 ++PostEvent(EVT_ACCOUNT, static_cast <void *> (ac_type_R), static_cast <void *> (theClient)) ;
571 +-PostEvent( EVT_ACCOUNT, static_cast< void* >( theClient ) ) ;
576 + } // namespace gnuworld