~ubuntu-branches/debian/sid/ircd-hybrid/sid

« back to all changes in this revision

Viewing changes to src/server.c

  • Committer: Package Import Robot
  • Author(s): Dominic Hargreaves
  • Date: 2015-04-19 15:53:09 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20150419155309-06y59x2at2ax5ou3
Tags: 1:8.2.7+dfsg.1-1
* Remove Suggests: hybserv since it doesn't really work with
  ircd-hybrid 8 and above
* New upstream release
  - update debian/copyright with minor changes
  - update config files from new reference.conf
  - fixes DoS from localhost clients (Closes: #782859)
  - supports SSL certficate chaining (Closes: #769741)
* Debconf configuration script no longer ignores the result of
  upgrade questions (Closes: #779082)
* Don't display upgrade warnings on new installs (Closes: #782883)
* Add NEWS item about updated configuration

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3
3
 *
4
 
 *  Copyright (c) 1997-2014 ircd-hybrid development team
 
4
 *  Copyright (c) 1997-2015 ircd-hybrid development team
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
21
21
 
22
22
/*! \file s_serv.c
23
23
 * \brief Server related functions.
24
 
 * \version $Id: server.c 4564 2014-08-24 10:24:47Z michael $
 
24
 * \version $Id: server.c 5775 2015-04-04 17:31:06Z michael $
25
25
 */
26
26
 
27
27
#include "stdinc.h"
51
51
#define MIN_CONN_FREQ 300
52
52
 
53
53
dlink_list flatten_links;
54
 
static dlink_list cap_list = { NULL, NULL, 0 };
 
54
static dlink_list cap_list;
55
55
static void serv_connect_callback(fde_t *, int, void *);
56
56
 
57
57
 
67
67
write_links_file(void *unused)
68
68
{
69
69
  FILE *file = NULL;
70
 
  dlink_node *ptr = NULL, *ptr_next = NULL;
 
70
  dlink_node *node = NULL, *node_next = NULL;
71
71
  char buff[IRCD_BUFSIZE] = "";
72
72
 
73
73
  if ((file = fopen(LIPATH, "w")) == NULL)
74
74
    return;
75
75
 
76
 
  DLINK_FOREACH_SAFE(ptr, ptr_next, flatten_links.head)
 
76
  DLINK_FOREACH_SAFE(node, node_next, flatten_links.head)
77
77
  {
78
 
    dlinkDelete(ptr, &flatten_links);
79
 
    MyFree(ptr->data);
80
 
    free_dlink_node(ptr);
 
78
    dlinkDelete(node, &flatten_links);
 
79
    MyFree(node->data);
 
80
    free_dlink_node(node);
81
81
  }
82
82
 
83
 
  DLINK_FOREACH(ptr, global_server_list.head)
 
83
  DLINK_FOREACH(node, global_server_list.head)
84
84
  {
85
 
    const struct Client *target_p = ptr->data;
 
85
    const struct Client *target_p = node->data;
86
86
 
87
87
    /*
88
88
     * Skip hidden servers, aswell as ourselves, since we already send
157
157
            const int server, const int parc, char *parv[])
158
158
{
159
159
  struct Client *target_p = NULL;
160
 
  dlink_node *ptr = NULL;
 
160
  dlink_node *node = NULL;
161
161
 
162
162
  /* Assume it's me, if no server */
163
163
  if (parc <= server || EmptyString(parv[server]))
177
177
 
178
178
  if (!target_p && has_wildcards(parv[server]))
179
179
  {
180
 
    DLINK_FOREACH(ptr, global_client_list.head)
 
180
    DLINK_FOREACH(node, global_client_list.head)
181
181
    {
182
 
      struct Client *tmp = ptr->data;
 
182
      struct Client *tmp = node->data;
183
183
 
184
184
      assert(IsMe(tmp) || IsServer(tmp) || IsClient(tmp));
185
185
      if (!match(parv[server], tmp->name))
187
187
        if (tmp->from == source_p->from && !MyConnect(tmp))
188
188
          continue;
189
189
 
190
 
        target_p = ptr->data;
 
190
        target_p = node->data;
191
191
        break;
192
192
      }
193
193
    }
223
223
void
224
224
try_connections(void *unused)
225
225
{
226
 
  dlink_node *ptr = NULL;
 
226
  dlink_node *node = NULL;
227
227
  int confrq = 0;
228
228
 
229
229
  /* TODO: change this to set active flag to 0 when added to event! --Habeeb */
230
230
  if (GlobalSetOptions.autoconn == 0)
231
231
    return;
232
232
 
233
 
  DLINK_FOREACH(ptr, server_items.head)
 
233
  DLINK_FOREACH(node, server_items.head)
234
234
  {
235
 
    struct MaskItem *conf = ptr->data;
 
235
    struct MaskItem *conf = node->data;
236
236
 
237
237
    assert(conf->type == CONF_SERVER);
238
238
 
269
269
    if (conf->class->ref_count < conf->class->max_total)
270
270
    {
271
271
      /* Go to the end of the list, if not already last */
272
 
      if (ptr->next)
 
272
      if (node->next)
273
273
      {
274
 
        dlinkDelete(ptr, &server_items);
 
274
        dlinkDelete(node, &server_items);
275
275
        dlinkAddTail(conf, &conf->node, &server_items);
276
276
      }
277
277
 
324
324
int
325
325
check_server(const char *name, struct Client *client_p)
326
326
{
327
 
  dlink_node *ptr;
 
327
  dlink_node *node = NULL;
328
328
  struct MaskItem *conf        = NULL;
329
329
  struct MaskItem *server_conf = NULL;
330
330
  int error = -1;
332
332
  assert(client_p);
333
333
 
334
334
  /* loop through looking for all possible connect items that might work */
335
 
  DLINK_FOREACH(ptr, server_items.head)
 
335
  DLINK_FOREACH(node, server_items.head)
336
336
  {
337
 
    conf = ptr->data;
 
337
    conf = node->data;
338
338
 
339
339
    if (match(name, conf->name))
340
340
      continue;
348
348
    {
349
349
      error = -2;
350
350
 
351
 
      if (!match_conf_password(client_p->localClient->password, conf))
 
351
      if (!match_conf_password(client_p->connection->password, conf))
352
352
        return -2;
353
353
 
354
354
      if (!EmptyString(conf->certfp))
376
376
        v6 = (struct sockaddr_in6 *)&server_conf->addr;
377
377
 
378
378
        if (IN6_IS_ADDR_UNSPECIFIED(&v6->sin6_addr))
379
 
          memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
 
379
          memcpy(&server_conf->addr, &client_p->connection->ip, sizeof(struct irc_ssaddr));
380
380
        break;
381
381
      case AF_INET:
382
382
        v4 = (struct sockaddr_in *)&server_conf->addr;
383
383
 
384
384
        if (v4->sin_addr.s_addr == INADDR_NONE)
385
 
          memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
 
385
          memcpy(&server_conf->addr, &client_p->connection->ip, sizeof(struct irc_ssaddr));
386
386
        break;
387
387
    }
388
388
  }
418
418
 * output       - NONE
419
419
 * side effects - delete given capability from ones known.
420
420
 */
421
 
int
 
421
void
422
422
delete_capability(const char *capab_name)
423
423
{
424
 
  dlink_node *ptr = NULL, *ptr_next = NULL;
 
424
  dlink_node *node = NULL, *node_next = NULL;
425
425
 
426
 
  DLINK_FOREACH_SAFE(ptr, ptr_next, cap_list.head)
 
426
  DLINK_FOREACH_SAFE(node, node_next, cap_list.head)
427
427
  {
428
 
    struct Capability *cap = ptr->data;
 
428
    struct Capability *cap = node->data;
429
429
 
430
430
    if (cap->cap)
431
431
    {
432
432
      if (!irccmp(cap->name, capab_name))
433
433
      {
434
434
        default_server_capabs &= ~(cap->cap);
435
 
        dlinkDelete(ptr, &cap_list);
 
435
        dlinkDelete(node, &cap_list);
436
436
        MyFree(cap->name);
437
437
        MyFree(cap);
438
438
      }
439
439
    }
440
440
  }
441
 
 
442
 
  return 0;
443
441
}
444
442
 
445
443
/*
452
450
unsigned int
453
451
find_capability(const char *capab)
454
452
{
455
 
  const dlink_node *ptr = NULL;
 
453
  const dlink_node *node = NULL;
456
454
 
457
 
  DLINK_FOREACH(ptr, cap_list.head)
 
455
  DLINK_FOREACH(node, cap_list.head)
458
456
  {
459
 
    const struct Capability *cap = ptr->data;
 
457
    const struct Capability *cap = node->data;
460
458
 
461
459
    if (cap->cap && !irccmp(cap->name, capab))
462
460
      return cap->cap;
477
475
send_capabilities(struct Client *client_p, int cap_can_send)
478
476
{
479
477
  char buf[IRCD_BUFSIZE] = "";
480
 
  const dlink_node *ptr = NULL;
 
478
  const dlink_node *node = NULL;
481
479
 
482
 
  DLINK_FOREACH(ptr, cap_list.head)
 
480
  DLINK_FOREACH(node, cap_list.head)
483
481
  {
484
 
    const struct Capability *cap = ptr->data;
 
482
    const struct Capability *cap = node->data;
485
483
 
486
484
    if (cap->cap & (cap_can_send|default_server_capabs))
487
485
    {
488
486
      strlcat(buf, cap->name, sizeof(buf));
489
 
      if (ptr->next)
 
487
      if (node->next)
490
488
        strlcat(buf, " ", sizeof(buf));
491
489
    }
492
490
  }
505
503
show_capabilities(const struct Client *target_p)
506
504
{
507
505
  static char msgbuf[IRCD_BUFSIZE] = "";
508
 
  const dlink_node *ptr = NULL;
 
506
  const dlink_node *node = NULL;
509
507
 
510
508
  strlcpy(msgbuf, "TS", sizeof(msgbuf));
511
509
 
512
 
  DLINK_FOREACH(ptr, cap_list.head)
 
510
  DLINK_FOREACH(node, cap_list.head)
513
511
  {
514
 
    const struct Capability *cap = ptr->data;
 
512
    const struct Capability *cap = node->data;
515
513
 
516
514
    if (!IsCapable(target_p, cap->cap))
517
515
      continue;
572
570
  /* Make sure conf is useful */
573
571
  assert(conf);
574
572
 
575
 
  getnameinfo((struct sockaddr *)&conf->addr, conf->addr.ss_len,
 
573
  getnameinfo((const struct sockaddr *)&conf->addr, conf->addr.ss_len,
576
574
              buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
577
575
  ilog(LOG_TYPE_IRCD, "Connect to %s[%s] @%s", conf->name, conf->host,
578
576
       buf);
622
620
  strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
623
621
 
624
622
  /* create a socket for the server connection */
625
 
  if (comm_open(&client_p->localClient->fd, conf->addr.ss.ss_family, SOCK_STREAM, 0, NULL) < 0)
 
623
  if (comm_open(&client_p->connection->fd, conf->addr.ss.ss_family, SOCK_STREAM, 0, NULL) < 0)
626
624
  {
627
625
    /* Eek, failure to create the socket */
628
626
    report_error(L_ALL, "opening stream socket to %s: %s", conf->name, errno);
633
631
  }
634
632
 
635
633
  /* servernames are always guaranteed under HOSTLEN chars */
636
 
  fd_note(&client_p->localClient->fd, "Server: %s", conf->name);
 
634
  fd_note(&client_p->connection->fd, "Server: %s", conf->name);
637
635
 
638
636
  /* Attach config entries to client here rather than in
639
637
   * serv_connect_callback(). This to avoid null pointer references.
641
639
  if (!attach_connect_block(client_p, conf->name, conf->host))
642
640
  {
643
641
    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
644
 
                         "Host %s is not enabled for connecting: no connect{} block",
 
642
                         "Host %s is not enabled for connecting: no connect {} block",
645
643
                         conf->name);
646
644
    if (by && IsClient(by) && !MyClient(by))
647
 
      sendto_one_notice(by, &me, ":Connect to host %s failed.", client_p->name);
 
645
      sendto_one_notice(by, &me, ":Connect to host %s failed: no connect {} block", client_p->name);
648
646
 
649
647
    SetDead(client_p);
650
648
    exit_client(client_p, "Connection failed");
665
663
    strlcpy(client_p->serv->by, "AutoConn.", sizeof(client_p->serv->by));
666
664
 
667
665
  SetConnecting(client_p);
668
 
  client_p->localClient->aftype = conf->aftype;
 
666
  client_p->connection->aftype = conf->aftype;
669
667
 
670
668
  /* Now, initiate the connection */
671
669
  /* XXX assume that a non 0 type means a specific bind address
682
680
        ipn.ss.ss_family = AF_INET;
683
681
        ipn.ss_port = 0;
684
682
        memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
685
 
        comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
 
683
        comm_connect_tcp(&client_p->connection->fd, conf->host, conf->port,
686
684
                         (struct sockaddr *)&ipn, ipn.ss_len,
687
685
                         serv_connect_callback, client_p, conf->aftype,
688
686
                         CONNECTTIMEOUT);
694
692
        ipn.ss.ss_family = AF_INET;
695
693
        ipn.ss_port = 0;
696
694
        memcpy(&ipn, &ConfigServerInfo.ip, sizeof(struct irc_ssaddr));
697
 
        comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
 
695
        comm_connect_tcp(&client_p->connection->fd, conf->host, conf->port,
698
696
                         (struct sockaddr *)&ipn, ipn.ss_len,
699
697
                         serv_connect_callback, client_p, conf->aftype,
700
698
                         CONNECTTIMEOUT);
701
699
      }
702
700
      else
703
 
        comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
 
701
        comm_connect_tcp(&client_p->connection->fd, conf->host, conf->port,
704
702
                         NULL, 0, serv_connect_callback, client_p, conf->aftype,
705
703
                         CONNECTTIMEOUT);
706
704
      break;
719
717
          memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
720
718
          ipn.ss.ss_family = AF_INET6;
721
719
          ipn.ss_port = 0;
722
 
          comm_connect_tcp(&client_p->localClient->fd,
 
720
          comm_connect_tcp(&client_p->connection->fd,
723
721
                           conf->host, conf->port,
724
722
                           (struct sockaddr *)&ipn, ipn.ss_len,
725
723
                           serv_connect_callback, client_p,
730
728
          memcpy(&ipn, &ConfigServerInfo.ip6, sizeof(struct irc_ssaddr));
731
729
          ipn.ss.ss_family = AF_INET6;
732
730
          ipn.ss_port = 0;
733
 
          comm_connect_tcp(&client_p->localClient->fd,
 
731
          comm_connect_tcp(&client_p->connection->fd,
734
732
                           conf->host, conf->port,
735
733
                           (struct sockaddr *)&ipn, ipn.ss_len,
736
734
                           serv_connect_callback, client_p,
737
735
                           conf->aftype, CONNECTTIMEOUT);
738
736
        }
739
737
        else
740
 
          comm_connect_tcp(&client_p->localClient->fd,
 
738
          comm_connect_tcp(&client_p->connection->fd,
741
739
                           conf->host, conf->port,
742
740
                           NULL, 0, serv_connect_callback, client_p,
743
741
                           conf->aftype, CONNECTTIMEOUT);
753
751
{
754
752
  struct MaskItem *conf = NULL;
755
753
 
756
 
  conf = find_conf_name(&client_p->localClient->confs,
 
754
  conf = find_conf_name(&client_p->connection->confs,
757
755
                        client_p->name, CONF_SERVER);
758
756
  if (conf == NULL)
759
757
  {
790
788
 
791
789
  /* don't move to serv_list yet -- we haven't sent a burst! */
792
790
  /* If we get here, we're ok, so lets start reading some data */
793
 
  comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, read_packet, client_p, 0);
 
791
  comm_setselect(&client_p->connection->fd, COMM_SELECT_READ, read_packet, client_p, 0);
794
792
}
795
793
 
796
794
static void
800
798
  X509 *cert = NULL;
801
799
  int ret = 0;
802
800
 
803
 
  if ((ret = SSL_connect(client_p->localClient->fd.ssl)) <= 0)
 
801
  if ((ret = SSL_connect(client_p->connection->fd.ssl)) <= 0)
804
802
  {
805
 
    switch (SSL_get_error(client_p->localClient->fd.ssl, ret))
 
803
    if ((CurrentTime - client_p->connection->firsttime) > CONNECTTIMEOUT)
 
804
    {
 
805
      exit_client(client_p, "Timeout during SSL handshake");
 
806
      return;
 
807
    }
 
808
 
 
809
    switch (SSL_get_error(client_p->connection->fd.ssl, ret))
806
810
    {
807
811
      case SSL_ERROR_WANT_WRITE:
808
 
        comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE,
809
 
                       ssl_server_handshake, client_p, 0);
 
812
        comm_setselect(&client_p->connection->fd, COMM_SELECT_WRITE,
 
813
                       ssl_server_handshake, client_p, CONNECTTIMEOUT);
810
814
        return;
811
815
      case SSL_ERROR_WANT_READ:
812
 
        comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ,
813
 
                       ssl_server_handshake, client_p, 0);
 
816
        comm_setselect(&client_p->connection->fd, COMM_SELECT_READ,
 
817
                       ssl_server_handshake, client_p, CONNECTTIMEOUT);
814
818
        return;
815
819
      default:
816
820
      {
824
828
    }
825
829
  }
826
830
 
827
 
  if ((cert = SSL_get_peer_certificate(client_p->localClient->fd.ssl)))
 
831
  comm_settimeout(&client_p->connection->fd, 0, NULL, NULL);
 
832
 
 
833
  if ((cert = SSL_get_peer_certificate(client_p->connection->fd.ssl)))
828
834
  {
829
 
    int res = SSL_get_verify_result(client_p->localClient->fd.ssl);
 
835
    int res = SSL_get_verify_result(client_p->connection->fd.ssl);
830
836
    char buf[EVP_MAX_MD_SIZE * 2 + 1] = "";
831
837
    unsigned char md[EVP_MAX_MD_SIZE] = "";
832
838
 
854
860
static void
855
861
ssl_connect_init(struct Client *client_p, struct MaskItem *conf, fde_t *fd)
856
862
{
857
 
  if ((client_p->localClient->fd.ssl = SSL_new(ConfigServerInfo.client_ctx)) == NULL)
 
863
  if ((client_p->connection->fd.ssl = SSL_new(ConfigServerInfo.client_ctx)) == NULL)
858
864
  {
859
865
    ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
860
866
         ERR_error_string(ERR_get_error(), NULL));
866
872
  SSL_set_fd(fd->ssl, fd->fd);
867
873
 
868
874
  if (!EmptyString(conf->cipher_list))
869
 
    SSL_set_cipher_list(client_p->localClient->fd.ssl, conf->cipher_list);
 
875
    SSL_set_cipher_list(client_p->connection->fd.ssl, conf->cipher_list);
870
876
 
871
877
  ssl_server_handshake(NULL, client_p);
872
878
}
888
894
 
889
895
  /* First, make sure it's a real client! */
890
896
  assert(client_p);
891
 
  assert(&client_p->localClient->fd == fd);
 
897
  assert(&client_p->connection->fd == fd);
892
898
 
893
899
  /* Next, for backward purposes, record the ip of the server */
894
 
  memcpy(&client_p->localClient->ip, &fd->connect.hostaddr,
 
900
  memcpy(&client_p->connection->ip, &fd->connect.hostaddr,
895
901
         sizeof(struct irc_ssaddr));
896
902
 
897
903
  /* Check the status */
922
928
 
923
929
  /* COMM_OK, so continue the connection procedure */
924
930
  /* Get the C/N lines */
925
 
  conf = find_conf_name(&client_p->localClient->confs,
 
931
  conf = find_conf_name(&client_p->connection->confs,
926
932
                        client_p->name, CONF_SERVER);
927
933
  if (conf == NULL)
928
934
  {