5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "clientlibincludes.h"
23 #include "client_internal.h"
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30 SILC_TASK_CALLBACK(silc_client_rekey_callback);
31 SILC_TASK_CALLBACK(silc_client_rekey_final);
33 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
34 static void silc_client_packet_parse_type(SilcClient client,
35 SilcSocketConnection sock,
36 SilcPacketContext *packet);
37 void silc_client_resolve_auth_method(bool success,
38 SilcProtocolAuthMeth auth_meth,
39 const unsigned char *auth_data,
40 uint32 auth_data_len, void *context);
42 /* Allocates new client object. This has to be done before client may
43 work. After calling this one must call silc_client_init to initialize
44 the client. The `application' is application specific user data pointer
45 and caller must free it. */
47 SilcClient silc_client_alloc(SilcClientOperations *ops,
48 SilcClientParams *params,
50 const char *silc_version)
52 SilcClient new_client;
54 new_client = silc_calloc(1, sizeof(*new_client));
55 new_client->application = application;
56 new_client->ops = ops;
57 new_client->silc_client_version = strdup(silc_version);
58 new_client->params = silc_calloc(1, sizeof(*new_client->params));
61 memcpy(new_client->params, params, sizeof(*params));
63 if (!new_client->params->task_max)
64 new_client->params->task_max = 200;
66 if (!new_client->params->rekey_secs)
67 new_client->params->rekey_secs = 3600;
69 if (!new_client->params->connauth_request_secs)
70 new_client->params->connauth_request_secs = 2;
73 nickname_format[sizeof(new_client->params->nickname_format) - 1] = 0;
78 /* Frees client object and its internals. */
80 void silc_client_free(SilcClient client)
84 silc_rng_free(client->rng);
86 silc_free(client->silc_client_version);
87 silc_free(client->params);
92 /* Initializes the client. This makes all the necessary steps to make
93 the client ready to be run. One must call silc_client_run to run the
94 client. Returns FALSE if error occured, TRUE otherwise. */
96 int silc_client_init(SilcClient client)
98 SILC_LOG_DEBUG(("Initializing client"));
100 /* Initialize hash functions for client to use */
101 silc_hash_alloc("md5", &client->md5hash);
102 silc_hash_alloc("sha1", &client->sha1hash);
104 /* Initialize none cipher */
105 silc_cipher_alloc("none", &client->none_cipher);
107 /* Initialize random number generator */
108 client->rng = silc_rng_alloc();
109 silc_rng_init(client->rng);
110 silc_rng_global_init(client->rng);
112 /* Register protocols */
113 silc_client_protocols_register();
115 /* Initialize the scheduler */
116 client->schedule = silc_schedule_init(client->params->task_max ?
117 client->params->task_max : 200);
118 if (!client->schedule)
124 /* Stops the client. This is called to stop the client and thus to stop
127 void silc_client_stop(SilcClient client)
129 SILC_LOG_DEBUG(("Stopping client"));
131 silc_schedule_stop(client->schedule);
132 silc_schedule_uninit(client->schedule);
134 silc_client_protocols_unregister();
136 SILC_LOG_DEBUG(("Client stopped"));
139 /* Runs the client. This starts the scheduler from the utility library.
140 When this functions returns the execution of the appliation is over. */
142 void silc_client_run(SilcClient client)
144 SILC_LOG_DEBUG(("Running client"));
146 /* Start the scheduler, the heart of the SILC client. When this returns
147 the program will be terminated. */
148 silc_schedule(client->schedule);
151 static void silc_client_entry_destructor(SilcIDCache cache,
152 SilcIDCacheEntry entry)
154 silc_free(entry->name);
157 /* Allocates and adds new connection to the client. This adds the allocated
158 connection to the connection table and returns a pointer to it. A client
159 can have multiple connections to multiple servers. Every connection must
160 be added to the client using this function. User data `context' may
161 be sent as argument. This function is normally used only if the
162 application performed the connecting outside the library. The library
163 however may use this internally. */
165 SilcClientConnection silc_client_add_connection(SilcClient client,
170 SilcClientConnection conn;
173 conn = silc_calloc(1, sizeof(*conn));
175 /* Initialize ID caches */
176 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
177 silc_client_entry_destructor);
178 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
179 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
180 conn->client = client;
181 conn->remote_host = strdup(hostname);
182 conn->remote_port = port;
183 conn->context = context;
184 conn->pending_commands = silc_dlist_init();
186 /* Add the connection to connections table */
187 for (i = 0; i < client->conns_count; i++)
188 if (client->conns && !client->conns[i]) {
189 client->conns[i] = conn;
193 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
194 * (client->conns_count + 1));
195 client->conns[client->conns_count] = conn;
196 client->conns_count++;
201 /* Removes connection from client. Frees all memory. */
203 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
207 for (i = 0; i < client->conns_count; i++)
208 if (client->conns[i] == conn) {
209 if (conn->pending_commands)
210 silc_dlist_uninit(conn->pending_commands);
212 client->conns[i] = NULL;
216 /* Adds listener socket to the listener sockets table. This function is
217 used to add socket objects that are listeners to the client. This should
218 not be used to add other connection objects. */
220 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
224 if (!client->sockets) {
225 client->sockets = silc_calloc(1, sizeof(*client->sockets));
226 client->sockets[0] = silc_socket_dup(sock);
227 client->sockets_count = 1;
231 for (i = 0; i < client->sockets_count; i++) {
232 if (client->sockets[i] == NULL) {
233 client->sockets[i] = silc_socket_dup(sock);
238 client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
239 (client->sockets_count + 1));
240 client->sockets[client->sockets_count] = silc_socket_dup(sock);
241 client->sockets_count++;
244 /* Deletes listener socket from the listener sockets table. */
246 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
250 if (!client->sockets)
253 for (i = 0; i < client->sockets_count; i++) {
254 if (client->sockets[i] == sock) {
255 silc_socket_free(sock);
256 client->sockets[i] = NULL;
263 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
267 /* XXX In the future we should give up this non-blocking connect all
268 together and use threads instead. */
269 /* Create connection to server asynchronously */
270 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
274 /* Register task that will receive the async connect and will
276 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
277 silc_client_connect_to_server_start,
280 SILC_TASK_PRI_NORMAL);
281 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
288 /* Connects to remote server. This is the main routine used to connect
289 to SILC server. Returns -1 on error and the created socket otherwise.
290 The `context' is user context that is saved into the SilcClientConnection
291 that is created after the connection is created. Note that application
292 may handle the connecting process outside the library. If this is the
293 case then this function is not used at all. When the connecting is
294 done the `connect' client operation is called. */
296 int silc_client_connect_to_server(SilcClient client, int port,
297 char *host, void *context)
299 SilcClientInternalConnectContext *ctx;
300 SilcClientConnection conn;
303 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
306 conn = silc_client_add_connection(client, host, port, context);
308 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
309 "Connecting to port %d of server %s", port, host);
311 /* Allocate internal context for connection process. This is
312 needed as we are doing async connecting. */
313 ctx = silc_calloc(1, sizeof(*ctx));
314 ctx->client = client;
316 ctx->host = strdup(host);
320 /* Do the actual connecting process */
321 sock = silc_client_connect_to_server_internal(ctx);
323 silc_client_del_connection(client, conn);
327 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
328 key material between client and server. This function can be called
329 directly if application is performing its own connecting and does not
330 use the connecting provided by this library. This function is normally
331 used only if the application performed the connecting outside the library.
332 The library however may use this internally. */
334 bool silc_client_start_key_exchange(SilcClient client,
335 SilcClientConnection conn,
338 SilcProtocol protocol;
339 SilcClientKEInternalContext *proto_ctx;
342 /* Allocate new socket connection object */
343 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
345 /* Sometimes when doing quick reconnects the new socket may be same as
346 the old one and there might be pending stuff for the old socket.
347 If new one is same then those pending sutff might cause problems.
348 Make sure they do not do that. */
349 silc_schedule_task_del_by_fd(client->schedule, fd);
351 conn->nickname = strdup(client->username);
352 conn->sock->hostname = conn->remote_host;
353 conn->sock->ip = strdup(conn->remote_host);
354 conn->sock->port = conn->remote_port;
356 /* Allocate internal Key Exchange context. This is sent to the
357 protocol as context. */
358 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
359 proto_ctx->client = (void *)client;
360 proto_ctx->sock = silc_socket_dup(conn->sock);
361 proto_ctx->rng = client->rng;
362 proto_ctx->responder = FALSE;
363 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
364 proto_ctx->verify = silc_client_protocol_ke_verify_key;
366 /* Perform key exchange protocol. silc_client_connect_to_server_final
367 will be called after the protocol is finished. */
368 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
369 &protocol, (void *)proto_ctx,
370 silc_client_connect_to_server_second);
372 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
373 "Error: Could not start key exchange protocol");
376 conn->sock->protocol = protocol;
378 /* Register the connection for network input and output. This sets
379 that scheduler will listen for incoming packets for this connection
380 and sets that outgoing packets may be sent to this connection as well.
381 However, this doesn't set the scheduler for outgoing traffic, it will
382 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
383 later when outgoing data is available. */
384 context = (void *)client;
385 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
387 /* Execute the protocol */
388 silc_protocol_execute(protocol, client->schedule, 0, 0);
392 /* Start of the connection to the remote server. This is called after
393 succesful TCP/IP connection has been established to the remote host. */
395 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
397 SilcClientInternalConnectContext *ctx =
398 (SilcClientInternalConnectContext *)context;
399 SilcClient client = ctx->client;
400 SilcClientConnection conn = ctx->conn;
401 int opt, opt_len = sizeof(opt);
403 SILC_LOG_DEBUG(("Start"));
405 /* Check the socket status as it might be in error */
406 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
408 if (ctx->tries < 2) {
409 /* Connection failed but lets try again */
410 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
411 "Could not connect to server %s: %s",
412 ctx->host, strerror(opt));
413 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
414 "Connecting to port %d of server %s resumed",
415 ctx->port, ctx->host);
417 /* Unregister old connection try */
418 silc_schedule_unset_listen_fd(client->schedule, fd);
419 silc_net_close_connection(fd);
420 silc_schedule_task_del(client->schedule, ctx->task);
423 silc_client_connect_to_server_internal(ctx);
426 /* Connection failed and we won't try anymore */
427 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
428 "Could not connect to server %s: %s",
429 ctx->host, strerror(opt));
430 silc_schedule_unset_listen_fd(client->schedule, fd);
431 silc_net_close_connection(fd);
432 silc_schedule_task_del(client->schedule, ctx->task);
435 /* Notify application of failure */
436 client->ops->connect(client, conn, FALSE);
437 silc_client_del_connection(client, conn);
442 silc_schedule_unset_listen_fd(client->schedule, fd);
443 silc_schedule_task_del(client->schedule, ctx->task);
446 if (!silc_client_start_key_exchange(client, conn, fd)) {
447 silc_net_close_connection(fd);
448 client->ops->connect(client, conn, FALSE);
452 /* Second part of the connecting to the server. This executed
453 authentication protocol. */
455 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
457 SilcProtocol protocol = (SilcProtocol)context;
458 SilcClientKEInternalContext *ctx =
459 (SilcClientKEInternalContext *)protocol->context;
460 SilcClient client = (SilcClient)ctx->client;
461 SilcSocketConnection sock = NULL;
462 SilcClientConnAuthInternalContext *proto_ctx;
464 SILC_LOG_DEBUG(("Start"));
466 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
467 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
468 /* Error occured during protocol */
469 SILC_LOG_DEBUG(("Error during KE protocol"));
470 silc_protocol_free(protocol);
471 silc_ske_free_key_material(ctx->keymat);
473 silc_ske_free(ctx->ske);
475 silc_free(ctx->dest_id);
476 ctx->sock->protocol = NULL;
477 silc_socket_free(ctx->sock);
479 /* Notify application of failure */
480 client->ops->connect(client, ctx->sock->user_data, FALSE);
485 /* We now have the key material as the result of the key exchange
486 protocol. Take the key material into use. Free the raw key material
487 as soon as we've set them into use. */
488 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
489 ctx->ske->prop->cipher,
490 ctx->ske->prop->pkcs,
491 ctx->ske->prop->hash,
492 ctx->ske->prop->hmac,
493 ctx->ske->prop->group);
494 silc_ske_free_key_material(ctx->keymat);
496 /* Allocate internal context for the authentication protocol. This
497 is sent as context for the protocol. */
498 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
499 proto_ctx->client = (void *)client;
500 proto_ctx->sock = sock = ctx->sock;
501 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
502 proto_ctx->dest_id_type = ctx->dest_id_type;
503 proto_ctx->dest_id = ctx->dest_id;
505 /* Free old protocol as it is finished now */
506 silc_protocol_free(protocol);
508 silc_packet_context_free(ctx->packet);
510 sock->protocol = NULL;
512 /* Resolve the authentication method to be used in this connection. The
513 completion callback is called after the application has resolved
514 the authentication method. */
515 client->ops->get_auth_method(client, sock->user_data, sock->hostname,
516 sock->port, silc_client_resolve_auth_method,
520 /* Authentication method resolving callback. Application calls this function
521 after we've called the client->ops->get_auth_method client operation
522 to resolve the authentication method. We will continue the executiong
523 of the protocol in this function. */
525 void silc_client_resolve_auth_method(bool success,
526 SilcProtocolAuthMeth auth_meth,
527 const unsigned char *auth_data,
528 uint32 auth_data_len, void *context)
530 SilcClientConnAuthInternalContext *proto_ctx =
531 (SilcClientConnAuthInternalContext *)context;
532 SilcClient client = (SilcClient)proto_ctx->client;
535 auth_meth = SILC_AUTH_NONE;
537 proto_ctx->auth_meth = auth_meth;
539 if (auth_data && auth_data_len) {
540 proto_ctx->auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
541 memcpy(proto_ctx->auth_data, auth_data, auth_data_len);
542 proto_ctx->auth_data_len = auth_data_len;
545 /* Allocate the authenteication protocol and execute it. */
546 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
547 &proto_ctx->sock->protocol, (void *)proto_ctx,
548 silc_client_connect_to_server_final);
550 /* Execute the protocol */
551 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
554 /* Finalizes the connection to the remote SILC server. This is called
555 after authentication protocol has been completed. This send our
556 user information to the server to receive our client ID from
559 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
561 SilcProtocol protocol = (SilcProtocol)context;
562 SilcClientConnAuthInternalContext *ctx =
563 (SilcClientConnAuthInternalContext *)protocol->context;
564 SilcClient client = (SilcClient)ctx->client;
565 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
568 SILC_LOG_DEBUG(("Start"));
570 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
571 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
572 /* Error occured during protocol */
573 SILC_LOG_DEBUG(("Error during authentication protocol"));
574 silc_protocol_free(protocol);
576 silc_free(ctx->auth_data);
578 silc_ske_free(ctx->ske);
580 silc_free(ctx->dest_id);
581 conn->sock->protocol = NULL;
582 silc_socket_free(ctx->sock);
584 /* Notify application of failure */
585 client->ops->connect(client, ctx->sock->user_data, FALSE);
590 /* Send NEW_CLIENT packet to the server. We will become registered
591 to the SILC network after sending this packet and we will receive
592 client ID from the server. */
593 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
594 strlen(client->realname));
595 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
596 silc_buffer_format(packet,
597 SILC_STR_UI_SHORT(strlen(client->username)),
598 SILC_STR_UI_XNSTRING(client->username,
599 strlen(client->username)),
600 SILC_STR_UI_SHORT(strlen(client->realname)),
601 SILC_STR_UI_XNSTRING(client->realname,
602 strlen(client->realname)),
605 /* Send the packet */
606 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
608 packet->data, packet->len, TRUE);
609 silc_buffer_free(packet);
611 /* Save remote ID. */
612 conn->remote_id = ctx->dest_id;
613 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
614 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
616 /* Register re-key timeout */
617 conn->rekey->timeout = client->params->rekey_secs;
618 conn->rekey->context = (void *)client;
619 silc_schedule_task_add(client->schedule, conn->sock->sock,
620 silc_client_rekey_callback,
621 (void *)conn->sock, conn->rekey->timeout, 0,
622 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
624 silc_protocol_free(protocol);
626 silc_free(ctx->auth_data);
628 silc_ske_free(ctx->ske);
629 silc_socket_free(ctx->sock);
631 conn->sock->protocol = NULL;
634 /* Internal routine that sends packet or marks packet to be sent. This
635 is used directly only in special cases. Normal cases should use
636 silc_server_packet_send. Returns < 0 on error. */
638 int silc_client_packet_send_real(SilcClient client,
639 SilcSocketConnection sock,
644 /* If rekey protocol is active we must assure that all packets are
645 sent through packet queue. */
646 if (SILC_CLIENT_IS_REKEY(sock))
649 /* If outbound data is already pending do not force send */
650 if (SILC_IS_OUTBUF_PENDING(sock))
653 /* Send the packet */
654 ret = silc_packet_send(sock, force_send);
658 /* Mark that there is some outgoing data available for this connection.
659 This call sets the connection both for input and output (the input
660 is set always and this call keeps the input setting, actually).
661 Actual data sending is performed by silc_client_packet_process. */
662 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
664 /* Mark to socket that data is pending in outgoing buffer. This flag
665 is needed if new data is added to the buffer before the earlier
666 put data is sent to the network. */
667 SILC_SET_OUTBUF_PENDING(sock);
672 /* Packet processing callback. This is used to send and receive packets
673 from network. This is generic task. */
675 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
677 SilcClient client = (SilcClient)context;
678 SilcSocketConnection sock = NULL;
679 SilcClientConnection conn;
682 SILC_LOG_DEBUG(("Processing packet"));
684 SILC_CLIENT_GET_SOCK(client, fd, sock);
688 conn = (SilcClientConnection)sock->user_data;
691 if (type == SILC_TASK_WRITE) {
692 /* Do not send data to disconnected connection */
693 if (SILC_IS_DISCONNECTED(sock))
696 if (sock->outbuf->data - sock->outbuf->head)
697 silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
699 ret = silc_packet_send(sock, TRUE);
701 /* If returned -2 could not write to connection now, will do
710 /* The packet has been sent and now it is time to set the connection
711 back to only for input. When there is again some outgoing data
712 available for this connection it will be set for output as well.
713 This call clears the output setting and sets it only for input. */
714 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
715 SILC_UNSET_OUTBUF_PENDING(sock);
717 silc_buffer_clear(sock->outbuf);
721 /* Packet receiving */
722 if (type == SILC_TASK_READ) {
723 /* Read data from network */
724 ret = silc_packet_receive(sock);
730 SILC_LOG_DEBUG(("Read EOF"));
732 /* If connection is disconnecting already we will finally
733 close the connection */
734 if (SILC_IS_DISCONNECTING(sock)) {
735 if (sock == conn->sock)
736 client->ops->disconnect(client, conn);
737 silc_client_close_connection(client, sock, conn);
741 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
742 if (sock == conn->sock)
743 client->ops->disconnect(client, conn);
744 silc_client_close_connection(client, sock, conn);
748 /* Process the packet. This will call the parser that will then
749 decrypt and parse the packet. */
750 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
751 silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
752 silc_client_packet_parse, client);
754 silc_packet_receive_process(sock, NULL, NULL,
755 silc_client_packet_parse, client);
759 /* Callback function that the silc_packet_decrypt will call to make the
760 decision whether the packet is normal or special packet. We will
761 return TRUE if it is normal and FALSE if it is special */
763 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
765 SilcPacketContext *packet,
769 /* Packet is normal packet, if:
771 1) packet is private message packet and does not have private key set
772 2) is other packet than channel message packet
774 all other packets are special packets
777 if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
778 (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
781 if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
787 /* Parses whole packet, received earlier. */
789 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
791 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
792 SilcClient client = (SilcClient)parse_ctx->context;
793 SilcPacketContext *packet = parse_ctx->packet;
794 SilcBuffer buffer = packet->buffer;
795 SilcSocketConnection sock = parse_ctx->sock;
796 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
799 SILC_LOG_DEBUG(("Start"));
801 /* Decrypt the received packet */
802 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
803 ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
805 silc_client_packet_decrypt_check, parse_ctx);
807 ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
808 silc_client_packet_decrypt_check, parse_ctx);
814 /* Parse the packet. Packet type is returned. */
815 ret = silc_packet_parse(packet);
817 /* Parse the packet header in special way as this is "special"
819 ret = silc_packet_parse_special(packet);
822 if (ret == SILC_PACKET_NONE)
825 /* Parse the incoming packet type */
826 silc_client_packet_parse_type(client, sock, packet);
829 /* silc_buffer_clear(sock->inbuf); */
830 silc_packet_context_free(packet);
831 silc_free(parse_ctx);
834 /* Parser callback called by silc_packet_receive_process. Thie merely
835 registers timeout that will handle the actual parsing when appropriate. */
837 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
839 SilcClient client = (SilcClient)parser_context->context;
841 /* Parse the packet */
842 silc_schedule_task_add(client->schedule, parser_context->sock->sock,
843 silc_client_packet_parse_real,
844 (void *)parser_context, 0, 1,
846 SILC_TASK_PRI_NORMAL);
849 /* Parses the packet type and calls what ever routines the packet type
850 requires. This is done for all incoming packets. */
852 void silc_client_packet_parse_type(SilcClient client,
853 SilcSocketConnection sock,
854 SilcPacketContext *packet)
856 SilcBuffer buffer = packet->buffer;
857 SilcPacketType type = packet->type;
859 SILC_LOG_DEBUG(("Parsing packet type %d", type));
861 /* Parse the packet type */
863 case SILC_PACKET_DISCONNECT:
864 silc_client_disconnected_by_server(client, sock, buffer);
866 case SILC_PACKET_SUCCESS:
868 * Success received for something. For now we can have only
869 * one protocol for connection executing at once hence this
870 * success message is for whatever protocol is executing currently.
873 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
875 case SILC_PACKET_FAILURE:
877 * Failure received for some protocol. Set the protocol state to
878 * error and call the protocol callback. This fill cause error on
879 * protocol and it will call the final callback.
881 silc_client_process_failure(client, sock, packet);
883 case SILC_PACKET_REJECT:
886 case SILC_PACKET_NOTIFY:
888 * Received notify message
890 silc_client_notify_by_server(client, sock, packet);
893 case SILC_PACKET_ERROR:
895 * Received error message
897 silc_client_error_by_server(client, sock, buffer);
900 case SILC_PACKET_CHANNEL_MESSAGE:
902 * Received message to (from, actually) a channel
904 silc_client_channel_message(client, sock, packet);
906 case SILC_PACKET_CHANNEL_KEY:
908 * Received key for a channel. By receiving this key the client will be
909 * able to talk to the channel it has just joined. This can also be
910 * a new key for existing channel as keys expire peridiocally.
912 silc_client_receive_channel_key(client, sock, buffer);
915 case SILC_PACKET_PRIVATE_MESSAGE:
917 * Received private message
919 silc_client_private_message(client, sock, packet);
921 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
923 * Received private message key
927 case SILC_PACKET_COMMAND_REPLY:
929 * Recived reply for a command
931 silc_client_command_reply_process(client, sock, packet);
934 case SILC_PACKET_KEY_EXCHANGE:
935 if (sock->protocol && sock->protocol->protocol &&
936 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
937 SilcClientKEInternalContext *proto_ctx =
938 (SilcClientKEInternalContext *)sock->protocol->context;
940 proto_ctx->packet = silc_packet_context_dup(packet);
941 proto_ctx->dest_id_type = packet->src_id_type;
942 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
943 packet->src_id_type);
944 if (!proto_ctx->dest_id)
947 /* Let the protocol handle the packet */
948 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
950 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
951 "protocol active, packet dropped."));
955 case SILC_PACKET_KEY_EXCHANGE_1:
956 if (sock->protocol && sock->protocol->protocol &&
957 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
958 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
960 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
961 SilcClientRekeyInternalContext *proto_ctx =
962 (SilcClientRekeyInternalContext *)sock->protocol->context;
964 if (proto_ctx->packet)
965 silc_packet_context_free(proto_ctx->packet);
967 proto_ctx->packet = silc_packet_context_dup(packet);
969 /* Let the protocol handle the packet */
970 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
972 SilcClientKEInternalContext *proto_ctx =
973 (SilcClientKEInternalContext *)sock->protocol->context;
975 if (proto_ctx->packet)
976 silc_packet_context_free(proto_ctx->packet);
978 proto_ctx->packet = silc_packet_context_dup(packet);
979 proto_ctx->dest_id_type = packet->src_id_type;
980 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
981 packet->src_id_type);
982 if (!proto_ctx->dest_id)
985 /* Let the protocol handle the packet */
986 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
989 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
990 "protocol active, packet dropped."));
993 case SILC_PACKET_KEY_EXCHANGE_2:
994 if (sock->protocol && sock->protocol->protocol &&
995 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
996 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
998 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
999 SilcClientRekeyInternalContext *proto_ctx =
1000 (SilcClientRekeyInternalContext *)sock->protocol->context;
1002 if (proto_ctx->packet)
1003 silc_packet_context_free(proto_ctx->packet);
1005 proto_ctx->packet = silc_packet_context_dup(packet);
1007 /* Let the protocol handle the packet */
1008 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1010 SilcClientKEInternalContext *proto_ctx =
1011 (SilcClientKEInternalContext *)sock->protocol->context;
1013 if (proto_ctx->packet)
1014 silc_packet_context_free(proto_ctx->packet);
1016 proto_ctx->packet = silc_packet_context_dup(packet);
1017 proto_ctx->dest_id_type = packet->src_id_type;
1018 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1019 packet->src_id_type);
1020 if (!proto_ctx->dest_id)
1023 /* Let the protocol handle the packet */
1024 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1027 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1028 "protocol active, packet dropped."));
1032 case SILC_PACKET_NEW_ID:
1035 * Received new ID from server. This packet is received at
1036 * the connection to the server. New ID is also received when
1037 * user changes nickname but in that case the new ID is received
1038 * as command reply and not as this packet type.
1042 idp = silc_id_payload_parse(buffer);
1045 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1048 silc_client_receive_new_id(client, sock, idp);
1049 silc_id_payload_free(idp);
1053 case SILC_PACKET_HEARTBEAT:
1055 * Received heartbeat packet
1057 SILC_LOG_DEBUG(("Heartbeat packet"));
1060 case SILC_PACKET_KEY_AGREEMENT:
1062 * Received key agreement packet
1064 SILC_LOG_DEBUG(("Key agreement packet"));
1065 silc_client_key_agreement(client, sock, packet);
1068 case SILC_PACKET_REKEY:
1069 SILC_LOG_DEBUG(("Re-key packet"));
1070 /* We ignore this for now */
1073 case SILC_PACKET_REKEY_DONE:
1074 SILC_LOG_DEBUG(("Re-key done packet"));
1076 if (sock->protocol && sock->protocol->protocol &&
1077 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1079 SilcClientRekeyInternalContext *proto_ctx =
1080 (SilcClientRekeyInternalContext *)sock->protocol->context;
1082 if (proto_ctx->packet)
1083 silc_packet_context_free(proto_ctx->packet);
1085 proto_ctx->packet = silc_packet_context_dup(packet);
1087 /* Let the protocol handle the packet */
1088 if (proto_ctx->responder == FALSE)
1089 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1091 /* Let the protocol handle the packet */
1092 silc_protocol_execute(sock->protocol, client->schedule,
1095 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1096 "protocol active, packet dropped."));
1100 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1102 * Reveived reply to our connection authentication method request
1103 * packet. This is used to resolve the authentication method for the
1104 * current session from the server if the client does not know it.
1106 silc_client_connection_auth_request(client, sock, packet);
1109 case SILC_PACKET_FTP:
1110 /* Received file transfer packet. */
1111 silc_client_ftp(client, sock, packet);
1115 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1120 /* Sends packet. This doesn't actually send the packet instead it assembles
1121 it and marks it to be sent. However, if force_send is TRUE the packet
1122 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1123 will be derived from sock argument. Otherwise the valid arguments sent
1126 void silc_client_packet_send(SilcClient client,
1127 SilcSocketConnection sock,
1128 SilcPacketType type,
1130 SilcIdType dst_id_type,
1133 unsigned char *data,
1137 SilcPacketContext packetdata;
1142 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1144 /* Get data used in the packet sending, keys and stuff */
1145 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1146 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1147 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1149 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1150 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1152 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1153 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1154 dst_id_type = SILC_ID_SERVER;
1158 /* Set the packet context pointers */
1159 packetdata.flags = 0;
1160 packetdata.type = type;
1161 if (sock->user_data &&
1162 ((SilcClientConnection)sock->user_data)->local_id_data) {
1163 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1164 packetdata.src_id_len =
1165 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1168 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1169 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1171 packetdata.src_id_type = SILC_ID_CLIENT;
1173 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1174 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1175 packetdata.dst_id_type = dst_id_type;
1177 packetdata.dst_id = NULL;
1178 packetdata.dst_id_len = 0;
1179 packetdata.dst_id_type = SILC_ID_NONE;
1181 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1182 packetdata.src_id_len + packetdata.dst_id_len;
1183 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1185 /* Prepare outgoing data buffer for packet sending */
1186 silc_packet_send_prepare(sock,
1187 SILC_PACKET_HEADER_LEN +
1188 packetdata.src_id_len +
1189 packetdata.dst_id_len,
1193 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1195 packetdata.buffer = sock->outbuf;
1197 /* Put the data to the buffer */
1198 if (data && data_len)
1199 silc_buffer_put(sock->outbuf, data, data_len);
1201 /* Create the outgoing packet */
1202 silc_packet_assemble(&packetdata);
1204 /* Encrypt the packet */
1206 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1208 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1209 sock->outbuf->data, sock->outbuf->len);
1211 /* Now actually send the packet */
1212 silc_client_packet_send_real(client, sock, force_send);
1215 void silc_client_packet_queue_purge(SilcClient client,
1216 SilcSocketConnection sock)
1218 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1219 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1220 if (sock->outbuf->data - sock->outbuf->head)
1221 silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
1223 silc_packet_send(sock, TRUE);
1225 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1226 SILC_UNSET_OUTBUF_PENDING(sock);
1227 silc_buffer_clear(sock->outbuf);
1231 /* Closes connection to remote end. Free's all allocated data except
1232 for some information such as nickname etc. that are valid at all time.
1233 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1234 provided it will be checked whether the sock and `conn->sock' are the
1235 same (they can be different, ie. a socket can use `conn' as its
1236 connection but `conn->sock' might be actually a different connection
1237 than the `sock'). */
1239 void silc_client_close_connection(SilcClient client,
1240 SilcSocketConnection sock,
1241 SilcClientConnection conn)
1245 if (!sock || (sock && conn->sock == sock))
1250 /* We won't listen for this connection anymore */
1251 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1253 /* Unregister all tasks */
1254 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1255 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1257 /* Close the actual connection */
1258 silc_net_close_connection(sock->sock);
1260 /* Cancel any active protocol */
1261 if (sock->protocol) {
1262 if (sock->protocol->protocol->type ==
1263 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1264 sock->protocol->protocol->type ==
1265 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1266 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1267 silc_protocol_execute_final(sock->protocol, client->schedule);
1268 /* The application will recall this function with these protocols
1269 (the ops->connect client operation). */
1272 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1273 silc_protocol_execute_final(sock->protocol, client->schedule);
1274 sock->protocol = NULL;
1278 /* Free everything */
1279 if (del && sock->user_data) {
1280 /* Free all cache entries */
1281 SilcIDCacheList list;
1282 SilcIDCacheEntry entry;
1285 if (silc_idcache_get_all(conn->client_cache, &list)) {
1286 ret = silc_idcache_list_first(list, &entry);
1288 silc_client_del_client(client, conn, entry->context);
1289 ret = silc_idcache_list_next(list, &entry);
1291 silc_idcache_list_free(list);
1294 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1295 ret = silc_idcache_list_first(list, &entry);
1297 silc_client_del_channel(client, conn, entry->context);
1298 ret = silc_idcache_list_next(list, &entry);
1300 silc_idcache_list_free(list);
1303 if (silc_idcache_get_all(conn->server_cache, &list)) {
1304 ret = silc_idcache_list_first(list, &entry);
1306 silc_client_del_server(client, conn, entry->context);
1307 ret = silc_idcache_list_next(list, &entry);
1309 silc_idcache_list_free(list);
1312 /* Clear ID caches */
1313 if (conn->client_cache)
1314 silc_idcache_del_all(conn->client_cache);
1315 if (conn->channel_cache)
1316 silc_idcache_del_all(conn->channel_cache);
1317 if (conn->server_cache)
1318 silc_idcache_del_all(conn->server_cache);
1320 /* Free data (my ID is freed in above silc_client_del_client) */
1321 if (conn->remote_host)
1322 silc_free(conn->remote_host);
1323 if (conn->local_id_data)
1324 silc_free(conn->local_id_data);
1326 silc_cipher_free(conn->send_key);
1327 if (conn->receive_key)
1328 silc_cipher_free(conn->receive_key);
1329 if (conn->hmac_send) /* conn->hmac_receive is same */
1330 silc_hmac_free(conn->hmac_send);
1331 if (conn->pending_commands)
1332 silc_dlist_uninit(conn->pending_commands);
1334 silc_free(conn->rekey);
1336 memset(conn, 0, sizeof(*conn));
1337 silc_client_del_connection(client, conn);
1340 silc_socket_free(sock);
1343 /* Called when we receive disconnection packet from server. This
1344 closes our end properly and displays the reason of the disconnection
1347 void silc_client_disconnected_by_server(SilcClient client,
1348 SilcSocketConnection sock,
1353 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1355 msg = silc_calloc(message->len + 1, sizeof(char));
1356 memcpy(msg, message->data, message->len);
1357 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1360 SILC_SET_DISCONNECTED(sock);
1361 silc_client_close_connection(client, sock, sock->user_data);
1364 /* Received error message from server. Display it on the screen.
1365 We don't take any action what so ever of the error message. */
1367 void silc_client_error_by_server(SilcClient client,
1368 SilcSocketConnection sock,
1373 msg = silc_calloc(message->len + 1, sizeof(char));
1374 memcpy(msg, message->data, message->len);
1375 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1379 /* Processes the received new Client ID from server. Old Client ID is
1380 deleted from cache and new one is added. */
1382 void silc_client_receive_new_id(SilcClient client,
1383 SilcSocketConnection sock,
1386 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1387 int connecting = FALSE;
1390 if (!conn->local_entry)
1393 /* Delete old ID from ID cache */
1394 if (conn->local_id) {
1395 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1396 silc_free(conn->local_id);
1399 /* Save the new ID */
1401 if (conn->local_id_data)
1402 silc_free(conn->local_id_data);
1404 conn->local_id = silc_id_payload_get_id(idp);
1405 conn->local_id_data = silc_id_payload_get_data(idp);
1406 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1408 if (!conn->local_entry)
1409 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1411 conn->local_entry->nickname = conn->nickname;
1412 if (!conn->local_entry->username)
1413 conn->local_entry->username = strdup(client->username);
1414 if (!conn->local_entry->hostname)
1415 conn->local_entry->hostname = strdup(client->hostname);
1416 conn->local_entry->server = strdup(conn->remote_host);
1417 conn->local_entry->id = conn->local_id;
1418 conn->local_entry->valid = TRUE;
1420 /* Put it to the ID cache */
1421 silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
1422 (void *)conn->local_entry, FALSE);
1424 /* Issue INFO command to fetch the real server name and server information
1426 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1427 silc_client_send_command(client, conn, SILC_COMMAND_INFO,
1428 ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1429 silc_buffer_free(sidp);
1431 /* Notify application of successful connection. We do it here now that
1432 we've received the Client ID and are allowed to send traffic. */
1434 client->ops->connect(client, conn, TRUE);
1437 /* Processed received Channel ID for a channel. This is called when client
1438 joins to channel and server replies with channel ID. The ID is cached.
1439 Returns the created channel entry. This is also called when received
1440 channel ID in for example USERS command reply that we do not have. */
1442 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1443 SilcSocketConnection sock,
1448 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1449 SilcChannelEntry channel;
1451 SILC_LOG_DEBUG(("New channel ID"));
1453 channel = silc_calloc(1, sizeof(*channel));
1454 channel->channel_name = channel_name;
1455 channel->id = silc_id_payload_get_id(idp);
1456 channel->mode = mode;
1457 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1459 /* Put it to the ID cache */
1460 silc_idcache_add(conn->channel_cache, channel->channel_name,
1461 (void *)channel->id, (void *)channel, FALSE);
1466 /* Removes a client entry from all channel it has joined. This really is
1467 a performance killer (client_entry should have pointers to channel
1470 void silc_client_remove_from_channels(SilcClient client,
1471 SilcClientConnection conn,
1472 SilcClientEntry client_entry)
1474 SilcIDCacheEntry id_cache;
1475 SilcIDCacheList list;
1476 SilcChannelEntry channel;
1477 SilcChannelUser chu;
1479 if (!silc_idcache_get_all(conn->channel_cache, &list))
1482 silc_idcache_list_first(list, &id_cache);
1483 channel = (SilcChannelEntry)id_cache->context;
1487 /* Remove client from channel */
1488 silc_list_start(channel->clients);
1489 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1490 if (chu->client == client_entry) {
1491 silc_list_del(channel->clients, chu);
1497 if (!silc_idcache_list_next(list, &id_cache))
1500 channel = (SilcChannelEntry)id_cache->context;
1503 silc_idcache_list_free(list);
1506 /* Replaces `old' client entries from all channels to `new' client entry.
1507 This can be called for example when nickname changes and old ID entry
1508 is replaced from ID cache with the new one. If the old ID entry is only
1509 updated, then this fucntion needs not to be called. */
1511 void silc_client_replace_from_channels(SilcClient client,
1512 SilcClientConnection conn,
1513 SilcClientEntry old,
1514 SilcClientEntry new)
1516 SilcIDCacheEntry id_cache;
1517 SilcIDCacheList list;
1518 SilcChannelEntry channel;
1519 SilcChannelUser chu;
1521 if (!silc_idcache_get_all(conn->channel_cache, &list))
1524 silc_idcache_list_first(list, &id_cache);
1525 channel = (SilcChannelEntry)id_cache->context;
1529 /* Replace client entry */
1530 silc_list_start(channel->clients);
1531 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1532 if (chu->client == old) {
1538 if (!silc_idcache_list_next(list, &id_cache))
1541 channel = (SilcChannelEntry)id_cache->context;
1544 silc_idcache_list_free(list);
1547 /* Registers failure timeout to process the received failure packet
1550 void silc_client_process_failure(SilcClient client,
1551 SilcSocketConnection sock,
1552 SilcPacketContext *packet)
1556 if (sock->protocol) {
1557 if (packet->buffer->len >= 4)
1558 SILC_GET32_MSB(failure, packet->buffer->data);
1560 /* Notify application */
1561 client->ops->failure(client, sock->user_data, sock->protocol,
1566 /* A timeout callback for the re-key. We will be the initiator of the
1569 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1571 SilcSocketConnection sock = (SilcSocketConnection)context;
1572 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1573 SilcClient client = (SilcClient)conn->rekey->context;
1574 SilcProtocol protocol;
1575 SilcClientRekeyInternalContext *proto_ctx;
1577 SILC_LOG_DEBUG(("Start"));
1579 /* Allocate internal protocol context. This is sent as context
1581 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1582 proto_ctx->client = (void *)client;
1583 proto_ctx->sock = silc_socket_dup(sock);
1584 proto_ctx->responder = FALSE;
1585 proto_ctx->pfs = conn->rekey->pfs;
1587 /* Perform rekey protocol. Will call the final callback after the
1588 protocol is over. */
1589 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1590 &protocol, proto_ctx, silc_client_rekey_final);
1591 sock->protocol = protocol;
1593 /* Run the protocol */
1594 silc_protocol_execute(protocol, client->schedule, 0, 0);
1596 /* Re-register re-key timeout */
1597 silc_schedule_task_add(client->schedule, sock->sock,
1598 silc_client_rekey_callback,
1599 context, conn->rekey->timeout, 0,
1600 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1603 /* The final callback for the REKEY protocol. This will actually take the
1604 new key material into use. */
1606 SILC_TASK_CALLBACK(silc_client_rekey_final)
1608 SilcProtocol protocol = (SilcProtocol)context;
1609 SilcClientRekeyInternalContext *ctx =
1610 (SilcClientRekeyInternalContext *)protocol->context;
1611 SilcClient client = (SilcClient)ctx->client;
1612 SilcSocketConnection sock = ctx->sock;
1614 SILC_LOG_DEBUG(("Start"));
1616 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1617 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1618 /* Error occured during protocol */
1619 silc_protocol_cancel(protocol, client->schedule);
1620 silc_protocol_free(protocol);
1621 sock->protocol = NULL;
1623 silc_packet_context_free(ctx->packet);
1625 silc_ske_free(ctx->ske);
1626 silc_socket_free(ctx->sock);
1631 /* Purge the outgoing data queue to assure that all rekey packets really
1632 go to the network before we quit the protocol. */
1633 silc_client_packet_queue_purge(client, sock);
1636 silc_protocol_free(protocol);
1637 sock->protocol = NULL;
1639 silc_packet_context_free(ctx->packet);
1641 silc_ske_free(ctx->ske);
1642 silc_socket_free(ctx->sock);
1646 /* Processes incoming connection authentication method request packet.
1647 It is a reply to our previously sent request. The packet can be used
1648 to resolve the authentication method for the current session if the
1649 client does not know it beforehand. */
1651 void silc_client_connection_auth_request(SilcClient client,
1652 SilcSocketConnection sock,
1653 SilcPacketContext *packet)
1655 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1656 uint16 conn_type, auth_meth;
1659 /* If we haven't send our request then ignore this one. */
1660 if (!conn->connauth)
1663 /* Parse the payload */
1664 ret = silc_buffer_unformat(packet->buffer,
1665 SILC_STR_UI_SHORT(&conn_type),
1666 SILC_STR_UI_SHORT(&auth_meth),
1669 auth_meth = SILC_AUTH_NONE;
1671 /* Call the request callback to notify application for received
1672 authentication method information. */
1673 if (conn->connauth->callback)
1674 (*conn->connauth->callback)(client, conn, auth_meth,
1675 conn->connauth->context);
1677 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1679 silc_free(conn->connauth);
1680 conn->connauth = NULL;
1683 /* Timeout task callback called if the server does not reply to our
1684 connection authentication method request in the specified time interval. */
1686 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1688 SilcClientConnection conn = (SilcClientConnection)context;
1689 SilcClient client = conn->client;
1691 if (!conn->connauth)
1694 /* Call the request callback to notify application */
1695 if (conn->connauth->callback)
1696 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1697 conn->connauth->context);
1699 silc_free(conn->connauth);
1700 conn->connauth = NULL;
1703 /* This function can be used to request the current authentication method
1704 from the server. This may be called when connecting to the server
1705 and the client library requests the authentication data from the
1706 application. If the application does not know the current authentication
1707 method it can request it from the server using this function.
1708 The `callback' with `context' will be called after the server has
1709 replied back with the current authentication method. */
1712 silc_client_request_authentication_method(SilcClient client,
1713 SilcClientConnection conn,
1714 SilcConnectionAuthRequest callback,
1717 SilcClientConnAuthRequest connauth;
1720 connauth = silc_calloc(1, sizeof(*connauth));
1721 connauth->callback = callback;
1722 connauth->context = context;
1725 silc_free(conn->connauth);
1727 conn->connauth = connauth;
1729 /* Assemble the request packet and send it to the server */
1730 packet = silc_buffer_alloc(4);
1731 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1732 silc_buffer_format(packet,
1733 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1734 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1736 silc_client_packet_send(client, conn->sock,
1737 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1738 NULL, 0, NULL, NULL,
1739 packet->data, packet->len, FALSE);
1740 silc_buffer_free(packet);
1742 /* Register a timeout in case server does not reply anything back. */
1744 silc_schedule_task_add(client->schedule, conn->sock->sock,
1745 silc_client_request_authentication_method_timeout,
1746 conn, client->params->connauth_request_secs, 0,
1747 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1750 /* Called when file transfer packet is received. This will parse the
1751 packet and give it to the file transfer protocol. */
1753 void silc_client_ftp(SilcClient client,
1754 SilcSocketConnection sock,
1755 SilcPacketContext *packet)
1757 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1761 /* Parse the payload */
1762 ret = silc_buffer_unformat(packet->buffer,
1763 SILC_STR_UI_CHAR(&type),
1768 /* We support only type number 1 (== SFTP) */
1772 silc_buffer_pull(packet->buffer, 1);
1774 /* Give it to the file transfer protocol processor. */
1775 //silc_sftp_client_receive_process(xxx, sock, packet);