silc_server_command_send_status_data(SilcServerCommandContext cmd,
SilcCommand command,
SilcCommandStatus status,
- unsigned int arg_type,
+ uint32 arg_type,
unsigned char *arg,
- unsigned int arg_len);
+ uint32 arg_len);
SILC_TASK_CALLBACK(silc_server_command_process_timeout);
/* Server command list. */
SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
+ SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
{ NULL, 0 },
};
#define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
do { \
- unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
+ uint32 _argc = silc_argument_get_arg_num(cmd->args); \
\
SILC_LOG_DEBUG(("Start")); \
\
void silc_server_command_pending(SilcServer server,
SilcCommand reply_cmd,
- unsigned short ident,
+ uint16 ident,
SilcServerPendingDestructor destructor,
SilcCommandCb callback,
void *context)
void silc_server_command_pending_del(SilcServer server,
SilcCommand reply_cmd,
- unsigned short ident)
+ uint16 ident)
{
SilcServerCommandPending *r;
int silc_server_command_pending_check(SilcServer server,
SilcServerCommandReplyContext ctx,
SilcCommand command,
- unsigned short ident)
+ uint16 ident)
{
SilcServerCommandPending *r;
silc_server_command_send_status_data(SilcServerCommandContext cmd,
SilcCommand command,
SilcCommandStatus status,
- unsigned int arg_type,
+ uint32 arg_type,
unsigned char *arg,
- unsigned int arg_len)
+ uint32 arg_len)
{
SilcBuffer buffer;
static int
silc_server_command_whois_parse(SilcServerCommandContext cmd,
SilcClientID ***client_id,
- unsigned int *client_id_count,
+ uint32 *client_id_count,
char **nickname,
char **server_name,
int *count,
SilcCommand command)
{
unsigned char *tmp;
- unsigned int len;
- unsigned int argc = silc_argument_get_arg_num(cmd->args);
+ uint32 len;
+ uint32 argc = silc_argument_get_arg_num(cmd->args);
int i, k;
/* If client ID is in the command it must be used instead of nickname */
static char
silc_server_command_whois_check(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count)
+ uint32 clients_count)
{
SilcServer server = cmd->server;
int i;
if (!entry->nickname || !entry->username || !entry->userinfo) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
if (!entry->router)
continue;
static void
silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count,
+ uint32 clients_count,
int count)
{
SilcServer server = cmd->server;
SilcBuffer packet, idp, channels;
SilcClientEntry entry;
SilcCommandStatus status;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
char nh[128], uh[128];
unsigned char idle[4], mode[4];
SilcSocketConnection hsock;
strncat(nh, entry->nickname, strlen(entry->nickname));
if (!strchr(entry->nickname, '@')) {
strncat(nh, "@", 1);
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
+ if (entry->servername) {
+ strncat(nh, entry->servername, strlen(entry->servername));
+ } else {
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ strncat(nh, entry->router ? entry->router->server_name :
+ server->server_name, len);
+ }
}
strncat(uh, entry->username, strlen(entry->username));
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL, entry;
SilcClientID **client_id = NULL;
- unsigned int client_id_count = 0;
+ uint32 client_id_count = 0, clients_count = 0;
int i, ret = 0;
/* Protocol dictates that we must always send the received WHOIS request
if (server->server_type == SILC_SERVER && !cmd->pending &&
!server->standalone) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL, entry;
SilcClientID **client_id = NULL;
- unsigned int client_id_count = 0;
+ uint32 client_id_count = 0, clients_count = 0;
int i, ret = 0;
/* Parse the whois request */
int *count)
{
unsigned char *tmp;
- unsigned int len;
+ uint32 len;
tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
if (!tmp) {
static char
silc_server_command_whowas_check(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count)
+ uint32 clients_count)
{
SilcServer server = cmd->server;
int i;
if (!entry->nickname || !entry->username) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
if (!entry->router)
continue;
static void
silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count)
+ uint32 clients_count)
{
SilcServer server = cmd->server;
char *tmp;
SilcBuffer packet, idp;
SilcClientEntry entry = NULL;
SilcCommandStatus status;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
char found = FALSE;
char nh[256], uh[256];
strncat(nh, entry->nickname, strlen(entry->nickname));
if (!strchr(entry->nickname, '@')) {
strncat(nh, "@", 1);
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
+ if (entry->servername) {
+ strncat(nh, entry->servername, strlen(entry->servername));
+ } else {
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ strncat(nh, entry->router ? entry->router->server_name :
+ server->server_name, len);
+ }
}
strncat(uh, entry->username, strlen(entry->username));
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL;
+ uint32 clients_count = 0;
int ret = 0;
/* Protocol dictates that we must always send the received WHOWAS request
if (server->server_type == SILC_SERVER &&
!cmd->pending && !server->standalone) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL;
+ uint32 clients_count = 0;
int ret = 0;
/* Parse the whowas request */
static char
silc_server_command_identify_check(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count)
+ uint32 clients_count)
{
SilcServer server = cmd->server;
int i;
if (!entry->nickname) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
if (!entry->router)
continue;
static void
silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
SilcClientEntry *clients,
- unsigned int clients_count,
+ uint32 clients_count,
int count)
{
SilcServer server = cmd->server;
SilcBuffer packet, idp;
SilcClientEntry entry;
SilcCommandStatus status;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
char nh[256], uh[256];
SilcSocketConnection hsock;
strncat(nh, entry->nickname, strlen(entry->nickname));
if (!strchr(entry->nickname, '@')) {
strncat(nh, "@", 1);
- len = entry->router ? strlen(entry->router->server_name) :
- strlen(server->server_name);
- strncat(nh, entry->router ? entry->router->server_name :
- server->server_name, len);
+ if (entry->servername) {
+ strncat(nh, entry->servername, strlen(entry->servername));
+ } else {
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ strncat(nh, entry->router ? entry->router->server_name :
+ server->server_name, len);
+ }
}
if (!entry->username) {
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL, entry;
SilcClientID **client_id = NULL;
- unsigned int client_id_count = 0;
+ uint32 client_id_count = 0, clients_count = 0;
int i, ret = 0;
/* Protocol dictates that we must always send the received IDENTIFY request
if (server->server_type == SILC_SERVER &&
!cmd->pending && !server->standalone) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
{
SilcServer server = cmd->server;
char *nick = NULL, *server_name = NULL;
- int count = 0, clients_count = 0;
+ int count = 0;
SilcClientEntry *clients = NULL, entry;
SilcClientID **client_id = NULL;
- unsigned int client_id_count = 0;
+ uint32 client_id_count = 0, clients_count = 0;
int i, ret = 0;
/* Parse the IDENTIFY request */
SilcBuffer packet, nidp, oidp;
SilcClientID *new_id;
char *nick;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
goto out;
static void
silc_server_command_list_send_reply(SilcServerCommandContext cmd,
SilcChannelEntry *lch,
- unsigned int lch_count,
+ uint32 lch_count,
SilcChannelEntry *gch,
- unsigned int gch_count)
+ uint32 gch_count)
{
int i;
SilcBuffer packet, idp;
SilcChannelEntry entry;
SilcCommandStatus status;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
char *topic;
unsigned char usercount[4];
- unsigned int users;
+ uint32 users;
for (i = 0; i < lch_count; i++)
if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
SilcServer server = cmd->server;
SilcChannelID *channel_id = NULL;
unsigned char *tmp;
- unsigned int tmp_len;
+ uint32 tmp_len;
SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
- unsigned int lch_count = 0, gch_count = 0;
+ uint32 lch_count = 0, gch_count = 0;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
SilcChannelClientEntry chl;
SilcBuffer packet, idp;
unsigned char *tmp;
- unsigned int argc, tmp_len;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 argc, tmp_len;
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
SilcIDListData idata;
SilcBuffer idp, idp2, packet;
unsigned char *tmp, *add, *del;
- unsigned int len;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 len;
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
SilcSocketConnection sock = cmd->sock;
QuitInternal q;
unsigned char *tmp = NULL;
- unsigned int len = 0;
+ uint32 len = 0;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
SilcClientEntry remote_client;
SilcClientID *client_id;
unsigned char *tmp, *comment;
- unsigned int tmp_len, tmp_len2;
+ uint32 tmp_len, tmp_len2;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
SilcServer server = cmd->server;
SilcBuffer packet, idp;
unsigned char *tmp;
- unsigned int tmp_len;
+ uint32 tmp_len;
char *dest_server, *server_info = NULL, *server_name;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
SilcServerEntry entry = NULL;
SilcServerID *server_id = NULL;
server->server_type == SILC_ROUTER && entry && !entry->server_info) {
/* Send to the server */
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
if (!entry && !cmd->pending && !server->standalone) {
/* Send to the primary router */
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcServerID *id;
- unsigned int len;
+ uint32 len;
unsigned char *tmp;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
SilcChannelEntry channel,
SilcClientID *client_id,
int created,
- unsigned int umode)
+ uint32 umode)
{
SilcSocketConnection sock = cmd->sock;
unsigned char *tmp;
- unsigned int tmp_len, user_count;
+ uint32 tmp_len, user_count;
unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
SilcClientEntry client;
SilcChannelClientEntry chl;
SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
char check[512];
SILC_LOG_DEBUG(("Start"));
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- int tmp_len;
+ uint32 tmp_len;
char *tmp, *channel_name = NULL, *cipher, *hmac;
SilcChannelEntry channel;
- unsigned int umode = 0;
+ uint32 umode = 0;
int created = FALSE;
SilcClientID *client_id;
or joins the client to it). */
if (server->server_type == SILC_SERVER) {
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
SilcServer server = cmd->server;
SilcBuffer packet, idp;
char *motd, *dest_server;
- int motd_len;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 motd_len;
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
entry && !entry->motd) {
/* Send to the server */
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
if (!entry && !cmd->pending && !server->standalone) {
/* Send to the primary router */
SilcBuffer tmpbuf;
- unsigned short old_ident;
+ uint16 old_ident;
old_ident = silc_command_get_ident(cmd->payload);
silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
SilcBuffer packet;
unsigned char *tmp_mask;
- unsigned int mask;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 mask;
+ uint16 ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
goto out;
int silc_server_check_cmode_rights(SilcChannelEntry channel,
SilcChannelClientEntry client,
- unsigned int mode)
+ uint32 mode)
{
int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
SilcBuffer packet, cidp;
unsigned char *tmp, *tmp_id, *tmp_mask;
char *cipher = NULL, *hmac = NULL;
- unsigned int mode_mask, tmp_len, tmp_len2;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 mode_mask, tmp_len, tmp_len2;
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
/* User limit is set on channel */
- unsigned int user_limit;
+ uint32 user_limit;
/* Get user limit */
tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
SilcChannelClientEntry chl;
SilcBuffer packet, idp;
unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
- unsigned int target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
+ uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
int notify = FALSE;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
/* The client tries to claim the founder rights. */
unsigned char *tmp_auth;
- unsigned int tmp_auth_len, auth_len;
+ uint32 tmp_auth_len, auth_len;
void *auth;
if (target_client != client) {
server->server_type == SILC_ROUTER ?
TRUE : FALSE, channel,
target_mask, client->id,
- SILC_ID_CLIENT_LEN,
+ SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
target_client->id,
SILC_ID_CLIENT_LEN);
}
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcBuffer idp;
- unsigned int tmp_len;
+ uint32 tmp_len;
unsigned char *tmp, *comment;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
unsigned char *username, *auth;
- unsigned int tmp_len;
+ uint32 tmp_len;
SilcServerConfigSectionAdminConnection *admin;
SilcIDListData idata = (SilcIDListData)client;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
unsigned char *username, *auth;
- unsigned int tmp_len;
+ uint32 tmp_len;
SilcServerConfigSectionAdminConnection *admin;
SilcIDListData idata = (SilcIDListData)client;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
unsigned char *tmp, *host;
- unsigned int tmp_len;
- unsigned int port = SILC_PORT;
+ uint32 tmp_len;
+ uint32 port = SILC_PORT;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
SilcChannelClientEntry chl;
SilcChannelID *channel_id = NULL;
unsigned char *id, *add, *del;
- unsigned int id_len, tmp_len;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 id_len, tmp_len;
+ uint16 ident = silc_command_get_ident(cmd->payload);
if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
goto out;
SilcServerEntry server_entry;
SilcSocketConnection sock;
unsigned char *tmp;
- unsigned int tmp_len;
+ uint32 tmp_len;
unsigned char *name;
- unsigned int port = SILC_PORT;
+ uint32 port = SILC_PORT;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
SilcChannelID *id = NULL;
SilcChannelEntry channel;
- unsigned int len;
+ uint32 len;
unsigned char *tmp;
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
FALSE : !server->standalone);
}
- silc_free(id);
-
out:
if (id)
silc_free(id);
SilcChannelID *id;
SilcBuffer packet;
unsigned char *channel_id;
- unsigned int channel_id_len;
+ uint32 channel_id_len;
SilcBuffer client_id_list;
SilcBuffer client_mode_list;
unsigned char lc[4];
- unsigned int list_count = 0;
- unsigned short ident = silc_command_get_ident(cmd->payload);
+ uint32 list_count = 0;
+ uint16 ident = silc_command_get_ident(cmd->payload);
SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
out:
silc_server_command_free(cmd);
}
+
+/* Server side of command GETKEY. This fetches the client's public key
+ from the server where to the client is connected. */
+
+SILC_SERVER_CMD_FUNC(getkey)
+{
+ SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+ SilcServer server = cmd->server;
+ SilcBuffer packet;
+ SilcClientEntry client;
+ SilcServerEntry server_entry;
+ SilcClientID *client_id = NULL;
+ SilcServerID *server_id = NULL;
+ SilcIDPayload idp = NULL;
+ uint16 ident = silc_command_get_ident(cmd->payload);
+ unsigned char *tmp;
+ uint32 tmp_len;
+ SilcBuffer pk;
+ SilcIdType id_type;
+
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ if (!tmp) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ idp = silc_id_payload_parse_data(tmp, tmp_len);
+ if (!idp) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+
+ id_type = silc_id_payload_get_type(idp);
+ if (id_type == SILC_ID_CLIENT) {
+ client_id = silc_id_payload_get_id(idp);
+
+ /* If the client is not found from local list there is no chance it
+ would be locally connected client so send the command further. */
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
+
+ if ((!client && !cmd->pending && !server->standalone) ||
+ (client && !client->connection)) {
+ SilcBuffer tmpbuf;
+ uint16 old_ident;
+ SilcSocketConnection dest_sock;
+
+ dest_sock = silc_server_get_client_route(server, NULL, 0,
+ client_id, NULL);
+ if (!dest_sock)
+ goto out;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ silc_server_packet_send(server, dest_sock,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply from router */
+ silc_server_command_pending(server, SILC_COMMAND_GETKEY,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_destructor,
+ silc_server_command_getkey,
+ silc_server_command_dup(cmd));
+ cmd->pending = TRUE;
+
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_buffer_free(tmpbuf);
+ return;
+ }
+
+ if (!client && cmd->pending) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+ goto out;
+ }
+
+ /* The client is locally connected, just get the public key and
+ send it back. */
+ tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
+ pk = silc_buffer_alloc(4 + tmp_len);
+ silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+ silc_buffer_format(pk,
+ SILC_STR_UI_SHORT(tmp_len),
+ SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+ SILC_STR_UI_XNSTRING(tmp, tmp_len),
+ SILC_STR_END);
+ silc_free(tmp);
+
+ } else if (id_type == SILC_ID_SERVER) {
+ server_id = silc_id_payload_get_id(idp);
+
+ /* If the server is not found from local list there is no chance it
+ would be locally connected server so send the command further. */
+ server_entry = silc_idlist_find_server_by_id(server->local_list,
+ server_id, NULL);
+
+ if ((!server_entry && !cmd->pending && !server->standalone) ||
+ (server_entry && !server_entry->connection)) {
+ SilcBuffer tmpbuf;
+ uint16 old_ident;
+
+ old_ident = silc_command_get_ident(cmd->payload);
+ silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+ silc_server_packet_send(server, server->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+
+ /* Reprocess this packet after received reply from router */
+ silc_server_command_pending(server, SILC_COMMAND_GETKEY,
+ silc_command_get_ident(cmd->payload),
+ silc_server_command_destructor,
+ silc_server_command_getkey,
+ silc_server_command_dup(cmd));
+ cmd->pending = TRUE;
+
+ silc_command_set_ident(cmd->payload, old_ident);
+ silc_buffer_free(tmpbuf);
+ return;
+ }
+
+ if (!server_entry && cmd->pending) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+ SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
+ goto out;
+ }
+
+ /* The client is locally connected, just get the public key and
+ send it back. */
+ tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
+ pk = silc_buffer_alloc(4 + tmp_len);
+ silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+ silc_buffer_format(pk,
+ SILC_STR_UI_SHORT(tmp_len),
+ SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+ SILC_STR_UI_XNSTRING(tmp, tmp_len),
+ SILC_STR_END);
+ silc_free(tmp);
+ } else {
+ goto out;
+ }
+
+ tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
+ SILC_STATUS_OK, ident, 2,
+ 2, tmp, tmp_len,
+ 3, pk->data, pk->len);
+ silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
+ packet->data, packet->len, FALSE);
+ silc_buffer_free(packet);
+ silc_buffer_free(pk);
+
+ out:
+ if (idp)
+ silc_id_payload_free(idp);
+ silc_free(client_id);
+ silc_free(server_id);
+ silc_server_command_free(cmd);
+}