5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
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);
38 /* Allocates new client object. This has to be done before client may
39 work. After calling this one must call silc_client_init to initialize
40 the client. The `application' is application specific user data pointer
41 and caller must free it. */
43 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
45 SilcClient new_client;
47 new_client = silc_calloc(1, sizeof(*new_client));
48 new_client->application = application;
49 new_client->ops = ops;
54 /* Frees client object and its internals. */
56 void silc_client_free(SilcClient client)
60 silc_rng_free(client->rng);
66 /* Initializes the client. This makes all the necessary steps to make
67 the client ready to be run. One must call silc_client_run to run the
68 client. Returns FALSE if error occured, TRUE otherwise. */
70 int silc_client_init(SilcClient client)
72 SILC_LOG_DEBUG(("Initializing client"));
74 /* Initialize hash functions for client to use */
75 silc_hash_alloc("md5", &client->md5hash);
76 silc_hash_alloc("sha1", &client->sha1hash);
78 /* Initialize none cipher */
79 silc_cipher_alloc("none", &client->none_cipher);
81 /* Initialize random number generator */
82 client->rng = silc_rng_alloc();
83 silc_rng_init(client->rng);
84 silc_rng_global_init(client->rng);
86 /* Register protocols */
87 silc_client_protocols_register();
89 /* Initialize the scheduler */
90 client->schedule = silc_schedule_init(&client->io_queue,
91 &client->timeout_queue,
92 &client->generic_queue, 5000);
93 if (!client->schedule)
99 /* Stops the client. This is called to stop the client and thus to stop
102 void silc_client_stop(SilcClient client)
104 SILC_LOG_DEBUG(("Stopping client"));
106 /* Stop the scheduler, although it might be already stopped. This
107 doesn't hurt anyone. This removes all the tasks and task queues,
109 silc_schedule_stop(client->schedule);
110 silc_schedule_uninit(client->schedule);
112 silc_client_protocols_unregister();
114 SILC_LOG_DEBUG(("Client stopped"));
117 /* Runs the client. This starts the scheduler from the utility library.
118 When this functions returns the execution of the appliation is over. */
120 void silc_client_run(SilcClient client)
122 SILC_LOG_DEBUG(("Running client"));
124 /* Start the scheduler, the heart of the SILC client. When this returns
125 the program will be terminated. */
126 silc_schedule(client->schedule);
129 /* Allocates and adds new connection to the client. This adds the allocated
130 connection to the connection table and returns a pointer to it. A client
131 can have multiple connections to multiple servers. Every connection must
132 be added to the client using this function. User data `context' may
133 be sent as argument. This function is normally used only if the
134 application performed the connecting outside the library. The library
135 however may use this internally. */
137 SilcClientConnection silc_client_add_connection(SilcClient client,
142 SilcClientConnection conn;
145 conn = silc_calloc(1, sizeof(*conn));
147 /* Initialize ID caches */
148 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
149 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
150 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
151 conn->client = client;
152 conn->remote_host = strdup(hostname);
153 conn->remote_port = port;
154 conn->context = context;
155 conn->pending_commands = silc_dlist_init();
157 /* Add the connection to connections table */
158 for (i = 0; i < client->conns_count; i++)
159 if (client->conns && !client->conns[i]) {
160 client->conns[i] = conn;
164 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
165 * (client->conns_count + 1));
166 client->conns[client->conns_count] = conn;
167 client->conns_count++;
172 /* Removes connection from client. Frees all memory. */
174 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
178 for (i = 0; i < client->conns_count; i++)
179 if (client->conns[i] == conn) {
180 if (conn->pending_commands)
181 silc_dlist_uninit(conn->pending_commands);
183 client->conns[i] = NULL;
187 /* Adds listener socket to the listener sockets table. This function is
188 used to add socket objects that are listeners to the client. This should
189 not be used to add other connection objects. */
191 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
195 if (!client->sockets) {
196 client->sockets = silc_calloc(1, sizeof(*client->sockets));
197 client->sockets[0] = silc_socket_dup(sock);
198 client->sockets_count = 1;
202 for (i = 0; i < client->sockets_count; i++) {
203 if (client->sockets[i] == NULL) {
204 client->sockets[i] = silc_socket_dup(sock);
209 client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
210 (client->sockets_count + 1));
211 client->sockets[client->sockets_count] = silc_socket_dup(sock);
212 client->sockets_count++;
215 /* Deletes listener socket from the listener sockets table. */
217 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
221 if (!client->sockets)
224 for (i = 0; i < client->sockets_count; i++) {
225 if (client->sockets[i] == sock) {
226 silc_socket_free(sock);
227 client->sockets[i] = NULL;
234 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
238 /* XXX In the future we should give up this non-blocking connect all
239 together and use threads instead. */
240 /* Create connection to server asynchronously */
241 sock = silc_net_create_connection_async(ctx->port, ctx->host);
245 /* Register task that will receive the async connect and will
247 ctx->task = silc_task_register(ctx->client->io_queue, sock,
248 silc_client_connect_to_server_start,
251 SILC_TASK_PRI_NORMAL);
252 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
253 silc_schedule_set_listen_fd(ctx->client->schedule, sock, ctx->task->iomask);
260 /* Connects to remote server. This is the main routine used to connect
261 to SILC server. Returns -1 on error and the created socket otherwise.
262 The `context' is user context that is saved into the SilcClientConnection
263 that is created after the connection is created. Note that application
264 may handle the connecting process outside the library. If this is the
265 case then this function is not used at all. When the connecting is
266 done the `connect' client operation is called. */
268 int silc_client_connect_to_server(SilcClient client, int port,
269 char *host, void *context)
271 SilcClientInternalConnectContext *ctx;
272 SilcClientConnection conn;
275 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
278 conn = silc_client_add_connection(client, host, port, context);
280 client->ops->say(client, conn,
281 "Connecting to port %d of server %s", port, host);
283 /* Allocate internal context for connection process. This is
284 needed as we are doing async connecting. */
285 ctx = silc_calloc(1, sizeof(*ctx));
286 ctx->client = client;
288 ctx->host = strdup(host);
292 /* Do the actual connecting process */
293 sock = silc_client_connect_to_server_internal(ctx);
295 silc_client_del_connection(client, conn);
299 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
300 key material between client and server. This function can be called
301 directly if application is performing its own connecting and does not
302 use the connecting provided by this library. This function is normally
303 used only if the application performed the connecting outside the library.
304 The library however may use this internally. */
306 int silc_client_start_key_exchange(SilcClient client,
307 SilcClientConnection conn,
310 SilcProtocol protocol;
311 SilcClientKEInternalContext *proto_ctx;
314 /* Allocate new socket connection object */
315 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
317 conn->nickname = strdup(client->username);
318 conn->sock->hostname = conn->remote_host;
319 conn->sock->ip = strdup(conn->remote_host);
320 conn->sock->port = conn->remote_port;
322 /* Allocate internal Key Exchange context. This is sent to the
323 protocol as context. */
324 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
325 proto_ctx->client = (void *)client;
326 proto_ctx->sock = silc_socket_dup(conn->sock);
327 proto_ctx->rng = client->rng;
328 proto_ctx->responder = FALSE;
329 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
330 proto_ctx->verify = silc_client_protocol_ke_verify_key;
332 /* Perform key exchange protocol. silc_client_connect_to_server_final
333 will be called after the protocol is finished. */
334 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
335 &protocol, (void *)proto_ctx,
336 silc_client_connect_to_server_second);
338 client->ops->say(client, conn,
339 "Error: Could not start authentication protocol");
342 conn->sock->protocol = protocol;
344 /* Register the connection for network input and output. This sets
345 that scheduler will listen for incoming packets for this connection
346 and sets that outgoing packets may be sent to this connection as well.
347 However, this doesn't set the scheduler for outgoing traffic, it will
348 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
349 later when outgoing data is available. */
350 context = (void *)client;
351 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
353 /* Execute the protocol */
354 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
358 /* Start of the connection to the remote server. This is called after
359 succesful TCP/IP connection has been established to the remote host. */
361 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
363 SilcClientInternalConnectContext *ctx =
364 (SilcClientInternalConnectContext *)context;
365 SilcClient client = ctx->client;
366 SilcClientConnection conn = ctx->conn;
367 int opt, opt_len = sizeof(opt);
369 SILC_LOG_DEBUG(("Start"));
371 /* Check the socket status as it might be in error */
372 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
374 if (ctx->tries < 2) {
375 /* Connection failed but lets try again */
376 client->ops->say(client, conn, "Could not connect to server %s: %s",
377 ctx->host, strerror(opt));
378 client->ops->say(client, conn,
379 "Connecting to port %d of server %s resumed",
380 ctx->port, ctx->host);
382 /* Unregister old connection try */
383 silc_schedule_unset_listen_fd(client->schedule, fd);
384 silc_net_close_connection(fd);
385 silc_task_unregister(client->io_queue, ctx->task);
388 silc_client_connect_to_server_internal(ctx);
391 /* Connection failed and we won't try anymore */
392 client->ops->say(client, conn, "Could not connect to server %s: %s",
393 ctx->host, strerror(opt));
394 silc_schedule_unset_listen_fd(client->schedule, fd);
395 silc_net_close_connection(fd);
396 silc_task_unregister(client->io_queue, ctx->task);
399 /* Notify application of failure */
400 client->ops->connect(client, conn, FALSE);
401 silc_client_del_connection(client, conn);
406 silc_schedule_unset_listen_fd(client->schedule, fd);
407 silc_task_unregister(client->io_queue, ctx->task);
410 if (!silc_client_start_key_exchange(client, conn, fd)) {
411 silc_net_close_connection(fd);
412 client->ops->connect(client, conn, FALSE);
416 /* Second part of the connecting to the server. This executed
417 authentication protocol. */
419 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
421 SilcProtocol protocol = (SilcProtocol)context;
422 SilcClientKEInternalContext *ctx =
423 (SilcClientKEInternalContext *)protocol->context;
424 SilcClient client = (SilcClient)ctx->client;
425 SilcSocketConnection sock = NULL;
426 SilcClientConnAuthInternalContext *proto_ctx;
428 SILC_LOG_DEBUG(("Start"));
430 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
431 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
432 /* Error occured during protocol */
433 SILC_LOG_DEBUG(("Error during KE protocol"));
434 silc_protocol_free(protocol);
435 silc_ske_free_key_material(ctx->keymat);
437 silc_ske_free(ctx->ske);
439 silc_free(ctx->dest_id);
440 ctx->sock->protocol = NULL;
441 silc_socket_free(ctx->sock);
443 /* Notify application of failure */
444 client->ops->connect(client, ctx->sock->user_data, FALSE);
449 /* We now have the key material as the result of the key exchange
450 protocol. Take the key material into use. Free the raw key material
451 as soon as we've set them into use. */
452 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
453 ctx->ske->prop->cipher,
454 ctx->ske->prop->pkcs,
455 ctx->ske->prop->hash,
456 ctx->ske->prop->hmac,
457 ctx->ske->prop->group);
458 silc_ske_free_key_material(ctx->keymat);
460 /* Allocate internal context for the authentication protocol. This
461 is sent as context for the protocol. */
462 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
463 proto_ctx->client = (void *)client;
464 proto_ctx->sock = sock = ctx->sock;
465 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
466 proto_ctx->dest_id_type = ctx->dest_id_type;
467 proto_ctx->dest_id = ctx->dest_id;
469 /* Resolve the authentication method to be used in this connection */
470 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
471 sock->port, &proto_ctx->auth_meth,
472 &proto_ctx->auth_data,
473 &proto_ctx->auth_data_len))
474 proto_ctx->auth_meth = SILC_AUTH_NONE;
476 /* Free old protocol as it is finished now */
477 silc_protocol_free(protocol);
479 silc_packet_context_free(ctx->packet);
481 sock->protocol = NULL;
483 /* Allocate the authenteication protocol and execute it. */
484 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
485 &sock->protocol, (void *)proto_ctx,
486 silc_client_connect_to_server_final);
488 /* Execute the protocol */
489 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
492 /* Finalizes the connection to the remote SILC server. This is called
493 after authentication protocol has been completed. This send our
494 user information to the server to receive our client ID from
497 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
499 SilcProtocol protocol = (SilcProtocol)context;
500 SilcClientConnAuthInternalContext *ctx =
501 (SilcClientConnAuthInternalContext *)protocol->context;
502 SilcClient client = (SilcClient)ctx->client;
503 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
506 SILC_LOG_DEBUG(("Start"));
508 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
509 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
510 /* Error occured during protocol */
511 SILC_LOG_DEBUG(("Error during authentication protocol"));
512 silc_protocol_free(protocol);
514 silc_free(ctx->auth_data);
516 silc_ske_free(ctx->ske);
518 silc_free(ctx->dest_id);
519 conn->sock->protocol = NULL;
520 silc_socket_free(ctx->sock);
522 /* Notify application of failure */
523 client->ops->connect(client, ctx->sock->user_data, FALSE);
528 /* Send NEW_CLIENT packet to the server. We will become registered
529 to the SILC network after sending this packet and we will receive
530 client ID from the server. */
531 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
532 strlen(client->realname));
533 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
534 silc_buffer_format(packet,
535 SILC_STR_UI_SHORT(strlen(client->username)),
536 SILC_STR_UI_XNSTRING(client->username,
537 strlen(client->username)),
538 SILC_STR_UI_SHORT(strlen(client->realname)),
539 SILC_STR_UI_XNSTRING(client->realname,
540 strlen(client->realname)),
543 /* Send the packet */
544 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
546 packet->data, packet->len, TRUE);
547 silc_buffer_free(packet);
549 /* Save remote ID. */
550 conn->remote_id = ctx->dest_id;
551 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
552 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
554 /* Register re-key timeout */
555 conn->rekey->timeout = 3600; /* XXX hardcoded */
556 conn->rekey->context = (void *)client;
557 silc_task_register(client->timeout_queue, conn->sock->sock,
558 silc_client_rekey_callback,
559 (void *)conn->sock, conn->rekey->timeout, 0,
560 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
562 silc_protocol_free(protocol);
564 silc_free(ctx->auth_data);
566 silc_ske_free(ctx->ske);
567 silc_socket_free(ctx->sock);
569 conn->sock->protocol = NULL;
572 /* Internal routine that sends packet or marks packet to be sent. This
573 is used directly only in special cases. Normal cases should use
574 silc_server_packet_send. Returns < 0 on error. */
576 int silc_client_packet_send_real(SilcClient client,
577 SilcSocketConnection sock,
583 /* If rekey protocol is active we must assure that all packets are
584 sent through packet queue. */
585 if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
588 /* Send the packet */
589 ret = silc_packet_send(sock, force_send);
593 /* Mark that there is some outgoing data available for this connection.
594 This call sets the connection both for input and output (the input
595 is set always and this call keeps the input setting, actually).
596 Actual data sending is performed by silc_client_packet_process. */
597 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
599 /* Mark to socket that data is pending in outgoing buffer. This flag
600 is needed if new data is added to the buffer before the earlier
601 put data is sent to the network. */
602 SILC_SET_OUTBUF_PENDING(sock);
607 /* Packet processing callback. This is used to send and receive packets
608 from network. This is generic task. */
610 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
612 SilcClient client = (SilcClient)context;
613 SilcSocketConnection sock = NULL;
614 SilcClientConnection conn;
617 SILC_LOG_DEBUG(("Processing packet"));
619 SILC_CLIENT_GET_SOCK(client, fd, sock);
623 conn = (SilcClientConnection)sock->user_data;
626 if (type == SILC_TASK_WRITE) {
627 SILC_LOG_DEBUG(("Writing data to connection"));
629 if (sock->outbuf->data - sock->outbuf->head)
630 silc_buffer_push(sock->outbuf,
631 sock->outbuf->data - sock->outbuf->head);
633 ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
635 /* If returned -2 could not write to connection now, will do
640 /* The packet has been sent and now it is time to set the connection
641 back to only for input. When there is again some outgoing data
642 available for this connection it will be set for output as well.
643 This call clears the output setting and sets it only for input. */
644 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
645 SILC_UNSET_OUTBUF_PENDING(sock);
647 silc_buffer_clear(sock->outbuf);
651 /* Packet receiving */
652 if (type == SILC_TASK_READ) {
653 SILC_LOG_DEBUG(("Reading data from connection"));
655 /* Read data from network */
656 ret = silc_packet_receive(sock);
662 SILC_LOG_DEBUG(("Read EOF"));
664 /* If connection is disconnecting already we will finally
665 close the connection */
666 if (SILC_IS_DISCONNECTING(sock)) {
667 if (sock == conn->sock)
668 client->ops->disconnect(client, conn);
669 silc_client_close_connection(client, sock, conn);
673 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
674 if (sock == conn->sock)
675 client->ops->disconnect(client, conn);
676 silc_client_close_connection(client, sock, conn);
680 /* Process the packet. This will call the parser that will then
681 decrypt and parse the packet. */
682 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
683 silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
684 silc_client_packet_parse, client);
686 silc_packet_receive_process(sock, NULL, NULL,
687 silc_client_packet_parse, client);
691 /* Callback function that the silc_packet_decrypt will call to make the
692 decision whether the packet is normal or special packet. We will
693 return TRUE if it is normal and FALSE if it is special */
695 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
697 SilcPacketContext *packet,
701 /* Packet is normal packet, if:
703 1) packet is private message packet and does not have private key set
704 2) is other packet than channel message packet
706 all other packets are special packets
709 if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
710 (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
713 if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
719 /* Parses whole packet, received earlier. */
721 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
723 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
724 SilcClient client = (SilcClient)parse_ctx->context;
725 SilcPacketContext *packet = parse_ctx->packet;
726 SilcBuffer buffer = packet->buffer;
727 SilcSocketConnection sock = parse_ctx->sock;
728 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
731 SILC_LOG_DEBUG(("Start"));
733 /* Decrypt the received packet */
734 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
735 ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
737 silc_client_packet_decrypt_check, parse_ctx);
739 ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
740 silc_client_packet_decrypt_check, parse_ctx);
746 /* Parse the packet. Packet type is returned. */
747 ret = silc_packet_parse(packet);
749 /* Parse the packet header in special way as this is "special"
751 ret = silc_packet_parse_special(packet);
754 if (ret == SILC_PACKET_NONE)
757 /* Parse the incoming packet type */
758 silc_client_packet_parse_type(client, sock, packet);
761 /* silc_buffer_clear(sock->inbuf); */
762 silc_packet_context_free(packet);
763 silc_free(parse_ctx);
766 /* Parser callback called by silc_packet_receive_process. Thie merely
767 registers timeout that will handle the actual parsing when appropriate. */
769 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
771 SilcClient client = (SilcClient)parser_context->context;
773 /* Parse the packet */
774 silc_task_register(client->timeout_queue, parser_context->sock->sock,
775 silc_client_packet_parse_real,
776 (void *)parser_context, 0, 1,
778 SILC_TASK_PRI_NORMAL);
781 /* Parses the packet type and calls what ever routines the packet type
782 requires. This is done for all incoming packets. */
784 void silc_client_packet_parse_type(SilcClient client,
785 SilcSocketConnection sock,
786 SilcPacketContext *packet)
788 SilcBuffer buffer = packet->buffer;
789 SilcPacketType type = packet->type;
791 SILC_LOG_DEBUG(("Parsing packet type %d", type));
793 /* Parse the packet type */
795 case SILC_PACKET_DISCONNECT:
796 silc_client_disconnected_by_server(client, sock, buffer);
798 case SILC_PACKET_SUCCESS:
800 * Success received for something. For now we can have only
801 * one protocol for connection executing at once hence this
802 * success message is for whatever protocol is executing currently.
805 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
807 case SILC_PACKET_FAILURE:
809 * Failure received for some protocol. Set the protocol state to
810 * error and call the protocol callback. This fill cause error on
811 * protocol and it will call the final callback.
813 silc_client_process_failure(client, sock, packet);
815 case SILC_PACKET_REJECT:
818 case SILC_PACKET_NOTIFY:
820 * Received notify message
822 silc_client_notify_by_server(client, sock, packet);
825 case SILC_PACKET_ERROR:
827 * Received error message
829 silc_client_error_by_server(client, sock, buffer);
832 case SILC_PACKET_CHANNEL_MESSAGE:
834 * Received message to (from, actually) a channel
836 silc_client_channel_message(client, sock, packet);
838 case SILC_PACKET_CHANNEL_KEY:
840 * Received key for a channel. By receiving this key the client will be
841 * able to talk to the channel it has just joined. This can also be
842 * a new key for existing channel as keys expire peridiocally.
844 silc_client_receive_channel_key(client, sock, buffer);
847 case SILC_PACKET_PRIVATE_MESSAGE:
849 * Received private message
851 silc_client_private_message(client, sock, packet);
853 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
855 * Received private message key
859 case SILC_PACKET_COMMAND_REPLY:
861 * Recived reply for a command
863 silc_client_command_reply_process(client, sock, packet);
866 case SILC_PACKET_KEY_EXCHANGE:
867 if (sock->protocol && sock->protocol->protocol &&
868 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
869 SilcClientKEInternalContext *proto_ctx =
870 (SilcClientKEInternalContext *)sock->protocol->context;
872 proto_ctx->packet = silc_packet_context_dup(packet);
873 proto_ctx->dest_id_type = packet->src_id_type;
874 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
875 packet->src_id_type);
876 if (!proto_ctx->dest_id)
879 /* Let the protocol handle the packet */
880 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
882 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
883 "protocol active, packet dropped."));
887 case SILC_PACKET_KEY_EXCHANGE_1:
888 if (sock->protocol && sock->protocol->protocol &&
889 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
890 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
892 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
893 SilcClientRekeyInternalContext *proto_ctx =
894 (SilcClientRekeyInternalContext *)sock->protocol->context;
896 if (proto_ctx->packet)
897 silc_packet_context_free(proto_ctx->packet);
899 proto_ctx->packet = silc_packet_context_dup(packet);
901 /* Let the protocol handle the packet */
902 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
904 SilcClientKEInternalContext *proto_ctx =
905 (SilcClientKEInternalContext *)sock->protocol->context;
907 if (proto_ctx->packet)
908 silc_packet_context_free(proto_ctx->packet);
910 proto_ctx->packet = silc_packet_context_dup(packet);
911 proto_ctx->dest_id_type = packet->src_id_type;
912 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
913 packet->src_id_type);
914 if (!proto_ctx->dest_id)
917 /* Let the protocol handle the packet */
918 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
921 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
922 "protocol active, packet dropped."));
925 case SILC_PACKET_KEY_EXCHANGE_2:
926 if (sock->protocol && sock->protocol->protocol &&
927 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
928 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
930 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
931 SilcClientRekeyInternalContext *proto_ctx =
932 (SilcClientRekeyInternalContext *)sock->protocol->context;
934 if (proto_ctx->packet)
935 silc_packet_context_free(proto_ctx->packet);
937 proto_ctx->packet = silc_packet_context_dup(packet);
939 /* Let the protocol handle the packet */
940 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
942 SilcClientKEInternalContext *proto_ctx =
943 (SilcClientKEInternalContext *)sock->protocol->context;
945 if (proto_ctx->packet)
946 silc_packet_context_free(proto_ctx->packet);
948 proto_ctx->packet = silc_packet_context_dup(packet);
949 proto_ctx->dest_id_type = packet->src_id_type;
950 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
951 packet->src_id_type);
952 if (!proto_ctx->dest_id)
955 /* Let the protocol handle the packet */
956 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
959 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
960 "protocol active, packet dropped."));
964 case SILC_PACKET_NEW_ID:
967 * Received new ID from server. This packet is received at
968 * the connection to the server. New ID is also received when
969 * user changes nickname but in that case the new ID is received
970 * as command reply and not as this packet type.
974 idp = silc_id_payload_parse(buffer);
977 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
980 silc_client_receive_new_id(client, sock, idp);
981 silc_id_payload_free(idp);
985 case SILC_PACKET_HEARTBEAT:
987 * Received heartbeat packet
989 SILC_LOG_DEBUG(("Heartbeat packet"));
992 case SILC_PACKET_KEY_AGREEMENT:
994 * Received key agreement packet
996 SILC_LOG_DEBUG(("Key agreement packet"));
997 silc_client_key_agreement(client, sock, packet);
1000 case SILC_PACKET_REKEY:
1001 SILC_LOG_DEBUG(("Re-key packet"));
1002 /* We ignore this for now */
1005 case SILC_PACKET_REKEY_DONE:
1006 SILC_LOG_DEBUG(("Re-key done packet"));
1008 if (sock->protocol && sock->protocol->protocol &&
1009 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1011 SilcClientRekeyInternalContext *proto_ctx =
1012 (SilcClientRekeyInternalContext *)sock->protocol->context;
1014 if (proto_ctx->packet)
1015 silc_packet_context_free(proto_ctx->packet);
1017 proto_ctx->packet = silc_packet_context_dup(packet);
1019 /* Let the protocol handle the packet */
1020 if (proto_ctx->responder == FALSE)
1021 silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
1023 /* Let the protocol handle the packet */
1024 silc_protocol_execute(sock->protocol, client->timeout_queue,
1027 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1028 "protocol active, packet dropped."));
1033 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1038 /* Sends packet. This doesn't actually send the packet instead it assembles
1039 it and marks it to be sent. However, if force_send is TRUE the packet
1040 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1041 will be derived from sock argument. Otherwise the valid arguments sent
1044 void silc_client_packet_send(SilcClient client,
1045 SilcSocketConnection sock,
1046 SilcPacketType type,
1048 SilcIdType dst_id_type,
1051 unsigned char *data,
1055 SilcPacketContext packetdata;
1060 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1062 /* Get data used in the packet sending, keys and stuff */
1063 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1064 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1065 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1067 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1068 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1070 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1071 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1072 dst_id_type = SILC_ID_SERVER;
1076 /* Set the packet context pointers */
1077 packetdata.flags = 0;
1078 packetdata.type = type;
1079 if (sock->user_data &&
1080 ((SilcClientConnection)sock->user_data)->local_id_data) {
1081 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1082 packetdata.src_id_len =
1083 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1086 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1087 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1089 packetdata.src_id_type = SILC_ID_CLIENT;
1091 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1092 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1093 packetdata.dst_id_type = dst_id_type;
1095 packetdata.dst_id = NULL;
1096 packetdata.dst_id_len = 0;
1097 packetdata.dst_id_type = SILC_ID_NONE;
1099 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1100 packetdata.src_id_len + packetdata.dst_id_len;
1101 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1103 /* Prepare outgoing data buffer for packet sending */
1104 silc_packet_send_prepare(sock,
1105 SILC_PACKET_HEADER_LEN +
1106 packetdata.src_id_len +
1107 packetdata.dst_id_len,
1111 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1113 packetdata.buffer = sock->outbuf;
1115 /* Put the data to the buffer */
1116 if (data && data_len)
1117 silc_buffer_put(sock->outbuf, data, data_len);
1119 /* Create the outgoing packet */
1120 silc_packet_assemble(&packetdata);
1122 /* Encrypt the packet */
1124 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1126 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1127 sock->outbuf->data, sock->outbuf->len);
1129 /* Now actually send the packet */
1130 silc_client_packet_send_real(client, sock, force_send, FALSE);
1133 /* Closes connection to remote end. Free's all allocated data except
1134 for some information such as nickname etc. that are valid at all time.
1135 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1136 provided it will be checked whether the sock and `conn->sock' are the
1137 same (they can be different, ie. a socket can use `conn' as its
1138 connection but `conn->sock' might be actually a different connection
1139 than the `sock'). */
1141 void silc_client_close_connection(SilcClient client,
1142 SilcSocketConnection sock,
1143 SilcClientConnection conn)
1147 if (!sock || (sock && conn->sock == sock))
1152 /* We won't listen for this connection anymore */
1153 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1155 /* Unregister all tasks */
1156 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1157 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1159 /* Close the actual connection */
1160 silc_net_close_connection(sock->sock);
1162 /* Cancel any active protocol */
1163 if (sock->protocol) {
1164 if (sock->protocol->protocol->type ==
1165 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1166 sock->protocol->protocol->type ==
1167 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1168 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1169 silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1170 sock->protocol = NULL;
1171 /* The application will recall this function with these protocols
1172 (the ops->connect client operation). */
1175 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1176 silc_protocol_execute_final(sock->protocol, client->timeout_queue);
1177 sock->protocol = NULL;
1181 /* Free everything */
1182 if (del && sock->user_data) {
1183 /* XXX Free all client entries and channel entries. */
1185 /* Clear ID caches */
1186 if (conn->client_cache)
1187 silc_idcache_del_all(conn->client_cache);
1188 if (conn->channel_cache)
1189 silc_idcache_del_all(conn->channel_cache);
1192 if (conn->remote_host)
1193 silc_free(conn->remote_host);
1195 silc_free(conn->local_id);
1196 if (conn->local_id_data)
1197 silc_free(conn->local_id_data);
1199 silc_cipher_free(conn->send_key);
1200 if (conn->receive_key)
1201 silc_cipher_free(conn->receive_key);
1202 if (conn->hmac_send) /* conn->hmac_receive is same */
1203 silc_hmac_free(conn->hmac_send);
1204 if (conn->pending_commands)
1205 silc_dlist_uninit(conn->pending_commands);
1207 silc_free(conn->rekey);
1209 memset(conn, 0, sizeof(*conn));
1210 silc_client_del_connection(client, conn);
1213 silc_socket_free(sock);
1216 /* Called when we receive disconnection packet from server. This
1217 closes our end properly and displays the reason of the disconnection
1220 void silc_client_disconnected_by_server(SilcClient client,
1221 SilcSocketConnection sock,
1226 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1228 msg = silc_calloc(message->len + 1, sizeof(char));
1229 memcpy(msg, message->data, message->len);
1230 client->ops->say(client, sock->user_data, msg);
1233 SILC_SET_DISCONNECTED(sock);
1234 silc_client_close_connection(client, sock, sock->user_data);
1237 /* Received error message from server. Display it on the screen.
1238 We don't take any action what so ever of the error message. */
1240 void silc_client_error_by_server(SilcClient client,
1241 SilcSocketConnection sock,
1246 msg = silc_calloc(message->len + 1, sizeof(char));
1247 memcpy(msg, message->data, message->len);
1248 client->ops->say(client, sock->user_data, msg);
1252 /* Processes the received new Client ID from server. Old Client ID is
1253 deleted from cache and new one is added. */
1255 void silc_client_receive_new_id(SilcClient client,
1256 SilcSocketConnection sock,
1259 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1260 int connecting = FALSE;
1262 if (!conn->local_entry)
1265 /* Delete old ID from ID cache */
1266 if (conn->local_id) {
1267 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1268 silc_free(conn->local_id);
1271 /* Save the new ID */
1273 if (conn->local_id_data)
1274 silc_free(conn->local_id_data);
1276 conn->local_id = silc_id_payload_get_id(idp);
1277 conn->local_id_data = silc_id_payload_get_data(idp);
1278 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1280 if (!conn->local_entry)
1281 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1283 conn->local_entry->nickname = conn->nickname;
1284 if (!conn->local_entry->username) {
1285 conn->local_entry->username =
1286 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1287 sizeof(conn->local_entry->username));
1288 sprintf(conn->local_entry->username, "%s@%s", client->username,
1291 conn->local_entry->server = strdup(conn->remote_host);
1292 conn->local_entry->id = conn->local_id;
1294 /* Put it to the ID cache */
1295 silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
1296 (void *)conn->local_entry, FALSE);
1298 /* Notify application of successful connection. We do it here now that
1299 we've received the Client ID and are allowed to send traffic. */
1301 client->ops->connect(client, conn, TRUE);
1304 /* Processed received Channel ID for a channel. This is called when client
1305 joins to channel and server replies with channel ID. The ID is cached.
1306 Returns the created channel entry. */
1308 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1309 SilcSocketConnection sock,
1314 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1315 SilcChannelEntry channel;
1317 SILC_LOG_DEBUG(("New channel ID"));
1319 channel = silc_calloc(1, sizeof(*channel));
1320 channel->channel_name = channel_name;
1321 channel->id = silc_id_payload_get_id(idp);
1322 channel->mode = mode;
1323 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1325 conn->current_channel = channel;
1327 /* Put it to the ID cache */
1328 silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
1329 (void *)channel, FALSE);
1334 /* Removes a client entry from all channel it has joined. This really is
1335 a performance killer (client_entry should have pointers to channel
1338 void silc_client_remove_from_channels(SilcClient client,
1339 SilcClientConnection conn,
1340 SilcClientEntry client_entry)
1342 SilcIDCacheEntry id_cache;
1343 SilcIDCacheList list;
1344 SilcChannelEntry channel;
1345 SilcChannelUser chu;
1347 if (!silc_idcache_get_all(conn->channel_cache, &list))
1350 silc_idcache_list_first(list, &id_cache);
1351 channel = (SilcChannelEntry)id_cache->context;
1355 /* Remove client from channel */
1356 silc_list_start(channel->clients);
1357 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1358 if (chu->client == client_entry) {
1359 silc_list_del(channel->clients, chu);
1365 if (!silc_idcache_list_next(list, &id_cache))
1368 channel = (SilcChannelEntry)id_cache->context;
1371 silc_idcache_list_free(list);
1374 /* Replaces `old' client entries from all channels to `new' client entry.
1375 This can be called for example when nickname changes and old ID entry
1376 is replaced from ID cache with the new one. If the old ID entry is only
1377 updated, then this fucntion needs not to be called. */
1379 void silc_client_replace_from_channels(SilcClient client,
1380 SilcClientConnection conn,
1381 SilcClientEntry old,
1382 SilcClientEntry new)
1384 SilcIDCacheEntry id_cache;
1385 SilcIDCacheList list;
1386 SilcChannelEntry channel;
1387 SilcChannelUser chu;
1389 if (!silc_idcache_get_all(conn->channel_cache, &list))
1392 silc_idcache_list_first(list, &id_cache);
1393 channel = (SilcChannelEntry)id_cache->context;
1397 /* Replace client entry */
1398 silc_list_start(channel->clients);
1399 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1400 if (chu->client == old) {
1406 if (!silc_idcache_list_next(list, &id_cache))
1409 channel = (SilcChannelEntry)id_cache->context;
1412 silc_idcache_list_free(list);
1415 /* Registers failure timeout to process the received failure packet
1418 void silc_client_process_failure(SilcClient client,
1419 SilcSocketConnection sock,
1420 SilcPacketContext *packet)
1424 if (sock->protocol) {
1425 if (packet->buffer->len >= 4)
1426 SILC_GET32_MSB(failure, packet->buffer->data);
1428 /* Notify application */
1429 client->ops->failure(client, sock->user_data, sock->protocol,
1434 /* A timeout callback for the re-key. We will be the initiator of the
1437 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1439 SilcSocketConnection sock = (SilcSocketConnection)context;
1440 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1441 SilcClient client = (SilcClient)conn->rekey->context;
1442 SilcProtocol protocol;
1443 SilcClientRekeyInternalContext *proto_ctx;
1445 SILC_LOG_DEBUG(("Start"));
1447 /* Allocate internal protocol context. This is sent as context
1449 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1450 proto_ctx->client = (void *)client;
1451 proto_ctx->sock = silc_socket_dup(sock);
1452 proto_ctx->responder = FALSE;
1453 proto_ctx->pfs = conn->rekey->pfs;
1455 /* Perform rekey protocol. Will call the final callback after the
1456 protocol is over. */
1457 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1458 &protocol, proto_ctx, silc_client_rekey_final);
1459 sock->protocol = protocol;
1461 /* Run the protocol */
1462 silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1464 /* Re-register re-key timeout */
1465 silc_task_register(client->timeout_queue, sock->sock,
1466 silc_client_rekey_callback,
1467 context, conn->rekey->timeout, 0,
1468 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1471 /* The final callback for the REKEY protocol. This will actually take the
1472 new key material into use. */
1474 SILC_TASK_CALLBACK(silc_client_rekey_final)
1476 SilcProtocol protocol = (SilcProtocol)context;
1477 SilcClientRekeyInternalContext *ctx =
1478 (SilcClientRekeyInternalContext *)protocol->context;
1479 SilcClient client = (SilcClient)ctx->client;
1480 SilcSocketConnection sock = ctx->sock;
1482 SILC_LOG_DEBUG(("Start"));
1484 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1485 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1486 /* Error occured during protocol */
1487 silc_protocol_cancel(protocol, client->timeout_queue);
1488 silc_protocol_free(protocol);
1489 sock->protocol = NULL;
1491 silc_packet_context_free(ctx->packet);
1493 silc_ske_free(ctx->ske);
1494 silc_socket_free(ctx->sock);
1500 silc_protocol_free(protocol);
1501 sock->protocol = NULL;
1503 silc_packet_context_free(ctx->packet);
1505 silc_ske_free(ctx->ske);
1506 silc_socket_free(ctx->sock);