コード例 #1
0
/*
 * cryptlink_auth - CRYPTLINK AUTH message handler
 *        parv[1] = secret key
 */
static void
cryptlink_auth(struct Client *client_p, struct Client *source_p,
               int parc, char *parv[])
{
  struct EncCapability *ecap;
  struct ConfItem *conf;
  struct AccessItem *aconf;
  int   enc_len;
  int   len;
  unsigned char *enc;
  unsigned char *key;

  if (parc < 4)
  {
    cryptlink_error(client_p, "AUTH", "Invalid params",
                    "CRYPTLINK AUTH - Invalid params");
    return;
  }

  if (!IsWaitAuth(client_p))
    return;

  for (ecap = CipherTable; ecap->name; ecap++)
  {
    if ((!irccmp(ecap->name, parv[2])) &&
        (IsCapableEnc(client_p, ecap->cap)))
    {
      client_p->localClient->in_cipher = ecap;
      break;
    }
  }

  if (client_p->localClient->in_cipher == NULL)
  {
    cryptlink_error(client_p, "AUTH", "Invalid cipher", "Invalid cipher");
    return;
  }

  if (!(enc_len = unbase64_block(&enc, parv[3], strlen(parv[3]))))
  {
    cryptlink_error(client_p, "AUTH",
                    "Could not base64 decode response",
                    "Malformed CRYPTLINK AUTH reply");
    return;
  }

  if (verify_private_key() == -1)
  {
    sendto_realops_flags(UMODE_ALL, L_ADMIN,
      "verify_private_key() returned -1.  Check log for information.");
  }

  key = MyMalloc(RSA_size(ServerInfo.rsa_private_key));
  len = RSA_private_decrypt(enc_len, (unsigned char *)enc,(unsigned char *)key,
                            ServerInfo.rsa_private_key,
                            RSA_PKCS1_PADDING);

  if (len < client_p->localClient->in_cipher->keylen)
  {
    report_crypto_errors();
    if (len < 0)
    {
      cryptlink_error(client_p, "AUTH",
                      "Decryption failed",
                      "Malformed CRYPTLINK AUTH reply");
    }
    else
    {
      cryptlink_error(client_p, "AUTH",
                      "Not enough random data sent",
                      "Malformed CRYPTLINK AUTH reply");
    }
    MyFree(enc);
    MyFree(key);
    return;
  }

  if (memcmp(key, client_p->localClient->in_key,
             client_p->localClient->in_cipher->keylen) != 0)
  {
    cryptlink_error(client_p, "AUTH",
                    "Unauthorized server connection attempt",
                    "Malformed CRYPTLINK AUTH reply");
    return;
  }

  conf = find_conf_name(&client_p->localClient->confs,
                         client_p->name, SERVER_TYPE);

  if (conf == NULL)
  {
    cryptlink_error(client_p, "AUTH",
                    "Lost C-line for server",
                    "Lost C-line");
    return;
  }

  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;
  }

  /* set hopcount */
  client_p->hopcount = 1;

  SetCryptIn(client_p);
  ClearWaitAuth(client_p);
  server_estab(client_p);
}
コード例 #2
0
ファイル: m_server.c プロジェクト: mojadita/ircd
/** Handle a SERVER message from an unregistered connection.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server name
 * \li \a parv[2] is the hop count to the server
 * \li \a parv[3] is the start timestamp for the server
 * \li \a parv[4] is the link timestamp
 * \li \a parv[5] is the protocol version (P10 or J10)
 * \li \a parv[6] is the numnick mask for the server
 * \li \a parv[7] is a string of flags like +hs to mark hubs and services
 * \li \a parv[\a parc - 1] is the server description
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char*            host;
  struct ConfItem* aconf;
  struct Jupe*     ajupe;
  unsigned int     hop;
  int              ret;
  unsigned short   prot;
  time_t           start_timestamp;
  time_t           timestamp;
  time_t           recv_time;
  time_t           ghost;

  if (IsUserPort(cptr))
    return exit_client_msg(cptr, cptr, &me,
                           "Cannot connect a server to a user port");

  if (parc < 8)
  {
    need_more_params(sptr, "SERVER");
    return exit_client(cptr, cptr, &me, "Need more parameters");
  }
  host = clean_servername(parv[1]);
  if (!host)
  {
    sendto_opmask(0, SNO_OLDSNO, "Bogus server name (%s) from %s",
                  host, cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
  }

  if ((ajupe = jupe_find(host)) && JupeIsActive(ajupe))
    return exit_client_msg(cptr, sptr, &me, "Juped: %s", JupeReason(ajupe));

  /* check connection rules */
  if (0 != conf_eval_crule(host, CRULE_ALL)) {
    ServerStats->is_ref++;
    sendto_opmask(0, SNO_OLDSNO, "Refused connection from %s.", cli_name(cptr));
    return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
  }

  log_write(LS_NETWORK, L_NOTICE, LOG_NOSNOTICE, "SERVER: %s %s[%s]", host,
	    cli_sockhost(cptr), cli_sock_ip(cptr));

  /*
   * Detect protocol
   */
  hop = atoi(parv[2]);
  start_timestamp = atoi(parv[3]);
  timestamp = atoi(parv[4]);
  prot = parse_protocol(parv[5]);
  if (!prot)
    return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
  else if (prot < atoi(MINOR_PROTOCOL))
    return exit_new_server(cptr, sptr, host, timestamp,
                           "Incompatible protocol: %s", parv[5]);

  Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age %Tu (%Tu)",
	 host, parv[4], start_timestamp, cli_serv(&me)->timestamp));

  if (timestamp < OLDEST_TS || start_timestamp < OLDEST_TS)
    return exit_client_msg(cptr, sptr, &me,
        "Bogus timestamps (%s %s)", parv[3], parv[4]);

  /* If the server had a different name before, change it. */
  if (!EmptyString(cli_name(cptr)) &&
      (IsUnknown(cptr) || IsHandshake(cptr)) &&
      0 != ircd_strcmp(cli_name(cptr), host))
    hChangeClient(cptr, host);
  ircd_strncpy(cli_name(cptr), host, HOSTLEN);
  ircd_strncpy(cli_info(cptr), parv[parc-1][0] ? parv[parc-1] : cli_name(&me), REALLEN);
  cli_hopcount(cptr) = hop;

  if (conf_check_server(cptr)) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Received unauthorized connection from %s",
                  cli_name(cptr));
    log_write(LS_NETWORK, L_NOTICE, LOG_NOSNOTICE, "Received unauthorized "
              "connection from %C [%s]", cptr,
              ircd_ntoa(&cli_ip(cptr)));
    return exit_client(cptr, cptr, &me, "No Connect block");
  }

  host = cli_name(cptr);

  update_load();

  if (!(aconf = find_conf_byname(cli_confs(cptr), host, CONF_SERVER))) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied. No conf line for server %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "Access denied. No conf line for server %s", cli_name(cptr));
  }

#if defined(USE_SSL)
  if (!verify_sslclifp(cptr, aconf)) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied (SSL fingerprint mismatch) %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "No Access (SSL fingerprint mismatch) %s", cli_name(cptr));
  }
#endif

  if (*aconf->passwd && !!strcmp(aconf->passwd, cli_passwd(cptr))) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied (passwd mismatch) %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "No Access (passwd mismatch) %s", cli_name(cptr));
  }

  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));

  ret = check_loop_and_lh(cptr, sptr, &ghost, host, (parc > 7 ? parv[6] : NULL), timestamp, hop, 1);
  if (ret != 1)
    return ret;

  make_server(cptr);
  cli_serv(cptr)->timestamp = timestamp;
  cli_serv(cptr)->prot = prot;
  cli_serv(cptr)->ghost = ghost;
  memset(cli_privs(cptr), 255, sizeof(struct Privs));
  ClrPriv(cptr, PRIV_SET);
  SetServerYXX(cptr, cptr, parv[6]);
  update_uworld_flags(cptr);

  if (*parv[7] == '+')
    set_server_flags(cptr, parv[7] + 1);

  recv_time = TStime();
  check_start_timestamp(cptr, timestamp, start_timestamp, recv_time);
  ret = server_estab(cptr, aconf);

  if (feature_bool(FEAT_RELIABLE_CLOCK) &&
      abs(cli_serv(cptr)->timestamp - recv_time) > 30) {
    sendto_opmask(0, SNO_OLDSNO, "Connected to a net with a "
                  "timestamp-clock difference of %Td seconds! "
                  "Used SETTIME to correct this.",
                  timestamp - recv_time);
    sendcmdto_prio_one(&me, CMD_SETTIME, cptr, "%Tu :%s", TStime(),
		       cli_name(&me));
  }

  return ret;
}
コード例 #3
0
ファイル: m_server.c プロジェクト: Cloudxtreme/ircd-3
/*
 * 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);
}