Esempio n. 1
0
static SilcBool silc_net_set_sockaddr(TInetAddr *addr, const char *ip_addr,
                                      int port)
{
  /* Check for IPv4 and IPv6 addresses */
  if (ip_addr) {
    if (!silc_net_is_ip(ip_addr)) {
      SILC_LOG_ERROR(("%s is not IP address", ip_addr));
      return FALSE;
    }

    if (silc_net_is_ip4(ip_addr)) {
      /* IPv4 address */
      unsigned char buf[4];
      TUint32 a;

      if (!silc_net_addr2bin(ip_addr, buf, sizeof(buf)))
        return FALSE;

      SILC_GET32_MSB(a, buf);
      addr->SetAddress(a);
      addr->SetPort(port);
    } else {
#ifdef HAVE_IPV6
      SILC_LOG_ERROR(("IPv6 not supported"));
      return FALSE;
#else
      SILC_LOG_ERROR(("Operating System does not support IPv6"));
      return FALSE;
#endif
    }
  } else {
    addr->SetAddress(0);
    addr->SetPort(port);
  }

  return TRUE;
}
Esempio n. 2
0
SilcBool silc_attribute_get_object(SilcAttributePayload payload,
				   void *object, SilcUInt32 object_size)
{
  SilcUInt16 len;
  SilcBool ret = FALSE;

  if (!object || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID)
    return FALSE;

  switch (payload->attribute) {
  case SILC_ATTRIBUTE_USER_INFO:
    {
      SilcVCard vcard = object;
      if (object_size != sizeof(*vcard))
	break;
      if (!silc_vcard_decode(payload->data, payload->data_len, vcard))
	break;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_SERVICE:
    {
      SilcAttributeObjService *service = object;
      SilcBufferStruct buf;
      SilcUInt16 addr_len, signon_len;
      char *addr, *signon;
      int res;
      if (object_size != sizeof(*service))
	break;
      if (payload->data_len < 13)
	break;
      silc_buffer_set(&buf, payload->data, payload->data_len);
      res = silc_buffer_unformat(&buf,
				 SILC_STR_UI_INT(&service->port),
				 SILC_STR_UI16_NSTRING(&addr, &addr_len),
				 SILC_STR_UI_CHAR(&service->status),
				 SILC_STR_UI16_NSTRING(&signon, &signon_len),
				 SILC_STR_UI_INT(&service->idle),
				 SILC_STR_END);
      if (res == -1)
	break;
      memset(service->address, 0, sizeof(service->address));
      memset(service->signon, 0, sizeof(service->signon));
      memcpy(service->address, addr,
	     (addr_len < sizeof(service->address) - 1 ? addr_len :
	      sizeof(service->address) - 1));
      memcpy(service->signon, signon,
	     (signon_len < sizeof(service->signon) - 1 ? signon_len :
	      sizeof(service->signon) - 1));
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_STATUS_MOOD:
  case SILC_ATTRIBUTE_PREFERRED_CONTACT:
    {
      SilcUInt32 *mask = (SilcUInt32 *)object;
      if (object_size != sizeof(SilcUInt32))
	break;
      if (payload->data_len < 4)
	break;
      SILC_GET32_MSB(*mask, payload->data);
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_STATUS_FREETEXT:
  case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
  case SILC_ATTRIBUTE_TIMEZONE:
    {
      char *string = object;
      if (payload->data_len < 2)
	break;
      SILC_GET16_MSB(len, payload->data);
      if (payload->data_len < 2 + len)
	break;
      if (object_size < len)
	break;
      memcpy(string, payload->data + 2, len);
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_STATUS_MESSAGE:
  case SILC_ATTRIBUTE_EXTENSION:
  case SILC_ATTRIBUTE_USER_ICON:
    {
      SilcMime mime = object;
      if (object_size != sizeof(*mime))
	break;
      if (!silc_mime_decode(mime, payload->data, payload->data_len))
	break;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_GEOLOCATION:
    {
      SilcAttributeObjGeo *geo = object;
      SilcBufferStruct buffer;
      int res;
      if (object_size != sizeof(*geo))
	break;
      silc_buffer_set(&buffer, (unsigned char *)payload->data,
		      payload->data_len);
      res = silc_buffer_unformat(&buffer,
				 SILC_STR_UI16_STRING_ALLOC(&geo->longitude),
				 SILC_STR_UI16_STRING_ALLOC(&geo->latitude),
				 SILC_STR_UI16_STRING_ALLOC(&geo->altitude),
				 SILC_STR_UI16_STRING_ALLOC(&geo->accuracy),
				 SILC_STR_END);
      if (res == -1)
	break;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_DEVICE_INFO:
    {
      SilcAttributeObjDevice *dev = object;
      SilcBufferStruct buffer;
      SilcUInt32 type;
      int res;
      if (object_size != sizeof(*dev))
	break;
      silc_buffer_set(&buffer, (unsigned char *)payload->data,
		      payload->data_len);
      res =
	silc_buffer_unformat(&buffer,
			     SILC_STR_UI_INT(&type),
			     SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer),
			     SILC_STR_UI16_STRING_ALLOC(&dev->version),
			     SILC_STR_UI16_STRING_ALLOC(&dev->model),
			     SILC_STR_UI16_STRING_ALLOC(&dev->language),
			     SILC_STR_END);
      if (res == -1)
	break;
      dev->type = type;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_PHONE_NUMBER:
    {
      SilcAttributeObjPN *pn = object;
      SilcBufferStruct buffer;
      SilcUInt32 pn_format;
      int res;
      if (object_size != sizeof(*pn))
	break;
      silc_buffer_set(&buffer, (unsigned char *)payload->data,
		      payload->data_len);
      res =
	silc_buffer_unformat(&buffer,
			     SILC_STR_UI_INT(&pn_format),
			     SILC_STR_UI16_STRING_ALLOC(&pn->number),
			     SILC_STR_END);
      if (res == -1)
	break;
      pn->format = pn_format;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
  case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
    {
      SilcAttributeObjPk *pk = object;
      SilcBufferStruct buffer;
      int res;
      if (object_size != sizeof(*pk))
	break;
      silc_buffer_set(&buffer, (unsigned char *)payload->data,
		      payload->data_len);
      res =
	silc_buffer_unformat(&buffer,
			     SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len),
			     SILC_STR_END);
      if (res == -1 || len > silc_buffer_len(&buffer) - 2)
	break;
      pk->data = silc_memdup(payload->data + 2 + len,
			     payload->data_len - 2 - len);
      pk->data_len = payload->data_len - 2 - len;
      ret = TRUE;
    }
    break;

  case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
  case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
    {
      SilcAttributeObjPk *pk = object;
      if (object_size != sizeof(*pk))
	break;
      pk->type = NULL;
      pk->data = silc_memdup(payload->data, payload->data_len);
      pk->data_len = payload->data_len;
      ret = TRUE;
    }
    break;

  default:
    break;
  }

  return ret;
}
Esempio n. 3
0
int cast5_setup(const unsigned char *key, int keylen, int num_rounds,
		cast5_key *skey)
{
   SilcUInt32 x[4], z[4];
   int y, i;

   if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0)
     return FALSE;

   if (num_rounds == 12 && (keylen / 8) > 10)
     return FALSE;

   if ((keylen / 8) < 5)
     return FALSE;

   if ((keylen / 8) > 16)
     keylen = 128;

   /* load and start the awful looking network */
   for (y = 0; y < (keylen / 8) / 4; y++)
     SILC_GET32_MSB(x[3-y],key+4*y);

   for (i = y = 0; y < 2; y++) {
        z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
        z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
        z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
        z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
        skey->K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)];
        skey->K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)];
        skey->K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)];
        skey->K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)];

        x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
        x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
        x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
        x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
        skey->K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)];
        skey->K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)];
        skey->K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)];
        skey->K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)];

        /* second half */
        z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
        z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
        z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
        z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
        skey->K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)];
        skey->K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)];
        skey->K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)];
        skey->K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)];

        x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
        x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
        x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
        x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
        skey->K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)];
        skey->K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)];
        skey->K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)];
        skey->K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)];
   }

   skey->keylen = keylen / 8;

   return TRUE;
}
Esempio n. 4
0
/* Transform 512-bits */
void  sha256_transform(SilcUInt32 *state, unsigned char *buf)
{
  SilcUInt32 S[8], W[64], t0, t1;
  int i;

  /* copy state into S */
  for (i = 0; i < 8; i++) {
    S[i] = state[i];
  }

  /* copy the state into 512-bits into W[0..15] */
  for (i = 0; i < 16; i++)
    SILC_GET32_MSB(W[i], buf + (4 * i));

  /* fill W[16..63] */
  for (i = 16; i < 64; i++) {
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
  }

  /* Compress */
#define RND(a,b,c,d,e,f,g,h,i,ki)		\
  t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];	\
  t1 = Sigma0(a) + Maj(a, b, c);		\
  d += t0;					\
  h  = t0 + t1;

  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
  RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
  RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
  RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
  RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
  RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
  RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
  RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
  RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);

#undef RND

  /* feedback */
  for (i = 0; i < 8; i++) {
    state[i] = state[i] + S[i];
  }
}
Esempio n. 5
0
static char
silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
{
  SilcServer server = cmd->server;
  unsigned char *id_data, *umodes;
  char *nickname, *username, *realname, *tmp;
  unsigned char *fingerprint;
  SilcID id;
  SilcClientEntry client;
  char global = FALSE;
  char nick[128 + 1], servername[256 + 1], uname[128 + 1];
  SilcUInt32 mode = 0, len, len2, id_len, flen;
  const char *hostname, *ip;

  silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
			      NULL, &hostname, &ip, NULL);

  id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
  nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
  username = silc_argument_get_arg_type(cmd->args, 4, &len);
  realname = silc_argument_get_arg_type(cmd->args, 5, &len);
  if (!id_data || !nickname || !username || !realname)
    return FALSE;

  tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
  if (tmp)
    SILC_GET32_MSB(mode, tmp);

  if (!silc_id_payload_parse_id(id_data, id_len, &id))
    return FALSE;

  fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);

  /* Check if we have this client cached already. */

  client = silc_idlist_find_client_by_id(server->local_list,
					 SILC_ID_GET_ID(id),
					 FALSE, NULL);
  if (!client) {
    client = silc_idlist_find_client_by_id(server->global_list,
					   SILC_ID_GET_ID(id),
					   FALSE, NULL);
    global = TRUE;
  }

  if (!client) {
    /* If router did not find such Client ID in its lists then this must
       be bogus client or some router in the net is buggy. */
    if (server->server_type != SILC_SERVER)
      return FALSE;

    /* Take hostname out of nick string if it includes it. */
    silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
			sizeof(servername));

    /* We don't have that client anywhere, add it. The client is added
       to global list since server didn't have it in the lists so it must be
       global. This will check for valid nickname and username strings. */
    client = silc_idlist_add_client(server->global_list,
				    strdup(nick), username,
				    strdup(realname),
				    silc_id_dup(SILC_ID_GET_ID(id),
						SILC_ID_CLIENT),
				    silc_packet_get_context(cmd->sock),
				    NULL);
    if (!client) {
      SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
      return FALSE;
    }

    client->data.status |=
      (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
    client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
    client->mode = mode;
    client->servername = servername[0] ? strdup(servername) : NULL;

    SILC_LOG_DEBUG(("stat.clients %d->%d", server->stat.clients,
		    server->stat.clients + 1));
    server->stat.clients++;
  } else {
    /* We have the client already, update the data */

    SILC_LOG_DEBUG(("Updating client data"));

    /* Check nickname */
    silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
			sizeof(servername));
    nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
				     128, NULL);
    if (!nickname) {
      SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
		      "from %s",
		      hostname ? hostname : "", nick));
      return FALSE;
    }

    /* Check username */
    silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
    if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
      SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
		      "from %s",
		      hostname ? hostname : "", tmp));
      return FALSE;
    }

    /* Update entry */
    silc_idcache_update_by_context(global ? server->global_list->clients :
				   server->local_list->clients, client, NULL,
				   nickname, TRUE);

    silc_free(client->nickname);
    silc_free(client->username);
    silc_free(client->userinfo);
    silc_free(client->servername);

    client->nickname = strdup(nick);
    client->username = strdup(username);
    client->userinfo = strdup(realname);
    client->servername = servername[0] ? strdup(servername) : NULL;
    client->mode = mode;
    client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
    client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
  }

  /* Save channel list if it was sent to us */
  if (server->server_type == SILC_SERVER) {
    tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
    umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
    if (tmp && umodes) {
      SilcBufferStruct channels_buf, umodes_buf;
      silc_buffer_set(&channels_buf, tmp, len);
      silc_buffer_set(&umodes_buf, umodes, len2);
      silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
				     &umodes_buf);
    } else {
      silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
    }
  }

  if (fingerprint && flen == sizeof(client->data.fingerprint))
    memcpy(client->data.fingerprint, fingerprint, flen);

  /* Take Requested Attributes if set. */
  tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
  if (tmp) {
    silc_free(client->attrs);
    client->attrs = silc_memdup(tmp, len);
    client->attrs_len = len;

    /* Try to take public key from attributes if present and we don't have
       the key already.  Do this only on normal server.  Routers do GETKEY
       for all clients anyway. */
    if (server->server_type != SILC_ROUTER && !client->data.public_key) {
      SilcAttributePayload attr;
      SilcAttributeObjPk pk;
      unsigned char f[SILC_HASH_MAXLEN];
      SilcDList attrs = silc_attribute_payload_parse(tmp, len);

      SILC_LOG_DEBUG(("Take client public key from attributes"));

      if (attrs) {
	silc_dlist_start(attrs);
	while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
	  if (silc_attribute_get_attribute(attr) ==
	      SILC_ATTRIBUTE_USER_PUBLIC_KEY) {

	    if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
	      continue;

	    /* Take only SILC public keys */
	    if (strcmp(pk.type, "silc-rsa")) {
	      silc_free(pk.type);
	      silc_free(pk.data);
	      continue;
	    }

	    /* Verify that the server provided fingerprint matches the key */
	    silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
	    if (memcmp(f, client->data.fingerprint, sizeof(f))) {
	      silc_free(pk.type);
	      silc_free(pk.data);
	      continue;
	    }

	    /* Save the public key. */
	    if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
					    pk.data, pk.data_len,
					    &client->data.public_key)) {
	      silc_free(pk.type);
	      silc_free(pk.data);
	      continue;
	    }

	    SILC_LOG_DEBUG(("Saved client public key from attributes"));

	    /* Add client's public key to repository */
	    if (!silc_server_get_public_key_by_client(server, client, NULL))
	      silc_skr_add_public_key_simple(server->repository,
					     client->data.public_key,
					     SILC_SKR_USAGE_IDENTIFICATION,
					     client, NULL);

	    silc_free(pk.type);
	    silc_free(pk.data);
	    break;
	  }
	}

	silc_attribute_payload_list_free(attrs);
      }
    }
  }

  return TRUE;
}
Esempio n. 6
0
static void silc_buffer_stream_io(SilcStream stream,
				  SilcStreamStatus status,
				  void *context)
{
  SilcBufferStream bs = context;
  SilcBuffer buffer = NULL;
  SilcUInt32 buf_len;
  int ret, len;

  if (bs->closed)
    return;

  if (status == SILC_STREAM_CAN_READ) {
    /* Read data */
    SILC_LOG_DEBUG(("Read data from buffer stream %p", bs));

    while ((ret = silc_stream_read(bs->stream, bs->inbuf->tail,
				   silc_buffer_taillen(bs->inbuf))) > 0) {
      if (!buffer) {
	buffer = silc_buffer_alloc(0);
	if (!buffer)
	  return;
      }

      silc_buffer_pull_tail(bs->inbuf, ret);

      /* Parse the buffer */
      while ((len = silc_buffer_unformat(bs->inbuf,
					 SILC_STR_BUFFER_ALLOC(buffer),
					 SILC_STR_END)) > 0) {
	/* Deliver the buffer */
	SILC_LOG_HEXDUMP(("Received buffer, size %d",
			  silc_buffer_len(buffer)),
			 silc_buffer_data(buffer), silc_buffer_len(buffer));
	bs->receiver(SILC_OK, (SilcStream)bs, buffer, bs->context);
	silc_buffer_pull(bs->inbuf, len);

	buffer = silc_buffer_alloc(0);
	if (!buffer)
	  return;
      }

      if (silc_buffer_len(bs->inbuf) > 0) {
	/* Not complete buffer, read more data */
	buf_len = 4;
	if (silc_buffer_len(bs->inbuf) >= 4) {
	  SILC_GET32_MSB(buf_len, bs->inbuf->data);
	  SILC_LOG_DEBUG(("Incomplete buffer, wait for rest, buffer size %d",
			  buf_len));
	}

	/* Enlarge inbuf if needed */
	if (silc_buffer_taillen(bs->inbuf) < buf_len)
	  silc_buffer_realloc(bs->inbuf, silc_buffer_truelen(bs->inbuf) +
			      buf_len);
	continue;
      }

      /* All data read, read more */
      silc_buffer_reset(bs->inbuf);
    }

    silc_buffer_free(buffer);

    if (ret == 0 || ret == -2) {
      bs->receiver(silc_errno, (SilcStream)bs, NULL, bs->context);
      return;
    }
  } else {
    /* Write any pending data */
    SILC_LOG_DEBUG(("Write pending data to buffer stream %p", bs));

    while (silc_buffer_len(&bs->queue) > 0) {
      ret = silc_stream_write(bs->stream, silc_buffer_data(&bs->queue),
			      silc_buffer_len(&bs->queue));
      if (silc_unlikely(ret == 0))
	return;

      if (silc_unlikely(ret == -2))
	return;

      if (silc_unlikely(ret == -1)) {
	SILC_LOG_DEBUG(("Buffer stream %p would block, send later", bs));
	return;
      }

      /* Wrote data */
      silc_buffer_pull(&bs->queue, ret);
    }

    memset(&bs->queue, 0, sizeof(bs->queue));
    silc_buffer_reset(bs->outbuf);
  }
}