/* * cryptlink_serv - CRYPTLINK SERV message handler * parv[0] == CRYPTLINK * parv[1] == SERV * parv[2] == server name * parv[3] == keyphrase * parv[4] == :server info (M-line) */ static void cryptlink_serv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char info[REALLEN + 1]; char *name; struct Client *target_p; char *key = client_p->localClient->out_key; unsigned char *b64_key; struct ConfItem *conf; struct AccessItem *aconf; char *encrypted; const char *p; int enc_len; /* if (client_p->name[0] != 0) return; */ if ((parc < 5) || (*parv[4] == '\0')) { cryptlink_error(client_p, "SERV", "Invalid params", "CRYPTLINK SERV - Invalid params"); return; } if ((name = parse_cryptserv_args(client_p, parv, parc, info, key)) == NULL) { cryptlink_error(client_p, "SERV", "Invalid params", "CRYPTLINK SERV - Invalid params"); return; } /* CRYPTLINK SERV support => TS support */ client_p->tsinfo = TS_DOESTS; if (bogus_host(name)) { exit_client(client_p, client_p, "Bogus server name"); return; } /* Now we just have to call check_server and everything should be * checked for us... -A1kmm. */ switch (check_server(name, client_p, CHECK_SERVER_CRYPTLINK)) { case -1: if (ConfigFileEntry.warn_no_nline) { cryptlink_error(client_p, "SERV", "Unauthorized server connection attempt: No entry for server", NULL); } exit_client(client_p, client_p, "Invalid server name"); return; break; case -2: cryptlink_error(client_p, "SERV", "Unauthorized server connection attempt: CRYPTLINK not " "enabled on remote server", "CRYPTLINK not enabled"); return; break; case -3: cryptlink_error(client_p, "SERV", "Unauthorized server connection attempt: Invalid host", "Invalid host"); return; break; } if ((target_p = find_server(name))) { /* * This link is trying feed me a server that I already have * access through another path -- multiple paths not accepted * currently, kill this link immediately!! * * Rather than KILL the link which introduced it, KILL the * youngest of the two links. -avalon * * Definitely don't do that here. This is from an unregistered * connect - A1kmm. */ cryptlink_error(client_p, "SERV", "Attempt to re-introduce existing server", "Server Exists"); return; } if (ServerInfo.hub && IsCapable(client_p, CAP_LL)) { if (IsCapable(client_p, CAP_HUB)) { ClearCap(client_p,CAP_LL); sendto_realops_flags(UMODE_ALL, L_ALL, "*** LazyLinks to a hub from a hub, that's a no-no."); } else { client_p->localClient->serverMask = nextFreeMask(); if(!client_p->localClient->serverMask) { sendto_realops_flags(UMODE_ALL, L_ALL, "serverMask is full!"); /* try and negotiate a non LL connect */ ClearCap(client_p,CAP_LL); } } } else if (IsCapable(client_p, CAP_LL)) { if (!IsCapable(client_p, CAP_HUB)) { ClearCap(client_p,CAP_LL); sendto_realops_flags(UMODE_ALL, L_ALL, "*** LazyLinks to a leaf from a leaf, that's a no-no."); } } conf = find_conf_name(&client_p->localClient->confs, name, SERVER_TYPE); if (conf == NULL) { cryptlink_error(client_p, "AUTH", "Lost C-line for server", "Lost C-line" ); return; } /* * if we are connecting (Handshake), we already have the name from the * connect {} block in client_p->name */ strlcpy(client_p->name, name, sizeof(client_p->name)); p = info; if (!strncmp(info, "(H)", 3)) { SetHidden(client_p); if ((p = strchr(info, ' ')) != NULL) { p++; if (*p == '\0') p = "(Unknown Location)"; } else p = "(Unknown Location)"; } strlcpy(client_p->info, p, sizeof(client_p->info)); client_p->hopcount = 0; aconf = (struct AccessItem *)map_to_conf(conf); if (!(client_p->localClient->out_cipher || (client_p->localClient->out_cipher = check_cipher(client_p, aconf)))) { cryptlink_error(client_p, "AUTH", "Couldn't find compatible cipher", "Couldn't find compatible cipher"); return; } encrypted = MyMalloc(RSA_size(ServerInfo.rsa_private_key)); enc_len = RSA_public_encrypt(client_p->localClient->out_cipher->keylen, (unsigned char *)key, (unsigned char *)encrypted, aconf->rsa_public_key, RSA_PKCS1_PADDING); if (enc_len <= 0) { report_crypto_errors(); MyFree(encrypted); cryptlink_error(client_p, "AUTH", "Couldn't encrypt data", "Couldn't encrypt data"); return; } base64_block(&b64_key, encrypted, enc_len); MyFree(encrypted); if (!IsWaitAuth(client_p)) { cryptlink_init(client_p, conf, NULL); } sendto_one(client_p, "CRYPTLINK AUTH %s %s", client_p->localClient->out_cipher->name, b64_key); /* needed for old servers that can't shove data back into slink */ send_queued_write(client_p); SetCryptOut(client_p); MyFree(b64_key); }
/* ** mo_jupe ** parv[0] = sender prefix ** parv[1] = server we're juping ** parv[2] = reason for jupe */ static void mo_jupe(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; struct Client *ajupe; dlink_node *m; char reason[REALLEN+2]; if(!ServerInfo.hub) return; if(!IsOperAdmin(source_p)) { sendto_one(source_p, ":%s NOTICE %s :You must be an admin to use this command", me.name, parv[0]); return; } if (bogus_host(parv[1])) { sendto_one(source_p, ":%s NOTICE %s :Invalid servername: %s", me.name, parv[0], parv[1]); return; } if(match(parv[1], me.name)) { sendto_one(source_p, ":%s NOTICE %s :I cant jupe myself!", me.name, source_p->name); return; } sendto_wallops_flags(UMODE_WALLOP, &me, "JUPE for %s requested by %s: %s", parv[1], get_oper_name(source_p), parv[2]); sendto_server(NULL, NOCAPS, NOCAPS, ":%s WALLOPS :JUPE for %s requested by %s!%s@%s: %s", parv[0], parv[1], source_p->name, source_p->username, source_p->host, parv[2]); ilog(L_NOTICE, "JUPE for %s requested by %s: %s", parv[1], get_oper_name(source_p), parv[2]); target_p= find_server(parv[1]); if(target_p) exit_client(client_p, target_p, &me, parv[2]); sendto_server(NULL, NOCAPS, NOCAPS, ":%s SERVER %s 1 :JUPED: %s", me.name, parv[1], parv[2]); sendto_realops_flags(UMODE_ALL, L_ALL, "Link with %s established: (JUPED) link", parv[1]); ajupe = make_client(NULL); /* make_client() adds client to unknown_list */ m = dlinkFind(&unknown_list, ajupe); if(m != NULL) dlinkDelete(m, &unknown_list); free_dlink_node(m); make_server(ajupe); ajupe->hopcount = 1; strlcpy(ajupe->name,parv[1],HOSTLEN); /* we need to give 7 chars to prepend "JUPED: " */ if(strlen(parv[2]) > (REALLEN-7)) parv[2][REALLEN-7] = '\0'; ircsprintf(reason, "%s %s", "JUPED:", parv[2]); strlcpy(ajupe->info,reason,REALLEN); ajupe->serv->up = me.name; ajupe->servptr = &me; SetServer(ajupe); SetDead(ajupe); Count.server++; Count.myserver++; /* Some day, all these lists will be consolidated *sigh* */ add_client_to_list(ajupe); add_to_client_hash_table(ajupe->name, ajupe); dlinkAdd(ajupe, &ajupe->lnode, &ajupe->servptr->serv->servers); add_server_to_list(ajupe); }
/* * mr_server - SERVER message handler * parv[0] = sender prefix * parv[1] = servername * parv[2] = serverinfo/hopcount * parv[3] = serverinfo */ static void mr_server(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char info[REALLEN + 1]; char *name; struct Client *target_p; int hop; if (parc < 4) { sendto_one(client_p,"ERROR :No servername"); exit_client(client_p, client_p, client_p, "Wrong number of args"); return; } name = parv[1]; hop = atoi(parv[2]); strlcpy(info, parv[3], REALLEN); /* * Reject a direct nonTS server connection if we're TS_ONLY -orabidoo */ if (!DoesTS(client_p)) { sendto_realops_flags(FLAGS_ALL, L_ADMIN,"Link %s dropped, non-TS server", get_client_name(client_p, HIDE_IP)); sendto_realops_flags(FLAGS_ALL, L_OPER,"Link %s dropped, non-TS server", get_client_name(client_p, MASK_IP)); exit_client(client_p, client_p, client_p, "Non-TS server"); return; } if (bogus_host(name)) { exit_client(client_p, client_p, client_p, "Bogus server name"); return; } /* Now we just have to call check_server and everything should be * check for us... -A1kmm. */ switch (check_server(name, client_p, CHECK_SERVER_NOCRYPTLINK)) { case -1: if (ConfigFileEntry.warn_no_nline) { sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Unauthorized server connection attempt from %s: No entry for " "servername %s", get_client_name(client_p, HIDE_IP), name); sendto_realops_flags(FLAGS_ALL, L_OPER, "Unauthorized server connection attempt from %s: No entry for " "servername %s", get_client_name(client_p, MASK_IP), name); } exit_client(client_p, client_p, client_p, "Invalid servername."); return; /* NOT REACHED */ break; case -2: sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Unauthorized server connection attempt from %s: Bad password " "for server %s", get_client_name(client_p, HIDE_IP), name); sendto_realops_flags(FLAGS_ALL, L_OPER, "Unauthorized server connection attempt from %s: Bad password " "for server %s", get_client_name(client_p, MASK_IP), name); exit_client(client_p, client_p, client_p, "Invalid password."); return; /* NOT REACHED */ break; case -3: sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Unauthorized server connection attempt from %s: Invalid host " "for server %s", get_client_name(client_p, HIDE_IP), name); sendto_realops_flags(FLAGS_ALL, L_OPER, "Unauthorized server connection attempt from %s: Invalid host " "for server %s", get_client_name(client_p, MASK_IP), name); exit_client(client_p, client_p, client_p, "Invalid host."); return; /* NOT REACHED */ break; /* servername is > HOSTLEN */ case -4: sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Invalid servername %s from %s", name, get_client_name(client_p, HIDE_IP)); sendto_realops_flags(FLAGS_ALL, L_OPER, "Invalid servername %s from %s", name, get_client_name(client_p, MASK_IP)); exit_client(client_p, client_p, client_p, "Invalid servername."); return; /* NOT REACHED */ break; } if ((target_p = server_exists(name))) { /* * This link is trying feed me a server that I already have * access through another path -- multiple paths not accepted * currently, kill this link immediately!! * * Rather than KILL the link which introduced it, KILL the * youngest of the two links. -avalon * * Definitely don't do that here. This is from an unregistered * connect - A1kmm. */ sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Attempt to re-introduce server %s from %s", name, get_client_name(client_p, HIDE_IP)); sendto_realops_flags(FLAGS_ALL, L_OPER, "Attempt to re-introduce server %s from %s", name, get_client_name(client_p, MASK_IP)); sendto_one(client_p, "ERROR :Server already exists."); exit_client(client_p, client_p, client_p, "Server Exists"); return; } if(ServerInfo.hub && IsCapable(client_p, CAP_LL)) { if(IsCapable(client_p, CAP_HUB)) { ClearCap(client_p,CAP_LL); sendto_realops_flags(FLAGS_ALL, L_ALL, "*** LazyLinks to a hub from a hub, thats a no-no."); } else { client_p->localClient->serverMask = nextFreeMask(); if(!client_p->localClient->serverMask) { sendto_realops_flags(FLAGS_ALL, L_ALL, "serverMask is full!"); /* try and negotiate a non LL connect */ ClearCap(client_p,CAP_LL); } } } else if (IsCapable(client_p, CAP_LL)) { if(!IsCapable(client_p, CAP_HUB)) { ClearCap(client_p,CAP_LL); sendto_realops_flags(FLAGS_ALL, L_ALL, "*** LazyLinks to a leaf from a leaf, thats a no-no."); } } /* * if we are connecting (Handshake), we already have the name from the * C:line in client_p->name */ strlcpy(client_p->name, name, HOSTLEN+1); set_server_gecos(client_p, info); client_p->hopcount = hop; server_estab(client_p); }