Logo Search packages:      
Sourcecode: rageircd version File versions  Download package

identity.c

/*
 * RageIRCd: an advanced Internet Relay Chat daemon (ircd).
 * (C) 2000-2005 the RageIRCd Development Team, all rights reserved.
 *
 * This software is free, licensed under the General Public License.
 * Please refer to doc/LICENSE and doc/README for further details.
 *
 * $Id: identity.c,v 1.15.2.1 2004/12/07 03:05:12 pneumatus Exp $
 */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "h.h"

static aClient *servid_table[MAX_SERVID + 1];
static unsigned long last_local_userid;
static unsigned long userids_inuse;

char int6_to_base64_map[] = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
      'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
      'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
      'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '}'
};

char base64_to_int6_map[] =
{
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
      -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
      25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
      -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
      51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, 63, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static inline char *int_to_base64(unsigned int val)
{
      static char b64buf[IDLEN]; /* No +1, we aren't including a prefix */
      unsigned int i = IDLEN - 1;

      b64buf[i] = '\0';
      do {
            b64buf[--i] = int6_to_base64_map[val & 63];
      } while (val >>= 6);

      return (b64buf + i);
}

static inline unsigned int base64_to_int(char *b64)
{
      unsigned int v = base64_to_int6_map[(unsigned char)*b64++];

      while (*b64 != '\0') {
            v <<= 6;
            v += base64_to_int6_map[(unsigned char)*b64++];
      }

      return v;
}

static inline unsigned short hash_id(unsigned short id)
{
      return (id % ID_MAP_SIZE);
}

static aClient *find_by_userid(aClient *sptr, unsigned short id)
{
      unsigned short idval = hash_id(id);
      aClient *cptr;

      for (cptr = sptr->serv->userid[idval]; cptr != NULL; cptr = cptr->idhnext) {
            if (USERID_PART(cptr->id.id) == id) {
                  return cptr;
            }
      }

      return NULL;
}

aClient *find_by_base64_id(char *b64)
{
      unsigned int id = base64_to_int(b64 + 1); /* Skip prefix */
      aClient *cptr, *sptr;
      unsigned short idval;
      unsigned short servid = SERVID_PART(id), userid;

      if (servid > MAX_SERVID || (sptr = servid_table[servid]) == NULL) {
            sendto_realops_lev(DEBUG_LEV, "Got idmsg for user on unknown servid %u",
                  servid);
            return NULL;
      }

      userid = USERID_PART(id);
      idval = hash_id(userid);

      for (cptr = sptr->serv->userid[idval]; cptr != NULL; cptr = cptr->idhnext) {
            if (USERID_PART(cptr->id.id) == userid) {
                  return cptr;
            }
      }

      return NULL;
}

aClient *find_serv_by_base64_id(char *b64, unsigned long *giveid)
{
      aClient *sptr;
      unsigned int id = base64_to_int(b64 + 1); /* Skip prefix */
      unsigned short servid = SERVID_PART(id);

      if (servid > MAX_SERVID || (sptr = servid_table[servid]) == NULL) {
            return NULL;
      }
      if (giveid != NULL) {
            *giveid = id;
      }

      return sptr;
}

void add_userid_to_serv(aClient *sptr, aClient *cptr)
{
      unsigned short idval = hash_id(USERID_PART(cptr->id.id));
      cptr->idhnext = sptr->serv->userid[idval];
      sptr->serv->userid[idval] = cptr;
}

int del_userid_from_serv(aClient *sptr, aClient *cptr)
{
      unsigned short idval = hash_id(USERID_PART(cptr->id.id));
      aClient *acptr, *prev = NULL;

      for (acptr = sptr->serv->userid[idval]; acptr != NULL; acptr = acptr->idhnext) {
            if (acptr == cptr) {
                  if (prev != NULL) {
                        prev->idhnext = acptr->idhnext;
                  }
                  else {
                        sptr->serv->userid[idval] = acptr->idhnext;
                  }
                  return 1;
            }
            prev = acptr;
      }

      sendto_realops_lev(DEBUG_LEV, "del_userid_from_serv(%s, %s[%d]) failed!",
            sptr->name, cptr->name, USERID_PART(cptr->id.id));
      ircdlog(LOG_ERROR, "del_userid_from_serv(%s, %s[%d]) failed!",
            sptr->name, cptr->name, USERID_PART(cptr->id.id));

      return 0;
}

void assign_local_userid(aClient *cptr)
{
      ASSERT(userids_inuse != 0xFFFFF);
      ASSERT(USERID_PART(cptr->id.id) == 0xFFFFF);

      do {
            if (++last_local_userid > MAX_USERID) {
                  last_local_userid = MIN_USERID;
            }
      } while (find_by_userid(&me, last_local_userid) != NULL);

      userids_inuse++;
      
      cptr->id.id = MAKE_ID(SERVID_PART(me.id.id), last_local_userid);
      *cptr->id.string = '!'; /* We include the prefix */
      strcpy(&cptr->id.string[1], int_to_base64(cptr->id.id));
      SetSUID(cptr);
      
      add_userid_to_serv(&me, cptr);
}

int free_local_userid(aClient *cptr)
{
      ASSERT(USERID_PART(cptr->id.id) != 0xFFFFF);

      if (!del_userid_from_serv(&me, cptr)) {
            ircdlog(LOG_ERROR, "free_local_userid() couldn't remove userid from local server?");
            return 0;
      }

      userids_inuse--;

      cptr->id.id = 0xFFFFFFFF;
      cptr->id.string[0] = '\0';
      ClearSUID(cptr);

      return 1;
}

int add_base64_serv(aClient *sptr, char *b64)
{
      unsigned int idval = base64_to_int(b64 + 1); /* Skip prefix */

      if (USERID_PART(idval) || servid_table[SERVID_PART(idval)] != NULL) {
            return 0;
      }

      strncpyzt(sptr->id.string, b64, IDLEN + 1);
      sptr->id.id = idval;
      SetSUID(sptr);

      servid_table[SERVID_PART(idval)] = sptr;
      add_userid_to_serv(sptr, sptr);

      return 1;
}

void del_base64_serv(aClient *sptr)
{
      del_userid_from_serv(sptr, sptr);
      servid_table[SERVID_PART(sptr->id.id)] = NULL;
      ClearSUID(sptr);
}

int init_identity(unsigned short servid)
{
      memset(servid_table, '\0', ((MAX_SERVID + 1) * sizeof(aClient *)));

      last_local_userid = 0;
      userids_inuse = 2;

      if (servid > MAX_SERVID) {
            return 0;
      }

      me.id.id = MAKE_ID(servid, 0);
      *me.id.string = '!'; /* We include the prefix */
      strcpy(&me.id.string[1], int_to_base64(me.id.id));
      SetSUID(&me);

      servid_table[servid] = &me;
      add_userid_to_serv(&me, &me);

      return 1;
}

char *base64enc(unsigned int val)
{
      return int_to_base64(val);
}

unsigned int base64dec(char *b64)
{
      return base64_to_int(b64 + 1); /* base64_to_int() does not account for prefixes */
}

Generated by  Doxygen 1.6.0   Back to index