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,
44 SilcClientParams *params,
46 const char *silc_version)
48 SilcClient new_client;
50 new_client = silc_calloc(1, sizeof(*new_client));
51 new_client->application = application;
52 new_client->ops = ops;
53 new_client->silc_client_version = strdup(silc_version);
54 new_client->params = silc_calloc(1, sizeof(*new_client->params));
57 memcpy(new_client->params, params, sizeof(*params));
59 if (!new_client->params->rekey_secs)
60 new_client->params->rekey_secs = 3600;
65 /* Frees client object and its internals. */
67 void silc_client_free(SilcClient client)
71 silc_rng_free(client->rng);
73 silc_free(client->silc_client_version);
74 silc_free(client->params);
79 /* Initializes the client. This makes all the necessary steps to make
80 the client ready to be run. One must call silc_client_run to run the
81 client. Returns FALSE if error occured, TRUE otherwise. */
83 int silc_client_init(SilcClient client)
85 SILC_LOG_DEBUG(("Initializing client"));
87 /* Initialize hash functions for client to use */
88 silc_hash_alloc("md5", &client->md5hash);
89 silc_hash_alloc("sha1", &client->sha1hash);
91 /* Initialize none cipher */
92 silc_cipher_alloc("none", &client->none_cipher);
94 /* Initialize random number generator */
95 client->rng = silc_rng_alloc();
96 silc_rng_init(client->rng);
97 silc_rng_global_init(client->rng);
99 /* Register protocols */
100 silc_client_protocols_register();
102 /* Initialize the scheduler */
103 client->schedule = silc_schedule_init(200);
104 if (!client->schedule)
110 /* Stops the client. This is called to stop the client and thus to stop
113 void silc_client_stop(SilcClient client)
115 SILC_LOG_DEBUG(("Stopping client"));
117 silc_schedule_stop(client->schedule);
118 silc_schedule_uninit(client->schedule);
120 silc_client_protocols_unregister();
122 SILC_LOG_DEBUG(("Client stopped"));
125 /* Runs the client. This starts the scheduler from the utility library.
126 When this functions returns the execution of the appliation is over. */
128 void silc_client_run(SilcClient client)
130 SILC_LOG_DEBUG(("Running client"));
132 /* Start the scheduler, the heart of the SILC client. When this returns
133 the program will be terminated. */
134 silc_schedule(client->schedule);
137 /* Allocates and adds new connection to the client. This adds the allocated
138 connection to the connection table and returns a pointer to it. A client
139 can have multiple connections to multiple servers. Every connection must
140 be added to the client using this function. User data `context' may
141 be sent as argument. This function is normally used only if the
142 application performed the connecting outside the library. The library
143 however may use this internally. */
145 SilcClientConnection silc_client_add_connection(SilcClient client,
150 SilcClientConnection conn;
153 conn = silc_calloc(1, sizeof(*conn));
155 /* Initialize ID caches */
156 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
157 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
158 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
159 conn->client = client;
160 conn->remote_host = strdup(hostname);
161 conn->remote_port = port;
162 conn->context = context;
163 conn->pending_commands = silc_dlist_init();
165 /* Add the connection to connections table */
166 for (i = 0; i < client->conns_count; i++)
167 if (client->conns && !client->conns[i]) {
168 client->conns[i] = conn;
172 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
173 * (client->conns_count + 1));
174 client->conns[client->conns_count] = conn;
175 client->conns_count++;
180 /* Removes connection from client. Frees all memory. */
182 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
186 for (i = 0; i < client->conns_count; i++)
187 if (client->conns[i] == conn) {
188 if (conn->pending_commands)
189 silc_dlist_uninit(conn->pending_commands);
191 client->conns[i] = NULL;
195 /* Adds listener socket to the listener sockets table. This function is
196 used to add socket objects that are listeners to the client. This should
197 not be used to add other connection objects. */
199 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
203 if (!client->sockets) {
204 client->sockets = silc_calloc(1, sizeof(*client->sockets));
205 client->sockets[0] = silc_socket_dup(sock);
206 client->sockets_count = 1;
210 for (i = 0; i < client->sockets_count; i++) {
211 if (client->sockets[i] == NULL) {
212 client->sockets[i] = silc_socket_dup(sock);
217 client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
218 (client->sockets_count + 1));
219 client->sockets[client->sockets_count] = silc_socket_dup(sock);
220 client->sockets_count++;
223 /* Deletes listener socket from the listener sockets table. */
225 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
229 if (!client->sockets)
232 for (i = 0; i < client->sockets_count; i++) {
233 if (client->sockets[i] == sock) {
234 silc_socket_free(sock);
235 client->sockets[i] = NULL;
242 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
246 /* XXX In the future we should give up this non-blocking connect all
247 together and use threads instead. */
248 /* Create connection to server asynchronously */
249 sock = silc_net_create_connection_async(ctx->port, ctx->host);
253 /* Register task that will receive the async connect and will
255 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
256 silc_client_connect_to_server_start,
259 SILC_TASK_PRI_NORMAL);
260 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
267 /* Connects to remote server. This is the main routine used to connect
268 to SILC server. Returns -1 on error and the created socket otherwise.
269 The `context' is user context that is saved into the SilcClientConnection
270 that is created after the connection is created. Note that application
271 may handle the connecting process outside the library. If this is the
272 case then this function is not used at all. When the connecting is
273 done the `connect' client operation is called. */
275 int silc_client_connect_to_server(SilcClient client, int port,
276 char *host, void *context)
278 SilcClientInternalConnectContext *ctx;
279 SilcClientConnection conn;
282 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
285 conn = silc_client_add_connection(client, host, port, context);
287 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
288 "Connecting to port %d of server %s", port, host);
290 /* Allocate internal context for connection process. This is
291 needed as we are doing async connecting. */
292 ctx = silc_calloc(1, sizeof(*ctx));
293 ctx->client = client;
295 ctx->host = strdup(host);
299 /* Do the actual connecting process */
300 sock = silc_client_connect_to_server_internal(ctx);
302 silc_client_del_connection(client, conn);
306 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
307 key material between client and server. This function can be called
308 directly if application is performing its own connecting and does not
309 use the connecting provided by this library. This function is normally
310 used only if the application performed the connecting outside the library.
311 The library however may use this internally. */
313 int silc_client_start_key_exchange(SilcClient client,
314 SilcClientConnection conn,
317 SilcProtocol protocol;
318 SilcClientKEInternalContext *proto_ctx;
321 /* Allocate new socket connection object */
322 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
324 conn->nickname = strdup(client->username);
325 conn->sock->hostname = conn->remote_host;
326 conn->sock->ip = strdup(conn->remote_host);
327 conn->sock->port = conn->remote_port;
329 /* Allocate internal Key Exchange context. This is sent to the
330 protocol as context. */
331 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
332 proto_ctx->client = (void *)client;
333 proto_ctx->sock = silc_socket_dup(conn->sock);
334 proto_ctx->rng = client->rng;
335 proto_ctx->responder = FALSE;
336 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
337 proto_ctx->verify = silc_client_protocol_ke_verify_key;
339 /* Perform key exchange protocol. silc_client_connect_to_server_final
340 will be called after the protocol is finished. */
341 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
342 &protocol, (void *)proto_ctx,
343 silc_client_connect_to_server_second);
345 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
346 "Error: Could not start authentication protocol");
349 conn->sock->protocol = protocol;
351 /* Register the connection for network input and output. This sets
352 that scheduler will listen for incoming packets for this connection
353 and sets that outgoing packets may be sent to this connection as well.
354 However, this doesn't set the scheduler for outgoing traffic, it will
355 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
356 later when outgoing data is available. */
357 context = (void *)client;
358 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
360 /* Execute the protocol */
361 silc_protocol_execute(protocol, client->schedule, 0, 0);
365 /* Start of the connection to the remote server. This is called after
366 succesful TCP/IP connection has been established to the remote host. */
368 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
370 SilcClientInternalConnectContext *ctx =
371 (SilcClientInternalConnectContext *)context;
372 SilcClient client = ctx->client;
373 SilcClientConnection conn = ctx->conn;
374 int opt, opt_len = sizeof(opt);
376 SILC_LOG_DEBUG(("Start"));
378 /* Check the socket status as it might be in error */
379 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
381 if (ctx->tries < 2) {
382 /* Connection failed but lets try again */
383 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
384 "Could not connect to server %s: %s",
385 ctx->host, strerror(opt));
386 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
387 "Connecting to port %d of server %s resumed",
388 ctx->port, ctx->host);
390 /* Unregister old connection try */
391 silc_schedule_unset_listen_fd(client->schedule, fd);
392 silc_net_close_connection(fd);
393 silc_schedule_task_del(client->schedule, ctx->task);
396 silc_client_connect_to_server_internal(ctx);
399 /* Connection failed and we won't try anymore */
400 client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
401 "Could not connect to server %s: %s",
402 ctx->host, strerror(opt));
403 silc_schedule_unset_listen_fd(client->schedule, fd);
404 silc_net_close_connection(fd);
405 silc_schedule_task_del(client->schedule, ctx->task);
408 /* Notify application of failure */
409 client->ops->connect(client, conn, FALSE);
410 silc_client_del_connection(client, conn);
415 silc_schedule_unset_listen_fd(client->schedule, fd);
416 silc_schedule_task_del(client->schedule, ctx->task);
419 if (!silc_client_start_key_exchange(client, conn, fd)) {
420 silc_net_close_connection(fd);
421 client->ops->connect(client, conn, FALSE);
425 /* Second part of the connecting to the server. This executed
426 authentication protocol. */
428 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
430 SilcProtocol protocol = (SilcProtocol)context;
431 SilcClientKEInternalContext *ctx =
432 (SilcClientKEInternalContext *)protocol->context;
433 SilcClient client = (SilcClient)ctx->client;
434 SilcSocketConnection sock = NULL;
435 SilcClientConnAuthInternalContext *proto_ctx;
437 SILC_LOG_DEBUG(("Start"));
439 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
440 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
441 /* Error occured during protocol */
442 SILC_LOG_DEBUG(("Error during KE protocol"));
443 silc_protocol_free(protocol);
444 silc_ske_free_key_material(ctx->keymat);
446 silc_ske_free(ctx->ske);
448 silc_free(ctx->dest_id);
449 ctx->sock->protocol = NULL;
450 silc_socket_free(ctx->sock);
452 /* Notify application of failure */
453 client->ops->connect(client, ctx->sock->user_data, FALSE);
458 /* We now have the key material as the result of the key exchange
459 protocol. Take the key material into use. Free the raw key material
460 as soon as we've set them into use. */
461 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
462 ctx->ske->prop->cipher,
463 ctx->ske->prop->pkcs,
464 ctx->ske->prop->hash,
465 ctx->ske->prop->hmac,
466 ctx->ske->prop->group);
467 silc_ske_free_key_material(ctx->keymat);
469 /* Allocate internal context for the authentication protocol. This
470 is sent as context for the protocol. */
471 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
472 proto_ctx->client = (void *)client;
473 proto_ctx->sock = sock = ctx->sock;
474 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
475 proto_ctx->dest_id_type = ctx->dest_id_type;
476 proto_ctx->dest_id = ctx->dest_id;
478 /* Resolve the authentication method to be used in this connection */
479 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
480 sock->port, &proto_ctx->auth_meth,
481 &proto_ctx->auth_data,
482 &proto_ctx->auth_data_len))
483 proto_ctx->auth_meth = SILC_AUTH_NONE;
485 /* Free old protocol as it is finished now */
486 silc_protocol_free(protocol);
488 silc_packet_context_free(ctx->packet);
490 sock->protocol = NULL;
492 /* Allocate the authenteication protocol and execute it. */
493 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
494 &sock->protocol, (void *)proto_ctx,
495 silc_client_connect_to_server_final);
497 /* Execute the protocol */
498 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
501 /* Finalizes the connection to the remote SILC server. This is called
502 after authentication protocol has been completed. This send our
503 user information to the server to receive our client ID from
506 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
508 SilcProtocol protocol = (SilcProtocol)context;
509 SilcClientConnAuthInternalContext *ctx =
510 (SilcClientConnAuthInternalContext *)protocol->context;
511 SilcClient client = (SilcClient)ctx->client;
512 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
515 SILC_LOG_DEBUG(("Start"));
517 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
518 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
519 /* Error occured during protocol */
520 SILC_LOG_DEBUG(("Error during authentication protocol"));
521 silc_protocol_free(protocol);
523 silc_free(ctx->auth_data);
525 silc_ske_free(ctx->ske);
527 silc_free(ctx->dest_id);
528 conn->sock->protocol = NULL;
529 silc_socket_free(ctx->sock);
531 /* Notify application of failure */
532 client->ops->connect(client, ctx->sock->user_data, FALSE);
537 /* Send NEW_CLIENT packet to the server. We will become registered
538 to the SILC network after sending this packet and we will receive
539 client ID from the server. */
540 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
541 strlen(client->realname));
542 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
543 silc_buffer_format(packet,
544 SILC_STR_UI_SHORT(strlen(client->username)),
545 SILC_STR_UI_XNSTRING(client->username,
546 strlen(client->username)),
547 SILC_STR_UI_SHORT(strlen(client->realname)),
548 SILC_STR_UI_XNSTRING(client->realname,
549 strlen(client->realname)),
552 /* Send the packet */
553 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
555 packet->data, packet->len, TRUE);
556 silc_buffer_free(packet);
558 /* Save remote ID. */
559 conn->remote_id = ctx->dest_id;
560 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
561 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
563 /* Register re-key timeout */
564 conn->rekey->timeout = client->params->rekey_secs;
565 conn->rekey->context = (void *)client;
566 silc_schedule_task_add(client->schedule, conn->sock->sock,
567 silc_client_rekey_callback,
568 (void *)conn->sock, conn->rekey->timeout, 0,
569 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
571 silc_protocol_free(protocol);
573 silc_free(ctx->auth_data);
575 silc_ske_free(ctx->ske);
576 silc_socket_free(ctx->sock);
578 conn->sock->protocol = NULL;
581 /* Internal routine that sends packet or marks packet to be sent. This
582 is used directly only in special cases. Normal cases should use
583 silc_server_packet_send. Returns < 0 on error. */
585 int silc_client_packet_send_real(SilcClient client,
586 SilcSocketConnection sock,
592 /* If rekey protocol is active we must assure that all packets are
593 sent through packet queue. */
594 if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
597 /* Send the packet */
598 ret = silc_packet_send(sock, force_send);
602 /* Mark that there is some outgoing data available for this connection.
603 This call sets the connection both for input and output (the input
604 is set always and this call keeps the input setting, actually).
605 Actual data sending is performed by silc_client_packet_process. */
606 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
608 /* Mark to socket that data is pending in outgoing buffer. This flag
609 is needed if new data is added to the buffer before the earlier
610 put data is sent to the network. */
611 SILC_SET_OUTBUF_PENDING(sock);
616 /* Packet processing callback. This is used to send and receive packets
617 from network. This is generic task. */
619 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
621 SilcClient client = (SilcClient)context;
622 SilcSocketConnection sock = NULL;
623 SilcClientConnection conn;
626 SILC_LOG_DEBUG(("Processing packet"));
628 SILC_CLIENT_GET_SOCK(client, fd, sock);
632 conn = (SilcClientConnection)sock->user_data;
635 if (type == SILC_TASK_WRITE) {
636 SILC_LOG_DEBUG(("Writing data to connection"));
638 if (sock->outbuf->data - sock->outbuf->head)
639 silc_buffer_push(sock->outbuf,
640 sock->outbuf->data - sock->outbuf->head);
642 ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
644 /* If returned -2 could not write to connection now, will do
649 /* The packet has been sent and now it is time to set the connection
650 back to only for input. When there is again some outgoing data
651 available for this connection it will be set for output as well.
652 This call clears the output setting and sets it only for input. */
653 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
654 SILC_UNSET_OUTBUF_PENDING(sock);
656 silc_buffer_clear(sock->outbuf);
660 /* Packet receiving */
661 if (type == SILC_TASK_READ) {
662 SILC_LOG_DEBUG(("Reading data from connection"));
664 /* Read data from network */
665 ret = silc_packet_receive(sock);
671 SILC_LOG_DEBUG(("Read EOF"));
673 /* If connection is disconnecting already we will finally
674 close the connection */
675 if (SILC_IS_DISCONNECTING(sock)) {
676 if (sock == conn->sock)
677 client->ops->disconnect(client, conn);
678 silc_client_close_connection(client, sock, conn);
682 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
683 if (sock == conn->sock)
684 client->ops->disconnect(client, conn);
685 silc_client_close_connection(client, sock, conn);
689 /* Process the packet. This will call the parser that will then
690 decrypt and parse the packet. */
691 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
692 silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
693 silc_client_packet_parse, client);
695 silc_packet_receive_process(sock, NULL, NULL,
696 silc_client_packet_parse, client);
700 /* Callback function that the silc_packet_decrypt will call to make the
701 decision whether the packet is normal or special packet. We will
702 return TRUE if it is normal and FALSE if it is special */
704 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
706 SilcPacketContext *packet,
710 /* Packet is normal packet, if:
712 1) packet is private message packet and does not have private key set
713 2) is other packet than channel message packet
715 all other packets are special packets
718 if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
719 (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
722 if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
728 /* Parses whole packet, received earlier. */
730 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
732 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
733 SilcClient client = (SilcClient)parse_ctx->context;
734 SilcPacketContext *packet = parse_ctx->packet;
735 SilcBuffer buffer = packet->buffer;
736 SilcSocketConnection sock = parse_ctx->sock;
737 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
740 SILC_LOG_DEBUG(("Start"));
742 /* Decrypt the received packet */
743 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
744 ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive,
746 silc_client_packet_decrypt_check, parse_ctx);
748 ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
749 silc_client_packet_decrypt_check, parse_ctx);
755 /* Parse the packet. Packet type is returned. */
756 ret = silc_packet_parse(packet);
758 /* Parse the packet header in special way as this is "special"
760 ret = silc_packet_parse_special(packet);
763 if (ret == SILC_PACKET_NONE)
766 /* Parse the incoming packet type */
767 silc_client_packet_parse_type(client, sock, packet);
770 /* silc_buffer_clear(sock->inbuf); */
771 silc_packet_context_free(packet);
772 silc_free(parse_ctx);
775 /* Parser callback called by silc_packet_receive_process. Thie merely
776 registers timeout that will handle the actual parsing when appropriate. */
778 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
780 SilcClient client = (SilcClient)parser_context->context;
782 /* Parse the packet */
783 silc_schedule_task_add(client->schedule, parser_context->sock->sock,
784 silc_client_packet_parse_real,
785 (void *)parser_context, 0, 1,
787 SILC_TASK_PRI_NORMAL);
790 /* Parses the packet type and calls what ever routines the packet type
791 requires. This is done for all incoming packets. */
793 void silc_client_packet_parse_type(SilcClient client,
794 SilcSocketConnection sock,
795 SilcPacketContext *packet)
797 SilcBuffer buffer = packet->buffer;
798 SilcPacketType type = packet->type;
800 SILC_LOG_DEBUG(("Parsing packet type %d", type));
802 /* Parse the packet type */
804 case SILC_PACKET_DISCONNECT:
805 silc_client_disconnected_by_server(client, sock, buffer);
807 case SILC_PACKET_SUCCESS:
809 * Success received for something. For now we can have only
810 * one protocol for connection executing at once hence this
811 * success message is for whatever protocol is executing currently.
814 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
816 case SILC_PACKET_FAILURE:
818 * Failure received for some protocol. Set the protocol state to
819 * error and call the protocol callback. This fill cause error on
820 * protocol and it will call the final callback.
822 silc_client_process_failure(client, sock, packet);
824 case SILC_PACKET_REJECT:
827 case SILC_PACKET_NOTIFY:
829 * Received notify message
831 silc_client_notify_by_server(client, sock, packet);
834 case SILC_PACKET_ERROR:
836 * Received error message
838 silc_client_error_by_server(client, sock, buffer);
841 case SILC_PACKET_CHANNEL_MESSAGE:
843 * Received message to (from, actually) a channel
845 silc_client_channel_message(client, sock, packet);
847 case SILC_PACKET_CHANNEL_KEY:
849 * Received key for a channel. By receiving this key the client will be
850 * able to talk to the channel it has just joined. This can also be
851 * a new key for existing channel as keys expire peridiocally.
853 silc_client_receive_channel_key(client, sock, buffer);
856 case SILC_PACKET_PRIVATE_MESSAGE:
858 * Received private message
860 silc_client_private_message(client, sock, packet);
862 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
864 * Received private message key
868 case SILC_PACKET_COMMAND_REPLY:
870 * Recived reply for a command
872 silc_client_command_reply_process(client, sock, packet);
875 case SILC_PACKET_KEY_EXCHANGE:
876 if (sock->protocol && sock->protocol->protocol &&
877 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
878 SilcClientKEInternalContext *proto_ctx =
879 (SilcClientKEInternalContext *)sock->protocol->context;
881 proto_ctx->packet = silc_packet_context_dup(packet);
882 proto_ctx->dest_id_type = packet->src_id_type;
883 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
884 packet->src_id_type);
885 if (!proto_ctx->dest_id)
888 /* Let the protocol handle the packet */
889 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
891 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
892 "protocol active, packet dropped."));
896 case SILC_PACKET_KEY_EXCHANGE_1:
897 if (sock->protocol && sock->protocol->protocol &&
898 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
899 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
901 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
902 SilcClientRekeyInternalContext *proto_ctx =
903 (SilcClientRekeyInternalContext *)sock->protocol->context;
905 if (proto_ctx->packet)
906 silc_packet_context_free(proto_ctx->packet);
908 proto_ctx->packet = silc_packet_context_dup(packet);
910 /* Let the protocol handle the packet */
911 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
913 SilcClientKEInternalContext *proto_ctx =
914 (SilcClientKEInternalContext *)sock->protocol->context;
916 if (proto_ctx->packet)
917 silc_packet_context_free(proto_ctx->packet);
919 proto_ctx->packet = silc_packet_context_dup(packet);
920 proto_ctx->dest_id_type = packet->src_id_type;
921 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
922 packet->src_id_type);
923 if (!proto_ctx->dest_id)
926 /* Let the protocol handle the packet */
927 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
930 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
931 "protocol active, packet dropped."));
934 case SILC_PACKET_KEY_EXCHANGE_2:
935 if (sock->protocol && sock->protocol->protocol &&
936 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
937 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
939 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
940 SilcClientRekeyInternalContext *proto_ctx =
941 (SilcClientRekeyInternalContext *)sock->protocol->context;
943 if (proto_ctx->packet)
944 silc_packet_context_free(proto_ctx->packet);
946 proto_ctx->packet = silc_packet_context_dup(packet);
948 /* Let the protocol handle the packet */
949 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
951 SilcClientKEInternalContext *proto_ctx =
952 (SilcClientKEInternalContext *)sock->protocol->context;
954 if (proto_ctx->packet)
955 silc_packet_context_free(proto_ctx->packet);
957 proto_ctx->packet = silc_packet_context_dup(packet);
958 proto_ctx->dest_id_type = packet->src_id_type;
959 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
960 packet->src_id_type);
961 if (!proto_ctx->dest_id)
964 /* Let the protocol handle the packet */
965 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
968 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
969 "protocol active, packet dropped."));
973 case SILC_PACKET_NEW_ID:
976 * Received new ID from server. This packet is received at
977 * the connection to the server. New ID is also received when
978 * user changes nickname but in that case the new ID is received
979 * as command reply and not as this packet type.
983 idp = silc_id_payload_parse(buffer);
986 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
989 silc_client_receive_new_id(client, sock, idp);
990 silc_id_payload_free(idp);
994 case SILC_PACKET_HEARTBEAT:
996 * Received heartbeat packet
998 SILC_LOG_DEBUG(("Heartbeat packet"));
1001 case SILC_PACKET_KEY_AGREEMENT:
1003 * Received key agreement packet
1005 SILC_LOG_DEBUG(("Key agreement packet"));
1006 silc_client_key_agreement(client, sock, packet);
1009 case SILC_PACKET_REKEY:
1010 SILC_LOG_DEBUG(("Re-key packet"));
1011 /* We ignore this for now */
1014 case SILC_PACKET_REKEY_DONE:
1015 SILC_LOG_DEBUG(("Re-key done packet"));
1017 if (sock->protocol && sock->protocol->protocol &&
1018 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1020 SilcClientRekeyInternalContext *proto_ctx =
1021 (SilcClientRekeyInternalContext *)sock->protocol->context;
1023 if (proto_ctx->packet)
1024 silc_packet_context_free(proto_ctx->packet);
1026 proto_ctx->packet = silc_packet_context_dup(packet);
1028 /* Let the protocol handle the packet */
1029 if (proto_ctx->responder == FALSE)
1030 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1032 /* Let the protocol handle the packet */
1033 silc_protocol_execute(sock->protocol, client->schedule,
1036 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1037 "protocol active, packet dropped."));
1042 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1047 /* Sends packet. This doesn't actually send the packet instead it assembles
1048 it and marks it to be sent. However, if force_send is TRUE the packet
1049 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1050 will be derived from sock argument. Otherwise the valid arguments sent
1053 void silc_client_packet_send(SilcClient client,
1054 SilcSocketConnection sock,
1055 SilcPacketType type,
1057 SilcIdType dst_id_type,
1060 unsigned char *data,
1064 SilcPacketContext packetdata;
1069 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1071 /* Get data used in the packet sending, keys and stuff */
1072 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1073 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1074 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1076 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1077 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1079 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1080 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1081 dst_id_type = SILC_ID_SERVER;
1085 /* Set the packet context pointers */
1086 packetdata.flags = 0;
1087 packetdata.type = type;
1088 if (sock->user_data &&
1089 ((SilcClientConnection)sock->user_data)->local_id_data) {
1090 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1091 packetdata.src_id_len =
1092 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1095 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1096 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1098 packetdata.src_id_type = SILC_ID_CLIENT;
1100 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1101 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1102 packetdata.dst_id_type = dst_id_type;
1104 packetdata.dst_id = NULL;
1105 packetdata.dst_id_len = 0;
1106 packetdata.dst_id_type = SILC_ID_NONE;
1108 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1109 packetdata.src_id_len + packetdata.dst_id_len;
1110 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1112 /* Prepare outgoing data buffer for packet sending */
1113 silc_packet_send_prepare(sock,
1114 SILC_PACKET_HEADER_LEN +
1115 packetdata.src_id_len +
1116 packetdata.dst_id_len,
1120 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1122 packetdata.buffer = sock->outbuf;
1124 /* Put the data to the buffer */
1125 if (data && data_len)
1126 silc_buffer_put(sock->outbuf, data, data_len);
1128 /* Create the outgoing packet */
1129 silc_packet_assemble(&packetdata);
1131 /* Encrypt the packet */
1133 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1135 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1136 sock->outbuf->data, sock->outbuf->len);
1138 /* Now actually send the packet */
1139 silc_client_packet_send_real(client, sock, force_send, FALSE);
1142 /* Closes connection to remote end. Free's all allocated data except
1143 for some information such as nickname etc. that are valid at all time.
1144 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1145 provided it will be checked whether the sock and `conn->sock' are the
1146 same (they can be different, ie. a socket can use `conn' as its
1147 connection but `conn->sock' might be actually a different connection
1148 than the `sock'). */
1150 void silc_client_close_connection(SilcClient client,
1151 SilcSocketConnection sock,
1152 SilcClientConnection conn)
1156 if (!sock || (sock && conn->sock == sock))
1161 /* We won't listen for this connection anymore */
1162 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1164 /* Unregister all tasks */
1165 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1166 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1168 /* Close the actual connection */
1169 silc_net_close_connection(sock->sock);
1171 /* Cancel any active protocol */
1172 if (sock->protocol) {
1173 if (sock->protocol->protocol->type ==
1174 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1175 sock->protocol->protocol->type ==
1176 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1177 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1178 silc_protocol_execute_final(sock->protocol, client->schedule);
1179 sock->protocol = NULL;
1180 /* The application will recall this function with these protocols
1181 (the ops->connect client operation). */
1184 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1185 silc_protocol_execute_final(sock->protocol, client->schedule);
1186 sock->protocol = NULL;
1190 /* Free everything */
1191 if (del && sock->user_data) {
1192 /* XXX Free all client entries and channel entries. */
1194 /* Clear ID caches */
1195 if (conn->client_cache)
1196 silc_idcache_del_all(conn->client_cache);
1197 if (conn->channel_cache)
1198 silc_idcache_del_all(conn->channel_cache);
1199 if (conn->server_cache)
1200 silc_idcache_del_all(conn->server_cache);
1203 if (conn->remote_host)
1204 silc_free(conn->remote_host);
1206 silc_free(conn->local_id);
1207 if (conn->local_id_data)
1208 silc_free(conn->local_id_data);
1210 silc_cipher_free(conn->send_key);
1211 if (conn->receive_key)
1212 silc_cipher_free(conn->receive_key);
1213 if (conn->hmac_send) /* conn->hmac_receive is same */
1214 silc_hmac_free(conn->hmac_send);
1215 if (conn->pending_commands)
1216 silc_dlist_uninit(conn->pending_commands);
1218 silc_free(conn->rekey);
1220 memset(conn, 0, sizeof(*conn));
1221 silc_client_del_connection(client, conn);
1224 silc_socket_free(sock);
1227 /* Called when we receive disconnection packet from server. This
1228 closes our end properly and displays the reason of the disconnection
1231 void silc_client_disconnected_by_server(SilcClient client,
1232 SilcSocketConnection sock,
1237 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1239 msg = silc_calloc(message->len + 1, sizeof(char));
1240 memcpy(msg, message->data, message->len);
1241 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1244 SILC_SET_DISCONNECTED(sock);
1245 silc_client_close_connection(client, sock, sock->user_data);
1248 /* Received error message from server. Display it on the screen.
1249 We don't take any action what so ever of the error message. */
1251 void silc_client_error_by_server(SilcClient client,
1252 SilcSocketConnection sock,
1257 msg = silc_calloc(message->len + 1, sizeof(char));
1258 memcpy(msg, message->data, message->len);
1259 client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
1263 /* Processes the received new Client ID from server. Old Client ID is
1264 deleted from cache and new one is added. */
1266 void silc_client_receive_new_id(SilcClient client,
1267 SilcSocketConnection sock,
1270 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1271 int connecting = FALSE;
1274 if (!conn->local_entry)
1277 /* Delete old ID from ID cache */
1278 if (conn->local_id) {
1279 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1280 silc_free(conn->local_id);
1283 /* Save the new ID */
1285 if (conn->local_id_data)
1286 silc_free(conn->local_id_data);
1288 conn->local_id = silc_id_payload_get_id(idp);
1289 conn->local_id_data = silc_id_payload_get_data(idp);
1290 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1292 if (!conn->local_entry)
1293 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1295 conn->local_entry->nickname = conn->nickname;
1296 if (!conn->local_entry->username) {
1297 conn->local_entry->username =
1298 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1299 sizeof(conn->local_entry->username));
1300 sprintf(conn->local_entry->username, "%s@%s", client->username,
1303 conn->local_entry->server = strdup(conn->remote_host);
1304 conn->local_entry->id = conn->local_id;
1306 /* Put it to the ID cache */
1307 silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
1308 (void *)conn->local_entry, FALSE);
1310 /* Issue INFO command to fetch the real server name and server information
1312 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1313 silc_client_send_command(client, conn, SILC_COMMAND_INFO,
1314 ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1315 silc_buffer_free(sidp);
1317 /* Notify application of successful connection. We do it here now that
1318 we've received the Client ID and are allowed to send traffic. */
1320 client->ops->connect(client, conn, TRUE);
1323 /* Processed received Channel ID for a channel. This is called when client
1324 joins to channel and server replies with channel ID. The ID is cached.
1325 Returns the created channel entry. This is also called when received
1326 channel ID in for example USERS command reply that we do not have. */
1328 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1329 SilcSocketConnection sock,
1334 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1335 SilcChannelEntry channel;
1337 SILC_LOG_DEBUG(("New channel ID"));
1339 channel = silc_calloc(1, sizeof(*channel));
1340 channel->channel_name = channel_name;
1341 channel->id = silc_id_payload_get_id(idp);
1342 channel->mode = mode;
1343 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1345 /* Put it to the ID cache */
1346 silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
1347 (void *)channel, FALSE);
1352 /* Removes a client entry from all channel it has joined. This really is
1353 a performance killer (client_entry should have pointers to channel
1356 void silc_client_remove_from_channels(SilcClient client,
1357 SilcClientConnection conn,
1358 SilcClientEntry client_entry)
1360 SilcIDCacheEntry id_cache;
1361 SilcIDCacheList list;
1362 SilcChannelEntry channel;
1363 SilcChannelUser chu;
1365 if (!silc_idcache_get_all(conn->channel_cache, &list))
1368 silc_idcache_list_first(list, &id_cache);
1369 channel = (SilcChannelEntry)id_cache->context;
1373 /* Remove client from channel */
1374 silc_list_start(channel->clients);
1375 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1376 if (chu->client == client_entry) {
1377 silc_list_del(channel->clients, chu);
1383 if (!silc_idcache_list_next(list, &id_cache))
1386 channel = (SilcChannelEntry)id_cache->context;
1389 silc_idcache_list_free(list);
1392 /* Replaces `old' client entries from all channels to `new' client entry.
1393 This can be called for example when nickname changes and old ID entry
1394 is replaced from ID cache with the new one. If the old ID entry is only
1395 updated, then this fucntion needs not to be called. */
1397 void silc_client_replace_from_channels(SilcClient client,
1398 SilcClientConnection conn,
1399 SilcClientEntry old,
1400 SilcClientEntry new)
1402 SilcIDCacheEntry id_cache;
1403 SilcIDCacheList list;
1404 SilcChannelEntry channel;
1405 SilcChannelUser chu;
1407 if (!silc_idcache_get_all(conn->channel_cache, &list))
1410 silc_idcache_list_first(list, &id_cache);
1411 channel = (SilcChannelEntry)id_cache->context;
1415 /* Replace client entry */
1416 silc_list_start(channel->clients);
1417 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1418 if (chu->client == old) {
1424 if (!silc_idcache_list_next(list, &id_cache))
1427 channel = (SilcChannelEntry)id_cache->context;
1430 silc_idcache_list_free(list);
1433 /* Registers failure timeout to process the received failure packet
1436 void silc_client_process_failure(SilcClient client,
1437 SilcSocketConnection sock,
1438 SilcPacketContext *packet)
1442 if (sock->protocol) {
1443 if (packet->buffer->len >= 4)
1444 SILC_GET32_MSB(failure, packet->buffer->data);
1446 /* Notify application */
1447 client->ops->failure(client, sock->user_data, sock->protocol,
1452 /* A timeout callback for the re-key. We will be the initiator of the
1455 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1457 SilcSocketConnection sock = (SilcSocketConnection)context;
1458 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1459 SilcClient client = (SilcClient)conn->rekey->context;
1460 SilcProtocol protocol;
1461 SilcClientRekeyInternalContext *proto_ctx;
1463 SILC_LOG_DEBUG(("Start"));
1465 /* Allocate internal protocol context. This is sent as context
1467 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1468 proto_ctx->client = (void *)client;
1469 proto_ctx->sock = silc_socket_dup(sock);
1470 proto_ctx->responder = FALSE;
1471 proto_ctx->pfs = conn->rekey->pfs;
1473 /* Perform rekey protocol. Will call the final callback after the
1474 protocol is over. */
1475 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1476 &protocol, proto_ctx, silc_client_rekey_final);
1477 sock->protocol = protocol;
1479 /* Run the protocol */
1480 silc_protocol_execute(protocol, client->schedule, 0, 0);
1482 /* Re-register re-key timeout */
1483 silc_schedule_task_add(client->schedule, sock->sock,
1484 silc_client_rekey_callback,
1485 context, conn->rekey->timeout, 0,
1486 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1489 /* The final callback for the REKEY protocol. This will actually take the
1490 new key material into use. */
1492 SILC_TASK_CALLBACK(silc_client_rekey_final)
1494 SilcProtocol protocol = (SilcProtocol)context;
1495 SilcClientRekeyInternalContext *ctx =
1496 (SilcClientRekeyInternalContext *)protocol->context;
1497 SilcClient client = (SilcClient)ctx->client;
1498 SilcSocketConnection sock = ctx->sock;
1500 SILC_LOG_DEBUG(("Start"));
1502 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1503 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1504 /* Error occured during protocol */
1505 silc_protocol_cancel(protocol, client->schedule);
1506 silc_protocol_free(protocol);
1507 sock->protocol = NULL;
1509 silc_packet_context_free(ctx->packet);
1511 silc_ske_free(ctx->ske);
1512 silc_socket_free(ctx->sock);
1518 silc_protocol_free(protocol);
1519 sock->protocol = NULL;
1521 silc_packet_context_free(ctx->packet);
1523 silc_ske_free(ctx->ske);
1524 silc_socket_free(ctx->sock);