/* * 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); }
/* * 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); }