Blame samples/logging_proxy.c

Packit Service 37472d
Packit Service 37472d
/*
Packit Service 37472d
  Logging Sametime Proxy Utility
Packit Service 37472d
  The Meanwhile Project
Packit Service 37472d
Packit Service 37472d
  This is a tool which can act as a proxy between a client and a
Packit Service 37472d
  sametime server, which will log all messages to stdout. It will also
Packit Service 37472d
  munge channel creation messages in order to be able to decrypt any
Packit Service 37472d
  encrypted data sent over a channel, and will log decrypted chunks to
Packit Service 37472d
  stdout as well. This makes reverse-engineering of services much,
Packit Service 37472d
  much easier.
Packit Service 37472d
Packit Service 37472d
  The idea is simple, but the implementation made my head hurt.
Packit Service 37472d
Packit Service 37472d
  Christopher O'Brien <siege@preoccupied.net>
Packit Service 37472d
*/
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#include <netinet/in.h>
Packit Service 37472d
#include <netdb.h>
Packit Service 37472d
#include <stdlib.h>
Packit Service 37472d
#include <stdio.h>
Packit Service 37472d
#include <string.h>
Packit Service 37472d
#include <sys/socket.h>
Packit Service 37472d
#include <unistd.h>
Packit Service 37472d
Packit Service 37472d
#include <glib.h>
Packit Service 37472d
Packit Service 37472d
#include <mw_cipher.h>
Packit Service 37472d
#include <mw_common.h>
Packit Service 37472d
#include <mw_message.h>
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** one side of the proxy (either the client side or the server
Packit Service 37472d
    side). The forward method for one should push data into the socket
Packit Service 37472d
    of the other. */
Packit Service 37472d
struct proxy_side {
Packit Service 37472d
  int sock;
Packit Service 37472d
  GIOChannel *chan;
Packit Service 37472d
  gint chan_io;
Packit Service 37472d
Packit Service 37472d
  guchar *buf;
Packit Service 37472d
  gsize buf_size;
Packit Service 37472d
  gsize buf_recv;
Packit Service 37472d
Packit Service 37472d
  void (*forward)(const guchar *buf, gsize len);
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static struct proxy_side client;  /**< side facing the client */
Packit Service 37472d
static struct proxy_side server;  /**< side facing the server */
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static char *host = NULL;
Packit Service 37472d
static int client_port = 0;
Packit Service 37472d
static int server_port = 0;
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int counter = 0;
Packit Service 37472d
static int listen_sock = 0;
Packit Service 37472d
static GIOChannel *listen_chan = NULL;
Packit Service 37472d
static gint listen_io = 0;
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** given one side, get the other */
Packit Service 37472d
#define OTHER_SIDE(side) \
Packit Service 37472d
  ((side == &client)? &server: &client)
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** encryption state information used in the RC2/40 cipher */
Packit Service 37472d
struct rc2_40enc {
Packit Service 37472d
  guchar outgoing_iv[8];
Packit Service 37472d
  int outgoing_key[64];
Packit Service 37472d
  guchar incoming_iv[8];
Packit Service 37472d
  int incoming_key[64];
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* re-usable rc2 40 stuff */
Packit Service 37472d
static int session_key[64] = {
Packit Service 37472d
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit Service 37472d
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit Service 37472d
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit Service 37472d
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** encryption state information used in the RC2/128 cipher */
Packit Service 37472d
struct rc2_128enc {
Packit Service 37472d
  guchar outgoing_iv[8];
Packit Service 37472d
  guchar incoming_iv[8];
Packit Service 37472d
  int shared_key[64];
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* re-usable rc2 128 stuff */
Packit Service 37472d
static struct mwMpi *private_key;
Packit Service 37472d
static struct mwOpaque public_key;
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** represents a channel. The channel has a left side and a right
Packit Service 37472d
    side. The left side is the creator of the channel. The right side
Packit Service 37472d
    is the target of the channel. Each side has its own encryption
Packit Service 37472d
    state information, so an incoming message from either side can
Packit Service 37472d
    be decrypted, then re-encrypted for the other side. */
Packit Service 37472d
struct channel {
Packit Service 37472d
  guint32 id;
Packit Service 37472d
Packit Service 37472d
  /* login id of creator or NULL if created by client side */
Packit Service 37472d
  char *creator;
Packit Service 37472d
Packit Service 37472d
  /* the offer from the left side */
Packit Service 37472d
  struct mwEncryptOffer offer;
Packit Service 37472d
Packit Service 37472d
  /** the mode of encryption */
Packit Service 37472d
  enum {
Packit Service 37472d
    enc_none = 0,  /**< nothing encrypted */
Packit Service 37472d
    enc_easy,      /**< easy (rc2/40) encryption */
Packit Service 37472d
    enc_hard,      /**< hard (rc2/128) encryption */
Packit Service 37472d
  } enc_mode;
Packit Service 37472d
Packit Service 37472d
  /** encryption data for the left side */
Packit Service 37472d
  union {
Packit Service 37472d
    struct rc2_40enc easy;
Packit Service 37472d
    struct rc2_128enc hard;
Packit Service 37472d
  } left_enc;
Packit Service 37472d
Packit Service 37472d
  /** encryption data for the right side */
Packit Service 37472d
  union {
Packit Service 37472d
    struct rc2_40enc easy;
Packit Service 37472d
    struct rc2_128enc hard;
Packit Service 37472d
  } right_enc;
Packit Service 37472d
Packit Service 37472d
  struct proxy_side *left;   /**< proxy side acting as the left side */
Packit Service 37472d
  struct proxy_side *right;  /**< proxy side acting as the right side */
Packit Service 37472d
};
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* collection of channels */
Packit Service 37472d
static GHashTable *channels;
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define PUT_CHANNEL(chan) \
Packit Service 37472d
  g_hash_table_insert(channels, GUINT_TO_POINTER((chan)->id), (chan))
Packit Service 37472d
Packit Service 37472d
#define GET_CHANNEL(id) \
Packit Service 37472d
  g_hash_table_lookup(channels, GUINT_TO_POINTER(id))
Packit Service 37472d
Packit Service 37472d
#define REMOVE_CHANNEL(id) \
Packit Service 37472d
  g_hash_table_remove(channels, GUINT_TO_POINTER(id))
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** print a message to stdout and use hexdump to print a data chunk */
Packit Service 37472d
static void hexdump_vprintf(const guchar *buf, gsize len,
Packit Service 37472d
			    const char *txt, va_list args) {
Packit Service 37472d
  FILE *fp;
Packit Service 37472d
Packit Service 37472d
  if(txt) {
Packit Service 37472d
    fputc('\n', stdout);
Packit Service 37472d
    vfprintf(stdout, txt, args);
Packit Service 37472d
    fputc('\n', stdout);
Packit Service 37472d
  }
Packit Service 37472d
  fflush(stdout);
Packit Service 37472d
Packit Service 37472d
  fp = popen("hexdump -C", "w");
Packit Service 37472d
  fwrite(buf, len, 1, fp);
Packit Service 37472d
  fflush(fp);
Packit Service 37472d
  pclose(fp);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** print a message to stdout and use hexdump to print a data chunk */
Packit Service 37472d
static void hexdump_printf(const guchar *buf, gsize len,
Packit Service 37472d
			   const char *txt, ...) {
Packit Service 37472d
  va_list args;
Packit Service 37472d
  va_start(args, txt);
Packit Service 37472d
  hexdump_vprintf(buf, len, txt, args);
Packit Service 37472d
  va_end(args);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** serialize a message for sending */
Packit Service 37472d
static void put_msg(struct mwMessage *msg, struct mwOpaque *o) {
Packit Service 37472d
  struct mwPutBuffer *b;
Packit Service 37472d
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  mwMessage_put(b, msg);
Packit Service 37472d
  mwPutBuffer_finalize(o, b);
Packit Service 37472d
  
Packit Service 37472d
  b = mwPutBuffer_new();
Packit Service 37472d
  mwOpaque_put(b, o);
Packit Service 37472d
  mwOpaque_clear(o);
Packit Service 37472d
  mwPutBuffer_finalize(o, b);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void key_copy(int to[64], int from[64]) {
Packit Service 37472d
  int i = 64;
Packit Service 37472d
  while(i--) to[i] = from[i];
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* we don't want to be redirected away from the proxy, so eat any
Packit Service 37472d
   redirect messages from the server and respond with a login cont */
Packit Service 37472d
static void munge_redir() {
Packit Service 37472d
  struct mwMessage *msg;
Packit Service 37472d
  struct mwOpaque o = { 0, 0 };
Packit Service 37472d
Packit Service 37472d
  msg = mwMessage_new(mwMessage_LOGIN_CONTINUE);
Packit Service 37472d
  put_msg(msg, &o);
Packit Service 37472d
  mwMessage_free(msg);
Packit Service 37472d
Packit Service 37472d
  server.forward(o.data, o.len);
Packit Service 37472d
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* handle receipt of channel create messages from either side,
Packit Service 37472d
   recording the offered ciphers, and munging it to instead include
Packit Service 37472d
   our own key as applicable, then sending it on */
Packit Service 37472d
static void munge_create(struct proxy_side *side,
Packit Service 37472d
			 struct mwMsgChannelCreate *msg) {
Packit Service 37472d
Packit Service 37472d
  struct mwOpaque o = { 0, 0 };
Packit Service 37472d
  GList *l;
Packit Service 37472d
  struct channel *c;
Packit Service 37472d
Packit Service 37472d
  /* create a new channel on the side */
Packit Service 37472d
  c = g_new0(struct channel, 1);
Packit Service 37472d
  c->id = msg->channel;
Packit Service 37472d
  c->left = side;
Packit Service 37472d
  c->right = OTHER_SIDE(side);
Packit Service 37472d
Packit Service 37472d
  if(msg->creator_flag) {
Packit Service 37472d
    c->creator = g_strdup(msg->creator.login_id);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  /* record the mode and encryption items */
Packit Service 37472d
  c->offer.mode = msg->encrypt.mode;
Packit Service 37472d
  c->offer.items = msg->encrypt.items;
Packit Service 37472d
  c->offer.extra = msg->encrypt.extra;
Packit Service 37472d
  c->offer.flag = msg->encrypt.flag;
Packit Service 37472d
Packit Service 37472d
  PUT_CHANNEL(c);
Packit Service 37472d
Packit Service 37472d
  /* replace the encryption items with our own as applicable */
Packit Service 37472d
  if(msg->encrypt.items) {
Packit Service 37472d
    l = msg->encrypt.items;
Packit Service 37472d
    msg->encrypt.items = NULL; /* steal them */
Packit Service 37472d
Packit Service 37472d
    for(; l; l = l->next) {
Packit Service 37472d
      struct mwEncryptItem *i1, *i2;
Packit Service 37472d
Packit Service 37472d
      /* the original we've stolen */
Packit Service 37472d
      i1 = l->data;
Packit Service 37472d
Packit Service 37472d
      /* the munged replacement */
Packit Service 37472d
      i2 = g_new0(struct mwEncryptItem, 1);
Packit Service 37472d
      i2->id = i1->id;
Packit Service 37472d
Packit Service 37472d
      switch(i1->id) {
Packit Service 37472d
      case mwCipher_RC2_128:
Packit Service 37472d
	printf("munging an offered RC2/128\n");
Packit Service 37472d
	mwOpaque_clone(&i2->info, &public_key);
Packit Service 37472d
	break;
Packit Service 37472d
      case mwCipher_RC2_40:
Packit Service 37472d
	printf("munging an offered RC2/40\n");
Packit Service 37472d
      default:
Packit Service 37472d
	;
Packit Service 37472d
      }
Packit Service 37472d
Packit Service 37472d
      msg->encrypt.items = g_list_append(msg->encrypt.items, i2);
Packit Service 37472d
    }
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  put_msg(MW_MESSAGE(msg), &o);
Packit Service 37472d
  side->forward(o.data, o.len);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* find an enc item by id in a list of items */
Packit Service 37472d
struct mwEncryptItem *find_item(GList *items, guint16 id) {
Packit Service 37472d
  GList *ltmp;
Packit Service 37472d
  for(ltmp = items; ltmp; ltmp = ltmp->next) {
Packit Service 37472d
    struct mwEncryptItem *i = ltmp->data;
Packit Service 37472d
    if(i->id == id) return i;
Packit Service 37472d
  }
Packit Service 37472d
  return NULL;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* handle acceptance of a channel */
Packit Service 37472d
static void munge_accept(struct proxy_side *side,
Packit Service 37472d
			 struct mwMsgChannelAccept *msg) {
Packit Service 37472d
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
  struct channel *chan;
Packit Service 37472d
  struct mwEncryptItem *item;
Packit Service 37472d
Packit Service 37472d
  chan = GET_CHANNEL(msg->head.channel);
Packit Service 37472d
  item = msg->encrypt.item;
Packit Service 37472d
Packit Service 37472d
  if(! item) {
Packit Service 37472d
    /* cut to the chase */
Packit Service 37472d
    put_msg(MW_MESSAGE(msg), &o);
Packit Service 37472d
    side->forward(o.data, o.len);
Packit Service 37472d
    mwOpaque_clear(&o);
Packit Service 37472d
    return;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  /* init right-side encryption with our enc and accepted enc */
Packit Service 37472d
  switch(item->id) {
Packit Service 37472d
  case mwCipher_RC2_128: {
Packit Service 37472d
    struct mwMpi *remote, *shared;
Packit Service 37472d
    struct mwOpaque k;
Packit Service 37472d
Packit Service 37472d
    remote = mwMpi_new();
Packit Service 37472d
    shared = mwMpi_new();
Packit Service 37472d
Packit Service 37472d
    printf("right side accepted RC2/128\n");
Packit Service 37472d
Packit Service 37472d
    mwMpi_import(remote, &item->info);
Packit Service 37472d
    mwMpi_calculateDHShared(shared, remote, private_key);
Packit Service 37472d
    mwMpi_export(shared, &k);
Packit Service 37472d
Packit Service 37472d
    chan->enc_mode = enc_hard;
Packit Service 37472d
Packit Service 37472d
    mwIV_init(chan->right_enc.hard.outgoing_iv);
Packit Service 37472d
    mwIV_init(chan->right_enc.hard.incoming_iv);
Packit Service 37472d
    mwKeyExpand(chan->right_enc.hard.shared_key, k.data+(k.len-16), 16);
Packit Service 37472d
Packit Service 37472d
    mwMpi_free(remote);
Packit Service 37472d
    mwMpi_free(shared);
Packit Service 37472d
    mwOpaque_clear(&k);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  case mwCipher_RC2_40: {
Packit Service 37472d
    char *who;
Packit Service 37472d
    
Packit Service 37472d
    printf("right side accepted RC2/40\n");
Packit Service 37472d
Packit Service 37472d
    chan->enc_mode = enc_easy;
Packit Service 37472d
Packit Service 37472d
    mwIV_init(chan->right_enc.easy.outgoing_iv);
Packit Service 37472d
    mwIV_init(chan->right_enc.easy.incoming_iv);
Packit Service 37472d
Packit Service 37472d
    if(msg->acceptor_flag) {
Packit Service 37472d
      who = msg->acceptor.login_id;
Packit Service 37472d
      printf("right side is the server\n");
Packit Service 37472d
      printf("server is %s\n", who);
Packit Service 37472d
      mwKeyExpand(chan->right_enc.easy.incoming_key, (guchar *) who, 5);
Packit Service 37472d
      key_copy(chan->right_enc.easy.outgoing_key, session_key);
Packit Service 37472d
Packit Service 37472d
    } else {
Packit Service 37472d
      who = chan->creator;
Packit Service 37472d
      printf("right side is the client\n");
Packit Service 37472d
      printf("server is %s\n", who);
Packit Service 37472d
      key_copy(chan->right_enc.easy.incoming_key, session_key);
Packit Service 37472d
      mwKeyExpand(chan->right_enc.easy.outgoing_key, (guchar *) who, 5);
Packit Service 37472d
    }
Packit Service 37472d
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  default:
Packit Service 37472d
    chan->enc_mode = enc_none;
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  /* init left-side encryption with offered enc and our enc, munge accept */
Packit Service 37472d
  switch(item->id) {
Packit Service 37472d
  case mwCipher_RC2_128: {
Packit Service 37472d
    struct mwMpi *remote, *shared;
Packit Service 37472d
    struct mwOpaque k;
Packit Service 37472d
    struct mwEncryptItem *offered;
Packit Service 37472d
    
Packit Service 37472d
    remote = mwMpi_new();
Packit Service 37472d
    shared = mwMpi_new();
Packit Service 37472d
Packit Service 37472d
    printf("accepting left side with RC2/128\n");
Packit Service 37472d
    
Packit Service 37472d
    offered = find_item(chan->offer.items, mwCipher_RC2_128);
Packit Service 37472d
    mwMpi_import(remote, &offered->info);
Packit Service 37472d
    mwMpi_calculateDHShared(shared, remote, private_key);
Packit Service 37472d
    mwMpi_export(shared, &k);
Packit Service 37472d
    
Packit Service 37472d
    mwIV_init(chan->left_enc.hard.outgoing_iv);
Packit Service 37472d
    mwIV_init(chan->left_enc.hard.incoming_iv);
Packit Service 37472d
    mwKeyExpand(chan->left_enc.hard.shared_key, k.data+(k.len-16), 16);
Packit Service 37472d
Packit Service 37472d
    mwMpi_free(remote);
Packit Service 37472d
    mwMpi_free(shared);
Packit Service 37472d
    mwOpaque_clear(&k);
Packit Service 37472d
    
Packit Service 37472d
    /* munge accept with out public key */
Packit Service 37472d
    mwOpaque_clear(&item->info);
Packit Service 37472d
    mwOpaque_clone(&item->info, &public_key);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  case mwCipher_RC2_40:
Packit Service 37472d
    printf("accepting left side with RC2/40\n");
Packit Service 37472d
Packit Service 37472d
    mwIV_init(chan->left_enc.easy.outgoing_iv);
Packit Service 37472d
    mwIV_init(chan->left_enc.easy.incoming_iv);
Packit Service 37472d
Packit Service 37472d
    key_copy(chan->left_enc.easy.outgoing_key,
Packit Service 37472d
	     chan->right_enc.easy.incoming_key);
Packit Service 37472d
Packit Service 37472d
    key_copy(chan->left_enc.easy.incoming_key,
Packit Service 37472d
	     chan->right_enc.easy.outgoing_key);
Packit Service 37472d
    break;
Packit Service 37472d
    
Packit Service 37472d
  default:
Packit Service 37472d
    ;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  put_msg(MW_MESSAGE(msg), &o);
Packit Service 37472d
  side->forward(o.data, o.len);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void dec(struct channel *chan, struct proxy_side *side,
Packit Service 37472d
		struct mwOpaque *to, struct mwOpaque *from) {
Packit Service 37472d
  
Packit Service 37472d
  switch(chan->enc_mode) {
Packit Service 37472d
  case enc_easy: {
Packit Service 37472d
    if(chan->left == side) {
Packit Service 37472d
      /* left side decrypt */
Packit Service 37472d
      mwDecryptExpanded(chan->left_enc.easy.incoming_key,
Packit Service 37472d
			chan->left_enc.easy.incoming_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    } else {
Packit Service 37472d
      /* right side decrypt */
Packit Service 37472d
      mwDecryptExpanded(chan->right_enc.easy.incoming_key,
Packit Service 37472d
			chan->right_enc.easy.incoming_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    }
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  case enc_hard: {
Packit Service 37472d
    if(chan->left == side) {
Packit Service 37472d
      /* left side decrypt */
Packit Service 37472d
      mwDecryptExpanded(chan->left_enc.hard.shared_key,
Packit Service 37472d
			chan->left_enc.hard.incoming_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    } else {
Packit Service 37472d
      /* right side decrypt */
Packit Service 37472d
      mwDecryptExpanded(chan->right_enc.hard.shared_key,
Packit Service 37472d
			chan->right_enc.hard.incoming_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    }
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void enc(struct channel *chan, struct proxy_side *side,
Packit Service 37472d
		struct mwOpaque *to, struct mwOpaque *from) {
Packit Service 37472d
Packit Service 37472d
  switch(chan->enc_mode) {
Packit Service 37472d
  case enc_easy: {
Packit Service 37472d
    if(chan->left == side) {
Packit Service 37472d
      /* left side encrypt */
Packit Service 37472d
      mwEncryptExpanded(chan->left_enc.easy.outgoing_key,
Packit Service 37472d
			chan->left_enc.easy.outgoing_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    } else {
Packit Service 37472d
      /* right side encrypt */
Packit Service 37472d
      mwEncryptExpanded(chan->right_enc.easy.outgoing_key,
Packit Service 37472d
			chan->right_enc.easy.outgoing_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    }
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  case enc_hard: {
Packit Service 37472d
    if(chan->left == side) {
Packit Service 37472d
      /* left side encrypt */
Packit Service 37472d
      mwEncryptExpanded(chan->left_enc.hard.shared_key,
Packit Service 37472d
			chan->left_enc.hard.outgoing_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    } else {
Packit Service 37472d
      /* right side encrypt */
Packit Service 37472d
      mwEncryptExpanded(chan->right_enc.hard.shared_key,
Packit Service 37472d
			chan->right_enc.hard.outgoing_iv,
Packit Service 37472d
			from, to);
Packit Service 37472d
    }
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void munge_channel(struct proxy_side *side,
Packit Service 37472d
			  struct mwMsgChannelSend *msg) {
Packit Service 37472d
Packit Service 37472d
  struct mwOpaque o = {0,0};
Packit Service 37472d
Packit Service 37472d
  if(msg->head.options & mwMessageOption_ENCRYPT) {
Packit Service 37472d
    struct mwOpaque d = {0,0};
Packit Service 37472d
    struct channel *chan;
Packit Service 37472d
Packit Service 37472d
    chan = GET_CHANNEL(msg->head.channel);
Packit Service 37472d
Packit Service 37472d
    /* decrypt from side */
Packit Service 37472d
    dec(chan, side, &d, &msg->data);
Packit Service 37472d
Packit Service 37472d
    /* display */
Packit Service 37472d
    hexdump_printf(d.data, d.len, "decrypted channel message data:",
Packit Service 37472d
		   msg->type);
Packit Service 37472d
Packit Service 37472d
    /* encrypt to other side */
Packit Service 37472d
    mwOpaque_clear(&msg->data);
Packit Service 37472d
    enc(chan, OTHER_SIDE(side), &msg->data, &d);
Packit Service 37472d
    mwOpaque_clear(&d);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  /* send to other side */
Packit Service 37472d
  put_msg(MW_MESSAGE(msg), &o);
Packit Service 37472d
  side->forward(o.data, o.len);
Packit Service 37472d
  mwOpaque_clear(&o);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* handle destruction of a channel */
Packit Service 37472d
static void handle_destroy(struct proxy_side *side,
Packit Service 37472d
			   struct mwMsgChannelDestroy *msg) {
Packit Service 37472d
Packit Service 37472d
  struct channel *chan;
Packit Service 37472d
  GList *l;
Packit Service 37472d
Packit Service 37472d
  chan = GET_CHANNEL(msg->head.channel);
Packit Service 37472d
  REMOVE_CHANNEL(msg->head.channel);
Packit Service 37472d
Packit Service 37472d
  if(! chan) return;
Packit Service 37472d
Packit Service 37472d
  for(l = chan->offer.items; l; l = l->next) {
Packit Service 37472d
    mwEncryptItem_free(l->data);
Packit Service 37472d
  }
Packit Service 37472d
  g_list_free(chan->offer.items);
Packit Service 37472d
  chan->offer.items = NULL;
Packit Service 37472d
Packit Service 37472d
  g_free(chan->creator);
Packit Service 37472d
  chan->creator = NULL;
Packit Service 37472d
Packit Service 37472d
  g_free(chan);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void forward(struct proxy_side *to,
Packit Service 37472d
		    struct mwOpaque *data) {
Packit Service 37472d
Packit Service 37472d
  struct mwPutBuffer *pb = mwPutBuffer_new();
Packit Service 37472d
  struct mwOpaque po = { 0, 0 };
Packit Service 37472d
Packit Service 37472d
  mwOpaque_put(pb, data);
Packit Service 37472d
  mwPutBuffer_finalize(&po, pb);
Packit Service 37472d
  to->forward(po.data, po.len);
Packit Service 37472d
  mwOpaque_clear(&po);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/* handle messages from either side */
Packit Service 37472d
static void side_process(struct proxy_side *s, const guchar *buf, gsize len) {
Packit Service 37472d
  struct mwOpaque o = { .len = len, .data = (guchar *) buf };
Packit Service 37472d
  struct mwGetBuffer *b;
Packit Service 37472d
  guint16 type;
Packit Service 37472d
Packit Service 37472d
  if(! len) return;
Packit Service 37472d
Packit Service 37472d
  if(s == &server) {
Packit Service 37472d
    hexdump_printf(buf, len, "server -> client");
Packit Service 37472d
  } else {
Packit Service 37472d
    hexdump_printf(buf, len, "client -> server");
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  b = mwGetBuffer_wrap(&o);
Packit Service 37472d
  type = guint16_peek(b);
Packit Service 37472d
Packit Service 37472d
  switch(type) {
Packit Service 37472d
  case mwMessage_LOGIN_ACK: {
Packit Service 37472d
    struct mwMsgLoginAck *msg = (struct mwMsgLoginAck *) mwMessage_get(b);
Packit Service 37472d
    printf("client is %s\n", msg->login.login_id);
Packit Service 37472d
    mwKeyExpand(session_key, (guchar *) msg->login.login_id, 5);
Packit Service 37472d
    mwMessage_free(MW_MESSAGE(msg));
Packit Service 37472d
    forward(s, &o);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  case mwMessage_LOGIN_REDIRECT: {
Packit Service 37472d
    munge_redir();
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  case mwMessage_CHANNEL_CREATE: {
Packit Service 37472d
    struct mwMessage *msg = mwMessage_get(b);
Packit Service 37472d
    munge_create(s, (struct mwMsgChannelCreate *) msg);
Packit Service 37472d
    mwMessage_free(msg);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  case mwMessage_CHANNEL_ACCEPT: {
Packit Service 37472d
    struct mwMessage *msg = mwMessage_get(b);
Packit Service 37472d
    munge_accept(s, (struct mwMsgChannelAccept *) msg);
Packit Service 37472d
    mwMessage_free(msg);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  case mwMessage_CHANNEL_DESTROY: {
Packit Service 37472d
    struct mwMessage *msg = mwMessage_get(b);
Packit Service 37472d
    handle_destroy(s, (struct mwMsgChannelDestroy *) msg);
Packit Service 37472d
    mwMessage_free(msg);
Packit Service 37472d
    forward(s, &o);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  case mwMessage_CHANNEL_SEND: {
Packit Service 37472d
    struct mwMessage *msg = mwMessage_get(b);
Packit Service 37472d
    munge_channel(s, (struct mwMsgChannelSend *) msg);
Packit Service 37472d
    mwMessage_free(msg);
Packit Service 37472d
    break;
Packit Service 37472d
  }
Packit Service 37472d
    
Packit Service 37472d
  default:
Packit Service 37472d
    forward(s, &o);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  mwGetBuffer_free(b);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** clean up a proxy side's inner buffer */
Packit Service 37472d
static void side_buf_free(struct proxy_side *s) {
Packit Service 37472d
  g_free(s->buf);
Packit Service 37472d
  s->buf = NULL;
Packit Service 37472d
  s->buf_size = 0;
Packit Service 37472d
  s->buf_recv = 0;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
#define ADVANCE(b, n, count) { b += count; n -= count; }
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** handle input to complete an existing buffer */
Packit Service 37472d
static gsize side_recv_cont(struct proxy_side *s, const guchar *b, gsize n) {
Packit Service 37472d
Packit Service 37472d
  gsize x = s->buf_size - s->buf_recv;
Packit Service 37472d
Packit Service 37472d
  if(n < x) {
Packit Service 37472d
    memcpy(s->buf+s->buf_recv, b, n);
Packit Service 37472d
    s->buf_recv += n;
Packit Service 37472d
    return 0;
Packit Service 37472d
    
Packit Service 37472d
  } else {
Packit Service 37472d
    memcpy(s->buf+s->buf_recv, b, x);
Packit Service 37472d
    ADVANCE(b, n, x);
Packit Service 37472d
    
Packit Service 37472d
    if(s->buf_size == 4) {
Packit Service 37472d
      struct mwOpaque o = { .len = 4, .data = s->buf };
Packit Service 37472d
      struct mwGetBuffer *gb = mwGetBuffer_wrap(&o);
Packit Service 37472d
      x = guint32_peek(gb);
Packit Service 37472d
      mwGetBuffer_free(gb);
Packit Service 37472d
Packit Service 37472d
      if(n < x) {
Packit Service 37472d
	guchar *t;
Packit Service 37472d
	x += 4;
Packit Service 37472d
	t = (guchar *) g_malloc(x);
Packit Service 37472d
	memcpy(t, s->buf, 4);
Packit Service 37472d
	memcpy(t+4, b, n);
Packit Service 37472d
	
Packit Service 37472d
	side_buf_free(s);
Packit Service 37472d
	
Packit Service 37472d
	s->buf = t;
Packit Service 37472d
	s->buf_size = x;
Packit Service 37472d
	s->buf_recv = n + 4;
Packit Service 37472d
	return 0;
Packit Service 37472d
	
Packit Service 37472d
      } else {
Packit Service 37472d
	side_buf_free(s);
Packit Service 37472d
	side_process(s, b, x);
Packit Service 37472d
	ADVANCE(b, n, x);
Packit Service 37472d
      }
Packit Service 37472d
      
Packit Service 37472d
    } else {
Packit Service 37472d
      side_process(s, s->buf+4, s->buf_size-4);
Packit Service 37472d
      side_buf_free(s);
Packit Service 37472d
    }
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  return n;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** handle input when there's nothing previously buffered */
Packit Service 37472d
static gsize side_recv_empty(struct proxy_side *s, const guchar *b, gsize n) {
Packit Service 37472d
  struct mwOpaque o = { .len = n, .data = (guchar *) b };
Packit Service 37472d
  struct mwGetBuffer *gb;
Packit Service 37472d
  gsize x;
Packit Service 37472d
Packit Service 37472d
  if(n < 4) {
Packit Service 37472d
    s->buf = (guchar *) g_malloc0(4);
Packit Service 37472d
    memcpy(s->buf, b, n);
Packit Service 37472d
    s->buf_size = 4;
Packit Service 37472d
    s->buf_recv = n;
Packit Service 37472d
    return 0;
Packit Service 37472d
  }
Packit Service 37472d
  
Packit Service 37472d
  gb = mwGetBuffer_wrap(&o);
Packit Service 37472d
  x = guint32_peek(gb);
Packit Service 37472d
  mwGetBuffer_free(gb);
Packit Service 37472d
  if(! x) return n - 4;
Packit Service 37472d
Packit Service 37472d
  if(n < (x + 4)) {
Packit Service 37472d
Packit Service 37472d
    x += 4;
Packit Service 37472d
    s->buf = (guchar *) g_malloc(x);
Packit Service 37472d
    memcpy(s->buf, b, n);
Packit Service 37472d
    s->buf_size = x;
Packit Service 37472d
    s->buf_recv = n;
Packit Service 37472d
    return 0;
Packit Service 37472d
    
Packit Service 37472d
  } else {
Packit Service 37472d
    ADVANCE(b, n, 4);
Packit Service 37472d
    side_process(s, b, x);
Packit Service 37472d
    ADVANCE(b, n, x);
Packit Service 37472d
Packit Service 37472d
    return n;
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** handle input in chunks */
Packit Service 37472d
static gsize side_recv(struct proxy_side *s, const guchar *b, gsize n) {
Packit Service 37472d
Packit Service 37472d
  if(n && (s->buf_size == 0) && (*b & 0x80)) {
Packit Service 37472d
    ADVANCE(b, n, 1);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(n == 0) {
Packit Service 37472d
    return 0;
Packit Service 37472d
Packit Service 37472d
  } else if(s->buf_size > 0) {
Packit Service 37472d
    return side_recv_cont(s, b, n);
Packit Service 37472d
Packit Service 37472d
  } else {
Packit Service 37472d
    return side_recv_empty(s, b, n);
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** handle input */
Packit Service 37472d
static void feed_buf(struct proxy_side *side, const guchar *buf, gsize n) {
Packit Service 37472d
  guchar *b = (guchar *) buf;
Packit Service 37472d
  gsize remain = 0;
Packit Service 37472d
  
Packit Service 37472d
  g_return_if_fail(side != NULL);
Packit Service 37472d
Packit Service 37472d
  while(n > 0) {
Packit Service 37472d
    remain = side_recv(side, b, n);
Packit Service 37472d
    b += (n - remain);
Packit Service 37472d
    n = remain;
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static int read_recv(struct proxy_side *side) {
Packit Service 37472d
  guchar buf[2048];
Packit Service 37472d
  int len;
Packit Service 37472d
Packit Service 37472d
  len = read(side->sock, buf, 2048);
Packit Service 37472d
  if(len > 0) feed_buf(side, buf, (gsize) len);
Packit Service 37472d
Packit Service 37472d
  return len;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void init_listen();
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void side_done(struct proxy_side *side) {
Packit Service 37472d
  if(side->sock) {
Packit Service 37472d
    g_source_remove(side->chan_io);
Packit Service 37472d
    close(side->sock);
Packit Service 37472d
    side->sock = 0;
Packit Service 37472d
    side->chan = NULL;
Packit Service 37472d
    side->chan_io = 0;
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void done() {
Packit Service 37472d
  printf("closing connection\n");
Packit Service 37472d
Packit Service 37472d
  side_done(&client);
Packit Service 37472d
  side_done(&server);
Packit Service 37472d
Packit Service 37472d
  if(counter--) {
Packit Service 37472d
    init_listen();
Packit Service 37472d
  } else {
Packit Service 37472d
    exit(0);
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static gboolean read_cb(GIOChannel *chan,
Packit Service 37472d
			GIOCondition cond,
Packit Service 37472d
			gpointer data) {
Packit Service 37472d
Packit Service 37472d
  struct proxy_side *side = data;
Packit Service 37472d
  int ret = 0;
Packit Service 37472d
Packit Service 37472d
  if(cond & G_IO_IN) {
Packit Service 37472d
    ret = read_recv(side);
Packit Service 37472d
    if(ret > 0) return TRUE;
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  done();
Packit Service 37472d
  
Packit Service 37472d
  return FALSE;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void client_cb(const guchar *buf, gsize len) {
Packit Service 37472d
  if(server.sock) write(server.sock, buf, len);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** setup the client */
Packit Service 37472d
static void init_client(int sock) {
Packit Service 37472d
Packit Service 37472d
  client.forward = client_cb;
Packit Service 37472d
  client.sock = sock;
Packit Service 37472d
  client.chan = g_io_channel_unix_new(sock);
Packit Service 37472d
  client.chan_io = g_io_add_watch(client.chan, G_IO_IN | G_IO_ERR | G_IO_HUP,
Packit Service 37472d
				  read_cb, &client);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void server_cb(const guchar *buf, gsize len) {
Packit Service 37472d
  if(client.sock) write(client.sock, buf, len);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** generate a private/public DH keypair for internal (re)use */
Packit Service 37472d
static void init_rc2_128() {
Packit Service 37472d
  struct mwMpi *public;
Packit Service 37472d
Packit Service 37472d
  private_key = mwMpi_new();
Packit Service 37472d
  public = mwMpi_new();
Packit Service 37472d
Packit Service 37472d
  mwMpi_randDHKeypair(private_key, public);
Packit Service 37472d
  mwMpi_export(public, &public_key);
Packit Service 37472d
Packit Service 37472d
  mwMpi_free(public);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** address lookup used by init_sock */
Packit Service 37472d
static void init_sockaddr(struct sockaddr_in *addr,
Packit Service 37472d
			  const char *host, int port) {
Packit Service 37472d
Packit Service 37472d
  struct hostent *hostinfo;
Packit Service 37472d
Packit Service 37472d
  addr->sin_family = AF_INET;
Packit Service 37472d
  addr->sin_port = htons (port);
Packit Service 37472d
  hostinfo = gethostbyname(host);
Packit Service 37472d
  if(hostinfo == NULL) {
Packit Service 37472d
    fprintf(stderr, "Unknown host %s.\n", host);
Packit Service 37472d
    exit(1);
Packit Service 37472d
  }
Packit Service 37472d
  addr->sin_addr = *(struct in_addr *) hostinfo->h_addr;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
/** connect to server on host:port */
Packit Service 37472d
static void init_server() {
Packit Service 37472d
  struct sockaddr_in srvrname;
Packit Service 37472d
  int sock;
Packit Service 37472d
Packit Service 37472d
  printf("connecting to %s:%i\n", host, server_port);
Packit Service 37472d
Packit Service 37472d
  sock = socket(PF_INET, SOCK_STREAM, 0);
Packit Service 37472d
  if(sock < 0) {
Packit Service 37472d
    fprintf(stderr, "socket failure");
Packit Service 37472d
    exit(1);
Packit Service 37472d
  }
Packit Service 37472d
  
Packit Service 37472d
  init_sockaddr(&srvrname, host, server_port);
Packit Service 37472d
  connect(sock, (struct sockaddr *)&srvrname, sizeof(srvrname));
Packit Service 37472d
Packit Service 37472d
  server.forward = server_cb;
Packit Service 37472d
  server.sock = sock;
Packit Service 37472d
  server.chan = g_io_channel_unix_new(sock);
Packit Service 37472d
  server.chan_io = g_io_add_watch(server.chan, G_IO_IN | G_IO_ERR | G_IO_HUP,
Packit Service 37472d
				  read_cb, &server);
Packit Service 37472d
Packit Service 37472d
  printf("connected to %s:%i\n", host, server_port);
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static gboolean listen_cb(GIOChannel *chan,
Packit Service 37472d
			  GIOCondition cond,
Packit Service 37472d
			  gpointer data) {
Packit Service 37472d
Packit Service 37472d
  struct sockaddr_in rem;
Packit Service 37472d
  guint len = sizeof(rem);
Packit Service 37472d
  int sock;
Packit Service 37472d
  
Packit Service 37472d
  printf("got connection\n");
Packit Service 37472d
Packit Service 37472d
  sock = accept(listen_sock, (struct sockaddr *) &rem, &len;;
Packit Service 37472d
  /* g_assert(sock > 0); */
Packit Service 37472d
Packit Service 37472d
  init_server();
Packit Service 37472d
  init_client(sock);
Packit Service 37472d
Packit Service 37472d
  listen_io = 0;
Packit Service 37472d
Packit Service 37472d
  return FALSE;
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
static void init_listen() {
Packit Service 37472d
  if(! listen_sock) {
Packit Service 37472d
    struct sockaddr_in sin;
Packit Service 37472d
    int sock;
Packit Service 37472d
Packit Service 37472d
    sock = socket(PF_INET, SOCK_STREAM, 0);
Packit Service 37472d
    g_assert(sock >= 0);
Packit Service 37472d
Packit Service 37472d
    memset(&sin, 0, sizeof(struct sockaddr_in));
Packit Service 37472d
    sin.sin_family = PF_INET;
Packit Service 37472d
    sin.sin_port = htons(client_port);
Packit Service 37472d
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
Packit Service 37472d
Packit Service 37472d
    if(bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
Packit Service 37472d
      g_assert_not_reached();
Packit Service 37472d
Packit Service 37472d
    if(listen(sock, 1) < 0)
Packit Service 37472d
      g_assert_not_reached();
Packit Service 37472d
Packit Service 37472d
    listen_sock = sock;
Packit Service 37472d
    listen_chan = g_io_channel_unix_new(sock);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(! listen_io) {
Packit Service 37472d
    listen_io = g_io_add_watch(listen_chan, G_IO_IN | G_IO_ERR | G_IO_HUP,
Packit Service 37472d
			       listen_cb, NULL);
Packit Service 37472d
    printf("listening on port %i\n", client_port);
Packit Service 37472d
  }
Packit Service 37472d
}
Packit Service 37472d
Packit Service 37472d
Packit Service 37472d
int main(int argc, char *argv[]) {
Packit Service 37472d
Packit Service 37472d
  memset(&client, 0, sizeof(struct proxy_side));
Packit Service 37472d
  memset(&server, 0, sizeof(struct proxy_side));
Packit Service 37472d
Packit Service 37472d
  if(argc > 1) {
Packit Service 37472d
    char *z;
Packit Service 37472d
Packit Service 37472d
    host = argv[1];
Packit Service 37472d
    z = host;
Packit Service 37472d
Packit Service 37472d
    host = strchr(z, ':');
Packit Service 37472d
    if(host) *host++ = '\0';
Packit Service 37472d
    client_port = atoi(z);
Packit Service 37472d
Packit Service 37472d
    z = strchr(host, ':');
Packit Service 37472d
    if(z) *z++ = '\0';
Packit Service 37472d
    server_port = atoi(z);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(argc > 2) {
Packit Service 37472d
    counter = atoi(argv[2]);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  if(!host || !*host || !client_port || !server_port) {
Packit Service 37472d
    fprintf(stderr,
Packit Service 37472d
	    ( " Usage: %s local_port:remote_host:remote_port [n]\n"
Packit Service 37472d
	      " Creates a locally-running sametime proxy which enforces"
Packit Service 37472d
	      " unencrypted channels. Will drop the first n connections\n" ),
Packit Service 37472d
	    argv[0]);
Packit Service 37472d
    exit(1);
Packit Service 37472d
  }
Packit Service 37472d
Packit Service 37472d
  /* @todo create signal handlers to cleanup sockets */
Packit Service 37472d
Packit Service 37472d
  channels = g_hash_table_new(g_direct_hash, g_direct_equal);
Packit Service 37472d
Packit Service 37472d
  init_rc2_128();
Packit Service 37472d
  init_listen();
Packit Service 37472d
Packit Service 37472d
  g_main_loop_run(g_main_loop_new(NULL, FALSE)); 
Packit Service 37472d
  return 0;
Packit Service 37472d
}
Packit Service 37472d