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_rekey_callback);
30 SILC_TASK_CALLBACK(silc_client_rekey_final);
32 static bool 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;
57 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
58 new_client->internal->ops = ops;
59 new_client->internal->params =
60 silc_calloc(1, sizeof(*new_client->internal->params));
61 new_client->internal->silc_client_version = strdup(silc_version);
64 memcpy(new_client->internal->params, params, sizeof(*params));
66 if (!new_client->internal->params->task_max)
67 new_client->internal->params->task_max = 200;
69 if (!new_client->internal->params->rekey_secs)
70 new_client->internal->params->rekey_secs = 3600;
72 if (!new_client->internal->params->connauth_request_secs)
73 new_client->internal->params->connauth_request_secs = 2;
75 new_client->internal->params->
76 nickname_format[sizeof(new_client->internal->
77 params->nickname_format) - 1] = 0;
82 /* Frees client object and its internals. */
84 void silc_client_free(SilcClient client)
88 silc_rng_free(client->rng);
90 silc_free(client->internal->params);
91 silc_free(client->internal->silc_client_version);
92 silc_free(client->internal);
97 /* Initializes the client. This makes all the necessary steps to make
98 the client ready to be run. One must call silc_client_run to run the
99 client. Returns FALSE if error occured, TRUE otherwise. */
101 int silc_client_init(SilcClient client)
103 SILC_LOG_DEBUG(("Initializing client"));
105 /* Initialize hash functions for client to use */
106 silc_hash_alloc("md5", &client->internal->md5hash);
107 silc_hash_alloc("sha1", &client->internal->sha1hash);
109 /* Initialize none cipher */
110 silc_cipher_alloc("none", &client->internal->none_cipher);
112 /* Initialize random number generator */
113 client->rng = silc_rng_alloc();
114 silc_rng_init(client->rng);
115 silc_rng_global_init(client->rng);
117 /* Register protocols */
118 silc_client_protocols_register();
120 /* Initialize the scheduler */
122 silc_schedule_init(client->internal->params->task_max ?
123 client->internal->params->task_max : 200);
124 if (!client->schedule)
127 /* Register commands */
128 silc_client_commands_register(client);
133 /* Stops the client. This is called to stop the client and thus to stop
136 void silc_client_stop(SilcClient client)
138 SILC_LOG_DEBUG(("Stopping client"));
140 silc_schedule_stop(client->schedule);
141 silc_schedule_uninit(client->schedule);
143 silc_client_protocols_unregister();
144 silc_client_commands_unregister(client);
146 SILC_LOG_DEBUG(("Client stopped"));
149 /* Runs the client. This starts the scheduler from the utility library.
150 When this functions returns the execution of the appliation is over. */
152 void silc_client_run(SilcClient client)
154 SILC_LOG_DEBUG(("Running client"));
156 /* Start the scheduler, the heart of the SILC client. When this returns
157 the program will be terminated. */
158 silc_schedule(client->schedule);
161 /* Runs the client and returns immeadiately. This function is used when
162 the SILC Client object indicated by the `client' is run under some
163 other scheduler, or event loop or main loop. On GUI applications,
164 for example this may be desired to use to run the client under the
165 GUI application's main loop. Typically the GUI application would
166 register an idle task that calls this function multiple times in
167 a second to quickly process the SILC specific data. */
169 void silc_client_run_one(SilcClient client)
171 /* Run the scheduler once. */
172 silc_schedule_one(client->schedule, 0);
175 static void silc_client_entry_destructor(SilcIDCache cache,
176 SilcIDCacheEntry entry)
178 silc_free(entry->name);
181 /* Allocates and adds new connection to the client. This adds the allocated
182 connection to the connection table and returns a pointer to it. A client
183 can have multiple connections to multiple servers. Every connection must
184 be added to the client using this function. User data `context' may
185 be sent as argument. This function is normally used only if the
186 application performed the connecting outside the library. The library
187 however may use this internally. */
189 SilcClientConnection silc_client_add_connection(SilcClient client,
194 SilcClientConnection conn;
197 conn = silc_calloc(1, sizeof(*conn));
199 /* Initialize ID caches */
200 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
201 silc_client_entry_destructor);
202 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
203 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
204 conn->client = client;
205 conn->remote_host = strdup(hostname);
206 conn->remote_port = port;
207 conn->context = context;
208 conn->pending_commands = silc_dlist_init();
209 conn->ftp_sessions = silc_dlist_init();
211 /* Add the connection to connections table */
212 for (i = 0; i < client->internal->conns_count; i++)
213 if (client->internal->conns && !client->internal->conns[i]) {
214 client->internal->conns[i] = conn;
218 client->internal->conns =
219 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
220 * (client->internal->conns_count + 1));
221 client->internal->conns[client->internal->conns_count] = conn;
222 client->internal->conns_count++;
227 /* Removes connection from client. Frees all memory. */
229 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
233 for (i = 0; i < client->internal->conns_count; i++)
234 if (client->internal->conns[i] == conn) {
236 silc_idcache_free(conn->client_cache);
237 silc_idcache_free(conn->channel_cache);
238 silc_idcache_free(conn->server_cache);
239 if (conn->pending_commands)
240 silc_dlist_uninit(conn->pending_commands);
241 silc_free(conn->remote_host);
242 silc_dlist_uninit(conn->ftp_sessions);
245 client->internal->conns[i] = NULL;
249 /* Adds listener socket to the listener sockets table. This function is
250 used to add socket objects that are listeners to the client. This should
251 not be used to add other connection objects. */
253 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
257 if (!client->internal->sockets) {
258 client->internal->sockets =
259 silc_calloc(1, sizeof(*client->internal->sockets));
260 client->internal->sockets[0] = silc_socket_dup(sock);
261 client->internal->sockets_count = 1;
265 for (i = 0; i < client->internal->sockets_count; i++) {
266 if (client->internal->sockets[i] == NULL) {
267 client->internal->sockets[i] = silc_socket_dup(sock);
272 client->internal->sockets =
273 silc_realloc(client->internal->sockets,
274 sizeof(*client->internal->sockets) *
275 (client->internal->sockets_count + 1));
276 client->internal->sockets[client->internal->sockets_count] =
277 silc_socket_dup(sock);
278 client->internal->sockets_count++;
281 /* Deletes listener socket from the listener sockets table. */
283 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
287 if (!client->internal->sockets)
290 for (i = 0; i < client->internal->sockets_count; i++) {
291 if (client->internal->sockets[i] == sock) {
292 silc_socket_free(sock);
293 client->internal->sockets[i] = NULL;
300 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
304 /* XXX In the future we should give up this non-blocking connect all
305 together and use threads instead. */
306 /* Create connection to server asynchronously */
307 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
311 /* Register task that will receive the async connect and will
313 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
314 silc_client_connect_to_server_start,
317 SILC_TASK_PRI_NORMAL);
318 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
325 /* Connects to remote server. This is the main routine used to connect
326 to SILC server. Returns -1 on error and the created socket otherwise.
327 The `context' is user context that is saved into the SilcClientConnection
328 that is created after the connection is created. Note that application
329 may handle the connecting process outside the library. If this is the
330 case then this function is not used at all. When the connecting is
331 done the `connect' client operation is called. */
333 int silc_client_connect_to_server(SilcClient client, int port,
334 char *host, void *context)
336 SilcClientInternalConnectContext *ctx;
337 SilcClientConnection conn;
340 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
343 conn = silc_client_add_connection(client, host, port, context);
345 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
346 "Connecting to port %d of server %s", port, host);
348 /* Allocate internal context for connection process. This is
349 needed as we are doing async connecting. */
350 ctx = silc_calloc(1, sizeof(*ctx));
351 ctx->client = client;
353 ctx->host = strdup(host);
357 /* Do the actual connecting process */
358 sock = silc_client_connect_to_server_internal(ctx);
360 silc_client_del_connection(client, conn);
364 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
365 key material between client and server. This function can be called
366 directly if application is performing its own connecting and does not
367 use the connecting provided by this library. This function is normally
368 used only if the application performed the connecting outside the library.
369 The library however may use this internally. */
371 bool silc_client_start_key_exchange(SilcClient client,
372 SilcClientConnection conn,
375 SilcProtocol protocol;
376 SilcClientKEInternalContext *proto_ctx;
379 /* Allocate new socket connection object */
380 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
382 /* Sometimes when doing quick reconnects the new socket may be same as
383 the old one and there might be pending stuff for the old socket.
384 If new one is same then those pending sutff might cause problems.
385 Make sure they do not do that. */
386 silc_schedule_task_del_by_fd(client->schedule, fd);
388 conn->nickname = strdup(client->username);
389 conn->sock->hostname = strdup(conn->remote_host);
390 conn->sock->ip = strdup(conn->remote_host);
391 conn->sock->port = conn->remote_port;
393 /* Allocate internal Key Exchange context. This is sent to the
394 protocol as context. */
395 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
396 proto_ctx->client = (void *)client;
397 proto_ctx->sock = silc_socket_dup(conn->sock);
398 proto_ctx->rng = client->rng;
399 proto_ctx->responder = FALSE;
400 proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
401 proto_ctx->verify = silc_client_protocol_ke_verify_key;
403 /* Perform key exchange protocol. silc_client_connect_to_server_final
404 will be called after the protocol is finished. */
405 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
406 &protocol, (void *)proto_ctx,
407 silc_client_connect_to_server_second);
409 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
410 "Error: Could not start key exchange protocol");
413 conn->sock->protocol = protocol;
415 /* Register the connection for network input and output. This sets
416 that scheduler will listen for incoming packets for this connection
417 and sets that outgoing packets may be sent to this connection as well.
418 However, this doesn't set the scheduler for outgoing traffic, it will
419 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
420 later when outgoing data is available. */
421 context = (void *)client;
422 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
424 /* Execute the protocol */
425 silc_protocol_execute(protocol, client->schedule, 0, 0);
429 /* Callback called when error has occurred during connecting to the server.
430 The `connect' client operation will be called. */
432 SILC_TASK_CALLBACK(silc_client_connect_failure)
434 SilcClientKEInternalContext *ctx =
435 (SilcClientKEInternalContext *)context;
436 SilcClient client = (SilcClient)ctx->client;
438 client->internal->ops->connect(client, ctx->sock->user_data, FALSE);
442 /* Start of the connection to the remote server. This is called after
443 succesful TCP/IP connection has been established to the remote host. */
445 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
447 SilcClientInternalConnectContext *ctx =
448 (SilcClientInternalConnectContext *)context;
449 SilcClient client = ctx->client;
450 SilcClientConnection conn = ctx->conn;
451 int opt, opt_len = sizeof(opt);
453 SILC_LOG_DEBUG(("Start"));
455 /* Check the socket status as it might be in error */
456 silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
458 if (ctx->tries < 2) {
459 /* Connection failed but lets try again */
460 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
461 "Could not connect to server %s: %s",
462 ctx->host, strerror(opt));
463 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
464 "Connecting to port %d of server %s resumed",
465 ctx->port, ctx->host);
467 /* Unregister old connection try */
468 silc_schedule_unset_listen_fd(client->schedule, fd);
469 silc_net_close_connection(fd);
470 silc_schedule_task_del(client->schedule, ctx->task);
473 silc_client_connect_to_server_internal(ctx);
476 /* Connection failed and we won't try anymore */
477 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
478 "Could not connect to server %s: %s",
479 ctx->host, strerror(opt));
480 silc_schedule_unset_listen_fd(client->schedule, fd);
481 silc_net_close_connection(fd);
482 silc_schedule_task_del(client->schedule, ctx->task);
485 /* Notify application of failure */
486 client->internal->ops->connect(client, conn, FALSE);
487 silc_client_del_connection(client, conn);
492 silc_schedule_unset_listen_fd(client->schedule, fd);
493 silc_schedule_task_del(client->schedule, ctx->task);
496 if (!silc_client_start_key_exchange(client, conn, fd)) {
497 silc_net_close_connection(fd);
498 client->internal->ops->connect(client, conn, FALSE);
502 /* Second part of the connecting to the server. This executed
503 authentication protocol. */
505 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
507 SilcProtocol protocol = (SilcProtocol)context;
508 SilcClientKEInternalContext *ctx =
509 (SilcClientKEInternalContext *)protocol->context;
510 SilcClient client = (SilcClient)ctx->client;
511 SilcSocketConnection sock = NULL;
512 SilcClientConnAuthInternalContext *proto_ctx;
514 SILC_LOG_DEBUG(("Start"));
516 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
517 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
518 /* Error occured during protocol */
519 SILC_LOG_DEBUG(("Error during KE protocol"));
520 silc_protocol_free(protocol);
521 silc_ske_free_key_material(ctx->keymat);
523 silc_ske_free(ctx->ske);
525 silc_free(ctx->dest_id);
526 ctx->sock->protocol = NULL;
527 silc_socket_free(ctx->sock);
529 /* Notify application of failure */
530 silc_schedule_task_add(client->schedule, ctx->sock->sock,
531 silc_client_connect_failure, ctx,
532 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
536 /* We now have the key material as the result of the key exchange
537 protocol. Take the key material into use. Free the raw key material
538 as soon as we've set them into use. */
539 silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
540 ctx->ske->prop->cipher,
541 ctx->ske->prop->pkcs,
542 ctx->ske->prop->hash,
543 ctx->ske->prop->hmac,
544 ctx->ske->prop->group,
546 silc_ske_free_key_material(ctx->keymat);
548 /* Allocate internal context for the authentication protocol. This
549 is sent as context for the protocol. */
550 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
551 proto_ctx->client = (void *)client;
552 proto_ctx->sock = sock = ctx->sock;
553 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
554 proto_ctx->dest_id_type = ctx->dest_id_type;
555 proto_ctx->dest_id = ctx->dest_id;
557 /* Free old protocol as it is finished now */
558 silc_protocol_free(protocol);
560 silc_packet_context_free(ctx->packet);
562 sock->protocol = NULL;
564 /* Resolve the authentication method to be used in this connection. The
565 completion callback is called after the application has resolved
566 the authentication method. */
567 client->internal->ops->get_auth_method(client, sock->user_data,
570 silc_client_resolve_auth_method,
574 /* Authentication method resolving callback. Application calls this function
575 after we've called the client->internal->ops->get_auth_method
576 client operation to resolve the authentication method. We will continue
577 the executiong of the protocol in this function. */
579 void silc_client_resolve_auth_method(bool success,
580 SilcProtocolAuthMeth auth_meth,
581 const unsigned char *auth_data,
582 uint32 auth_data_len, void *context)
584 SilcClientConnAuthInternalContext *proto_ctx =
585 (SilcClientConnAuthInternalContext *)context;
586 SilcClient client = (SilcClient)proto_ctx->client;
589 auth_meth = SILC_AUTH_NONE;
591 proto_ctx->auth_meth = auth_meth;
593 if (auth_data && auth_data_len) {
594 proto_ctx->auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
595 memcpy(proto_ctx->auth_data, auth_data, auth_data_len);
596 proto_ctx->auth_data_len = auth_data_len;
599 /* Allocate the authenteication protocol and execute it. */
600 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
601 &proto_ctx->sock->protocol, (void *)proto_ctx,
602 silc_client_connect_to_server_final);
604 /* Execute the protocol */
605 silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
608 /* Finalizes the connection to the remote SILC server. This is called
609 after authentication protocol has been completed. This send our
610 user information to the server to receive our client ID from
613 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
615 SilcProtocol protocol = (SilcProtocol)context;
616 SilcClientConnAuthInternalContext *ctx =
617 (SilcClientConnAuthInternalContext *)protocol->context;
618 SilcClient client = (SilcClient)ctx->client;
619 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
622 SILC_LOG_DEBUG(("Start"));
624 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
625 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
626 /* Error occured during protocol */
627 SILC_LOG_DEBUG(("Error during authentication protocol"));
628 silc_protocol_free(protocol);
630 silc_free(ctx->auth_data);
632 silc_ske_free(ctx->ske);
634 silc_free(ctx->dest_id);
635 conn->sock->protocol = NULL;
636 silc_socket_free(ctx->sock);
638 /* Notify application of failure */
639 silc_schedule_task_add(client->schedule, ctx->sock->sock,
640 silc_client_connect_failure, ctx,
641 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
645 /* Send NEW_CLIENT packet to the server. We will become registered
646 to the SILC network after sending this packet and we will receive
647 client ID from the server. */
648 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
649 strlen(client->realname));
650 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
651 silc_buffer_format(packet,
652 SILC_STR_UI_SHORT(strlen(client->username)),
653 SILC_STR_UI_XNSTRING(client->username,
654 strlen(client->username)),
655 SILC_STR_UI_SHORT(strlen(client->realname)),
656 SILC_STR_UI_XNSTRING(client->realname,
657 strlen(client->realname)),
660 /* Send the packet */
661 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
663 packet->data, packet->len, TRUE);
664 silc_buffer_free(packet);
666 /* Save remote ID. */
667 conn->remote_id = ctx->dest_id;
668 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
669 conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
671 /* Register re-key timeout */
672 conn->rekey->timeout = client->internal->params->rekey_secs;
673 conn->rekey->context = (void *)client;
674 silc_schedule_task_add(client->schedule, conn->sock->sock,
675 silc_client_rekey_callback,
676 (void *)conn->sock, conn->rekey->timeout, 0,
677 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
679 silc_protocol_free(protocol);
681 silc_free(ctx->auth_data);
683 silc_ske_free(ctx->ske);
684 silc_socket_free(ctx->sock);
686 conn->sock->protocol = NULL;
689 /* Internal routine that sends packet or marks packet to be sent. This
690 is used directly only in special cases. Normal cases should use
691 silc_server_packet_send. Returns < 0 on error. */
693 int silc_client_packet_send_real(SilcClient client,
694 SilcSocketConnection sock,
699 /* If rekey protocol is active we must assure that all packets are
700 sent through packet queue. */
701 if (SILC_CLIENT_IS_REKEY(sock))
704 /* If outbound data is already pending do not force send */
705 if (SILC_IS_OUTBUF_PENDING(sock))
708 /* Send the packet */
709 ret = silc_packet_send(sock, force_send);
713 /* Mark that there is some outgoing data available for this connection.
714 This call sets the connection both for input and output (the input
715 is set always and this call keeps the input setting, actually).
716 Actual data sending is performed by silc_client_packet_process. */
717 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
719 /* Mark to socket that data is pending in outgoing buffer. This flag
720 is needed if new data is added to the buffer before the earlier
721 put data is sent to the network. */
722 SILC_SET_OUTBUF_PENDING(sock);
727 /* Packet processing callback. This is used to send and receive packets
728 from network. This is generic task. */
730 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
732 SilcClient client = (SilcClient)context;
733 SilcSocketConnection sock = NULL;
734 SilcClientConnection conn;
737 SILC_LOG_DEBUG(("Processing packet"));
739 SILC_CLIENT_GET_SOCK(client, fd, sock);
743 conn = (SilcClientConnection)sock->user_data;
746 if (type == SILC_TASK_WRITE) {
747 /* Do not send data to disconnected connection */
748 if (SILC_IS_DISCONNECTED(sock))
751 if (sock->outbuf->data - sock->outbuf->head)
752 silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
754 ret = silc_packet_send(sock, TRUE);
756 /* If returned -2 could not write to connection now, will do
765 /* The packet has been sent and now it is time to set the connection
766 back to only for input. When there is again some outgoing data
767 available for this connection it will be set for output as well.
768 This call clears the output setting and sets it only for input. */
769 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
770 SILC_UNSET_OUTBUF_PENDING(sock);
772 silc_buffer_clear(sock->outbuf);
776 /* Packet receiving */
777 if (type == SILC_TASK_READ) {
778 /* Read data from network */
779 ret = silc_packet_receive(sock);
785 SILC_LOG_DEBUG(("Read EOF"));
787 /* If connection is disconnecting already we will finally
788 close the connection */
789 if (SILC_IS_DISCONNECTING(sock)) {
790 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
791 client->internal->ops->disconnect(client, conn);
792 silc_client_close_connection(client, sock, conn);
796 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
797 if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
798 client->internal->ops->disconnect(client, conn);
799 silc_client_close_connection(client, sock, conn);
803 /* Process the packet. This will call the parser that will then
804 decrypt and parse the packet. */
805 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
806 silc_packet_receive_process(sock, FALSE, conn->receive_key,
807 conn->hmac_receive, conn->psn_receive,
808 silc_client_packet_parse, client);
810 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
811 silc_client_packet_parse, client);
815 /* Parser callback called by silc_packet_receive_process. Thie merely
816 registers timeout that will handle the actual parsing when appropriate. */
818 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
821 SilcClient client = (SilcClient)context;
822 SilcSocketConnection sock = parser_context->sock;
823 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
824 SilcPacketContext *packet = parser_context->packet;
827 if (conn && conn->hmac_receive && conn->sock == sock)
828 conn->psn_receive = parser_context->packet->sequence + 1;
830 /* Parse the packet immediately */
831 if (parser_context->normal)
832 ret = silc_packet_parse(packet, conn->receive_key);
834 ret = silc_packet_parse_special(packet, conn->receive_key);
836 if (ret == SILC_PACKET_NONE) {
837 silc_packet_context_free(packet);
838 silc_free(parser_context);
842 /* If protocol for this connection is key exchange or rekey then we'll
843 process all packets synchronously, since there might be packets in
844 queue that we are not able to decrypt without first processing the
845 packets before them. */
846 if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
847 (sock->protocol && sock->protocol->protocol &&
848 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
849 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY))) {
851 /* Parse the incoming packet type */
852 silc_client_packet_parse_type(client, sock, packet);
853 silc_packet_context_free(packet);
854 silc_free(parser_context);
856 /* Reprocess the buffer since we'll return FALSE. This is because
857 the `conn->receive_key' might have become valid by processing
858 the previous packet */
859 if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
860 silc_packet_receive_process(sock, FALSE, conn->receive_key,
861 conn->hmac_receive, conn->psn_receive,
862 silc_client_packet_parse, client);
864 silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
865 silc_client_packet_parse, client);
870 /* Parse the incoming packet type */
871 silc_client_packet_parse_type(client, sock, packet);
872 silc_packet_context_free(packet);
873 silc_free(parser_context);
877 /* Parses the packet type and calls what ever routines the packet type
878 requires. This is done for all incoming packets. */
880 void silc_client_packet_parse_type(SilcClient client,
881 SilcSocketConnection sock,
882 SilcPacketContext *packet)
884 SilcBuffer buffer = packet->buffer;
885 SilcPacketType type = packet->type;
887 SILC_LOG_DEBUG(("Parsing packet type %d", type));
889 /* Parse the packet type */
891 case SILC_PACKET_DISCONNECT:
892 silc_client_disconnected_by_server(client, sock, buffer);
894 case SILC_PACKET_SUCCESS:
896 * Success received for something. For now we can have only
897 * one protocol for connection executing at once hence this
898 * success message is for whatever protocol is executing currently.
901 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
903 case SILC_PACKET_FAILURE:
905 * Failure received for some protocol. Set the protocol state to
906 * error and call the protocol callback. This fill cause error on
907 * protocol and it will call the final callback.
909 silc_client_process_failure(client, sock, packet);
911 case SILC_PACKET_REJECT:
914 case SILC_PACKET_NOTIFY:
916 * Received notify message
918 silc_client_notify_by_server(client, sock, packet);
921 case SILC_PACKET_ERROR:
923 * Received error message
925 silc_client_error_by_server(client, sock, buffer);
928 case SILC_PACKET_CHANNEL_MESSAGE:
930 * Received message to (from, actually) a channel
932 silc_client_channel_message(client, sock, packet);
934 case SILC_PACKET_CHANNEL_KEY:
936 * Received key for a channel. By receiving this key the client will be
937 * able to talk to the channel it has just joined. This can also be
938 * a new key for existing channel as keys expire peridiocally.
940 silc_client_receive_channel_key(client, sock, buffer);
943 case SILC_PACKET_PRIVATE_MESSAGE:
945 * Received private message
947 silc_client_private_message(client, sock, packet);
949 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
951 * Received private message key
955 case SILC_PACKET_COMMAND_REPLY:
957 * Recived reply for a command
959 silc_client_command_reply_process(client, sock, packet);
962 case SILC_PACKET_KEY_EXCHANGE:
963 if (sock->protocol && sock->protocol->protocol &&
964 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
965 SilcClientKEInternalContext *proto_ctx =
966 (SilcClientKEInternalContext *)sock->protocol->context;
968 proto_ctx->packet = silc_packet_context_dup(packet);
969 proto_ctx->dest_id_type = packet->src_id_type;
970 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
971 packet->src_id_type);
972 if (!proto_ctx->dest_id)
975 /* Let the protocol handle the packet */
976 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
978 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
979 "protocol active, packet dropped."));
983 case SILC_PACKET_KEY_EXCHANGE_1:
984 if (sock->protocol && sock->protocol->protocol &&
985 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
986 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
988 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
989 SilcClientRekeyInternalContext *proto_ctx =
990 (SilcClientRekeyInternalContext *)sock->protocol->context;
992 if (proto_ctx->packet)
993 silc_packet_context_free(proto_ctx->packet);
995 proto_ctx->packet = silc_packet_context_dup(packet);
997 /* Let the protocol handle the packet */
998 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1000 SilcClientKEInternalContext *proto_ctx =
1001 (SilcClientKEInternalContext *)sock->protocol->context;
1003 if (proto_ctx->packet)
1004 silc_packet_context_free(proto_ctx->packet);
1006 proto_ctx->packet = silc_packet_context_dup(packet);
1007 proto_ctx->dest_id_type = packet->src_id_type;
1008 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1009 packet->src_id_type);
1010 if (!proto_ctx->dest_id)
1013 /* Let the protocol handle the packet */
1014 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1017 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1018 "protocol active, packet dropped."));
1021 case SILC_PACKET_KEY_EXCHANGE_2:
1022 if (sock->protocol && sock->protocol->protocol &&
1023 (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1024 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1026 if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1027 SilcClientRekeyInternalContext *proto_ctx =
1028 (SilcClientRekeyInternalContext *)sock->protocol->context;
1030 if (proto_ctx->packet)
1031 silc_packet_context_free(proto_ctx->packet);
1033 proto_ctx->packet = silc_packet_context_dup(packet);
1035 /* Let the protocol handle the packet */
1036 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1038 SilcClientKEInternalContext *proto_ctx =
1039 (SilcClientKEInternalContext *)sock->protocol->context;
1041 if (proto_ctx->packet)
1042 silc_packet_context_free(proto_ctx->packet);
1044 proto_ctx->packet = silc_packet_context_dup(packet);
1045 proto_ctx->dest_id_type = packet->src_id_type;
1046 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1047 packet->src_id_type);
1048 if (!proto_ctx->dest_id)
1051 /* Let the protocol handle the packet */
1052 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1055 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1056 "protocol active, packet dropped."));
1060 case SILC_PACKET_NEW_ID:
1063 * Received new ID from server. This packet is received at
1064 * the connection to the server. New ID is also received when
1065 * user changes nickname but in that case the new ID is received
1066 * as command reply and not as this packet type.
1070 idp = silc_id_payload_parse(buffer->data, buffer->len);
1073 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1076 silc_client_receive_new_id(client, sock, idp);
1077 silc_id_payload_free(idp);
1081 case SILC_PACKET_HEARTBEAT:
1083 * Received heartbeat packet
1085 SILC_LOG_DEBUG(("Heartbeat packet"));
1088 case SILC_PACKET_KEY_AGREEMENT:
1090 * Received key agreement packet
1092 SILC_LOG_DEBUG(("Key agreement packet"));
1093 silc_client_key_agreement(client, sock, packet);
1096 case SILC_PACKET_REKEY:
1097 SILC_LOG_DEBUG(("Re-key packet"));
1098 /* We ignore this for now */
1101 case SILC_PACKET_REKEY_DONE:
1102 SILC_LOG_DEBUG(("Re-key done packet"));
1104 if (sock->protocol && sock->protocol->protocol &&
1105 sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1107 SilcClientRekeyInternalContext *proto_ctx =
1108 (SilcClientRekeyInternalContext *)sock->protocol->context;
1110 if (proto_ctx->packet)
1111 silc_packet_context_free(proto_ctx->packet);
1113 proto_ctx->packet = silc_packet_context_dup(packet);
1115 /* Let the protocol handle the packet */
1116 if (proto_ctx->responder == FALSE)
1117 silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1119 /* Let the protocol handle the packet */
1120 silc_protocol_execute(sock->protocol, client->schedule,
1123 SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1124 "protocol active, packet dropped."));
1128 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1130 * Reveived reply to our connection authentication method request
1131 * packet. This is used to resolve the authentication method for the
1132 * current session from the server if the client does not know it.
1134 silc_client_connection_auth_request(client, sock, packet);
1137 case SILC_PACKET_FTP:
1138 /* Received file transfer packet. */
1139 silc_client_ftp(client, sock, packet);
1143 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1148 /* Sends packet. This doesn't actually send the packet instead it assembles
1149 it and marks it to be sent. However, if force_send is TRUE the packet
1150 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1151 will be derived from sock argument. Otherwise the valid arguments sent
1154 void silc_client_packet_send(SilcClient client,
1155 SilcSocketConnection sock,
1156 SilcPacketType type,
1158 SilcIdType dst_id_type,
1161 unsigned char *data,
1165 SilcPacketContext packetdata;
1167 uint32 sequence = 0;
1172 SILC_LOG_DEBUG(("Sending packet, type %d", type));
1174 /* Get data used in the packet sending, keys and stuff */
1175 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1176 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1177 cipher = ((SilcClientConnection)sock->user_data)->send_key;
1179 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1180 hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1182 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1183 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1184 dst_id_type = SILC_ID_SERVER;
1188 sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1191 block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1193 /* Set the packet context pointers */
1194 packetdata.flags = 0;
1195 packetdata.type = type;
1196 if (sock->user_data &&
1197 ((SilcClientConnection)sock->user_data)->local_id_data) {
1198 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1199 packetdata.src_id_len =
1200 silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1203 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1204 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1206 packetdata.src_id_type = SILC_ID_CLIENT;
1208 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1209 packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1210 packetdata.dst_id_type = dst_id_type;
1212 packetdata.dst_id = NULL;
1213 packetdata.dst_id_len = 0;
1214 packetdata.dst_id_type = SILC_ID_NONE;
1216 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
1217 packetdata.src_id_len + packetdata.dst_id_len;
1218 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1220 /* Prepare outgoing data buffer for packet sending */
1221 silc_packet_send_prepare(sock,
1222 SILC_PACKET_HEADER_LEN +
1223 packetdata.src_id_len +
1224 packetdata.dst_id_len,
1228 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1230 packetdata.buffer = sock->outbuf;
1232 /* Put the data to the buffer */
1233 if (data && data_len)
1234 silc_buffer_put(sock->outbuf, data, data_len);
1236 /* Create the outgoing packet */
1237 silc_packet_assemble(&packetdata, cipher);
1239 /* Encrypt the packet */
1241 silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf,
1244 SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, sock->outbuf->len),
1245 sock->outbuf->data, sock->outbuf->len);
1247 /* Now actually send the packet */
1248 silc_client_packet_send_real(client, sock, force_send);
1251 void silc_client_packet_queue_purge(SilcClient client,
1252 SilcSocketConnection sock)
1254 if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
1255 (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1256 if (sock->outbuf->data - sock->outbuf->head)
1257 silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
1259 silc_packet_send(sock, TRUE);
1261 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1262 SILC_UNSET_OUTBUF_PENDING(sock);
1263 silc_buffer_clear(sock->outbuf);
1267 /* Closes connection to remote end. Free's all allocated data except
1268 for some information such as nickname etc. that are valid at all time.
1269 If the `sock' is NULL then the conn->sock will be used. If `sock' is
1270 provided it will be checked whether the sock and `conn->sock' are the
1271 same (they can be different, ie. a socket can use `conn' as its
1272 connection but `conn->sock' might be actually a different connection
1273 than the `sock'). */
1275 void silc_client_close_connection(SilcClient client,
1276 SilcSocketConnection sock,
1277 SilcClientConnection conn)
1281 SILC_LOG_DEBUG(("Start"));
1283 if (!sock || (sock && conn->sock == sock))
1288 /* We won't listen for this connection anymore */
1289 silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1291 /* Unregister all tasks */
1292 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1293 silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1295 /* Close the actual connection */
1296 silc_net_close_connection(sock->sock);
1298 /* Cancel any active protocol */
1299 if (sock->protocol) {
1300 if (sock->protocol->protocol->type ==
1301 SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1302 sock->protocol->protocol->type ==
1303 SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1304 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1305 silc_protocol_execute_final(sock->protocol, client->schedule);
1306 /* The application will recall this function with these protocols
1307 (the ops->connect client operation). */
1310 sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1311 silc_protocol_execute_final(sock->protocol, client->schedule);
1312 sock->protocol = NULL;
1316 /* Free everything */
1317 if (del && sock->user_data) {
1318 /* Free all cache entries */
1319 SilcIDCacheList list;
1320 SilcIDCacheEntry entry;
1323 if (silc_idcache_get_all(conn->client_cache, &list)) {
1324 ret = silc_idcache_list_first(list, &entry);
1326 silc_client_del_client(client, conn, entry->context);
1327 ret = silc_idcache_list_next(list, &entry);
1329 silc_idcache_list_free(list);
1332 if (silc_idcache_get_all(conn->channel_cache, &list)) {
1333 ret = silc_idcache_list_first(list, &entry);
1335 silc_client_del_channel(client, conn, entry->context);
1336 ret = silc_idcache_list_next(list, &entry);
1338 silc_idcache_list_free(list);
1341 if (silc_idcache_get_all(conn->server_cache, &list)) {
1342 ret = silc_idcache_list_first(list, &entry);
1344 silc_client_del_server(client, conn, entry->context);
1345 ret = silc_idcache_list_next(list, &entry);
1347 silc_idcache_list_free(list);
1350 /* Clear ID caches */
1351 if (conn->client_cache)
1352 silc_idcache_del_all(conn->client_cache);
1353 if (conn->channel_cache)
1354 silc_idcache_del_all(conn->channel_cache);
1355 if (conn->server_cache)
1356 silc_idcache_del_all(conn->server_cache);
1358 /* Free data (my ID is freed in above silc_client_del_client) */
1359 if (conn->remote_host)
1360 silc_free(conn->remote_host);
1361 if (conn->local_id_data)
1362 silc_free(conn->local_id_data);
1364 silc_cipher_free(conn->send_key);
1365 if (conn->receive_key)
1366 silc_cipher_free(conn->receive_key);
1367 if (conn->hmac_send)
1368 silc_hmac_free(conn->hmac_send);
1369 if (conn->hmac_receive)
1370 silc_hmac_free(conn->hmac_receive);
1371 if (conn->pending_commands)
1372 silc_dlist_uninit(conn->pending_commands);
1374 silc_free(conn->rekey);
1376 if (conn->active_session) {
1377 sock->user_data = NULL;
1378 silc_client_ftp_session_free(conn->active_session);
1379 conn->active_session = NULL;
1382 silc_client_ftp_free_sessions(client, conn);
1384 memset(conn, 0, sizeof(*conn));
1385 silc_client_del_connection(client, conn);
1388 silc_socket_free(sock);
1391 /* Called when we receive disconnection packet from server. This
1392 closes our end properly and displays the reason of the disconnection
1395 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1397 SilcClient client = (SilcClient)context;
1398 SilcSocketConnection sock;
1400 SILC_CLIENT_GET_SOCK(client, fd, sock);
1404 silc_client_close_connection(client, sock, sock->user_data);
1407 /* Called when we receive disconnection packet from server. This
1408 closes our end properly and displays the reason of the disconnection
1411 void silc_client_disconnected_by_server(SilcClient client,
1412 SilcSocketConnection sock,
1417 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1419 msg = silc_calloc(message->len + 1, sizeof(char));
1420 memcpy(msg, message->data, message->len);
1421 client->internal->ops->say(client, sock->user_data,
1422 SILC_CLIENT_MESSAGE_AUDIT, msg);
1425 SILC_SET_DISCONNECTED(sock);
1427 /* Close connection through scheduler. */
1428 silc_schedule_task_add(client->schedule, sock->sock,
1429 silc_client_disconnected_by_server_later,
1430 client, 0, 1, SILC_TASK_TIMEOUT,
1431 SILC_TASK_PRI_NORMAL);
1434 /* Received error message from server. Display it on the screen.
1435 We don't take any action what so ever of the error message. */
1437 void silc_client_error_by_server(SilcClient client,
1438 SilcSocketConnection sock,
1443 msg = silc_calloc(message->len + 1, sizeof(char));
1444 memcpy(msg, message->data, message->len);
1445 client->internal->ops->say(client, sock->user_data,
1446 SILC_CLIENT_MESSAGE_AUDIT, msg);
1450 /* Processes the received new Client ID from server. Old Client ID is
1451 deleted from cache and new one is added. */
1453 void silc_client_receive_new_id(SilcClient client,
1454 SilcSocketConnection sock,
1457 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1458 int connecting = FALSE;
1459 SilcClientID *client_id = silc_id_payload_get_id(idp);
1462 if (!conn->local_entry)
1465 /* Delete old ID from ID cache */
1466 if (conn->local_id) {
1467 /* Check whether they are different */
1468 if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1469 silc_free(client_id);
1473 silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1474 silc_free(conn->local_id);
1477 /* Save the new ID */
1479 if (conn->local_id_data)
1480 silc_free(conn->local_id_data);
1482 conn->local_id = client_id;
1483 conn->local_id_data = silc_id_payload_get_data(idp);
1484 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1486 if (!conn->local_entry)
1487 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1489 conn->local_entry->nickname = conn->nickname;
1490 if (!conn->local_entry->username)
1491 conn->local_entry->username = strdup(client->username);
1492 if (!conn->local_entry->hostname)
1493 conn->local_entry->hostname = strdup(client->hostname);
1494 conn->local_entry->server = strdup(conn->remote_host);
1495 conn->local_entry->id = conn->local_id;
1496 conn->local_entry->valid = TRUE;
1498 /* Put it to the ID cache */
1499 silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id,
1500 (void *)conn->local_entry, 0, NULL);
1503 /* Issue INFO comqmand to fetch the real server name and server information
1505 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1506 silc_client_command_reply_info_i, 0,
1508 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1509 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1510 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1511 silc_buffer_free(sidp);
1513 /* Notify application of successful connection. We do it here now that
1514 we've received the Client ID and are allowed to send traffic. */
1515 client->internal->ops->connect(client, conn, TRUE);
1519 /* Processed received Channel ID for a channel. This is called when client
1520 joins to channel and server replies with channel ID. The ID is cached.
1521 Returns the created channel entry. This is also called when received
1522 channel ID in for example USERS command reply that we do not have. */
1524 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1525 SilcSocketConnection sock,
1530 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1531 SilcChannelEntry channel;
1533 SILC_LOG_DEBUG(("New channel ID"));
1535 channel = silc_calloc(1, sizeof(*channel));
1536 channel->channel_name = channel_name;
1537 channel->id = silc_id_payload_get_id(idp);
1538 channel->mode = mode;
1539 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1541 /* Put it to the ID cache */
1542 silc_idcache_add(conn->channel_cache, channel->channel_name,
1543 (void *)channel->id, (void *)channel, 0, NULL);
1548 /* Removes a client entry from all channel it has joined. This really is
1549 a performance killer (client_entry should have pointers to channel
1552 void silc_client_remove_from_channels(SilcClient client,
1553 SilcClientConnection conn,
1554 SilcClientEntry client_entry)
1556 SilcIDCacheEntry id_cache;
1557 SilcIDCacheList list;
1558 SilcChannelEntry channel;
1559 SilcChannelUser chu;
1561 if (!silc_idcache_get_all(conn->channel_cache, &list))
1564 silc_idcache_list_first(list, &id_cache);
1565 channel = (SilcChannelEntry)id_cache->context;
1569 /* Remove client from channel */
1570 silc_list_start(channel->clients);
1571 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1572 if (chu->client == client_entry) {
1573 silc_list_del(channel->clients, chu);
1579 if (!silc_idcache_list_next(list, &id_cache))
1582 channel = (SilcChannelEntry)id_cache->context;
1585 silc_idcache_list_free(list);
1588 /* Replaces `old' client entries from all channels to `new' client entry.
1589 This can be called for example when nickname changes and old ID entry
1590 is replaced from ID cache with the new one. If the old ID entry is only
1591 updated, then this fucntion needs not to be called. */
1593 void silc_client_replace_from_channels(SilcClient client,
1594 SilcClientConnection conn,
1595 SilcClientEntry old,
1596 SilcClientEntry new)
1598 SilcIDCacheEntry id_cache;
1599 SilcIDCacheList list;
1600 SilcChannelEntry channel;
1601 SilcChannelUser chu;
1603 if (!silc_idcache_get_all(conn->channel_cache, &list))
1606 silc_idcache_list_first(list, &id_cache);
1607 channel = (SilcChannelEntry)id_cache->context;
1611 /* Replace client entry */
1612 silc_list_start(channel->clients);
1613 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1614 if (chu->client == old) {
1620 if (!silc_idcache_list_next(list, &id_cache))
1623 channel = (SilcChannelEntry)id_cache->context;
1626 silc_idcache_list_free(list);
1629 /* Registers failure timeout to process the received failure packet
1632 void silc_client_process_failure(SilcClient client,
1633 SilcSocketConnection sock,
1634 SilcPacketContext *packet)
1638 if (sock->protocol) {
1639 if (packet->buffer->len >= 4)
1640 SILC_GET32_MSB(failure, packet->buffer->data);
1642 /* Notify application */
1643 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1648 /* A timeout callback for the re-key. We will be the initiator of the
1651 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1653 SilcSocketConnection sock = (SilcSocketConnection)context;
1654 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1655 SilcClient client = (SilcClient)conn->rekey->context;
1656 SilcProtocol protocol;
1657 SilcClientRekeyInternalContext *proto_ctx;
1659 SILC_LOG_DEBUG(("Start"));
1661 /* Allocate internal protocol context. This is sent as context
1663 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1664 proto_ctx->client = (void *)client;
1665 proto_ctx->sock = silc_socket_dup(sock);
1666 proto_ctx->responder = FALSE;
1667 proto_ctx->pfs = conn->rekey->pfs;
1669 /* Perform rekey protocol. Will call the final callback after the
1670 protocol is over. */
1671 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1672 &protocol, proto_ctx, silc_client_rekey_final);
1673 sock->protocol = protocol;
1675 /* Run the protocol */
1676 silc_protocol_execute(protocol, client->schedule, 0, 0);
1678 /* Re-register re-key timeout */
1679 silc_schedule_task_add(client->schedule, sock->sock,
1680 silc_client_rekey_callback,
1681 context, conn->rekey->timeout, 0,
1682 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1685 /* The final callback for the REKEY protocol. This will actually take the
1686 new key material into use. */
1688 SILC_TASK_CALLBACK(silc_client_rekey_final)
1690 SilcProtocol protocol = (SilcProtocol)context;
1691 SilcClientRekeyInternalContext *ctx =
1692 (SilcClientRekeyInternalContext *)protocol->context;
1693 SilcClient client = (SilcClient)ctx->client;
1694 SilcSocketConnection sock = ctx->sock;
1696 SILC_LOG_DEBUG(("Start"));
1698 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1699 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1700 /* Error occured during protocol */
1701 silc_protocol_cancel(protocol, client->schedule);
1702 silc_protocol_free(protocol);
1703 sock->protocol = NULL;
1705 silc_packet_context_free(ctx->packet);
1707 silc_ske_free(ctx->ske);
1708 silc_socket_free(ctx->sock);
1713 /* Purge the outgoing data queue to assure that all rekey packets really
1714 go to the network before we quit the protocol. */
1715 silc_client_packet_queue_purge(client, sock);
1718 silc_protocol_free(protocol);
1719 sock->protocol = NULL;
1721 silc_packet_context_free(ctx->packet);
1723 silc_ske_free(ctx->ske);
1724 silc_socket_free(ctx->sock);
1728 /* Processes incoming connection authentication method request packet.
1729 It is a reply to our previously sent request. The packet can be used
1730 to resolve the authentication method for the current session if the
1731 client does not know it beforehand. */
1733 void silc_client_connection_auth_request(SilcClient client,
1734 SilcSocketConnection sock,
1735 SilcPacketContext *packet)
1737 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1738 uint16 conn_type, auth_meth;
1741 /* If we haven't send our request then ignore this one. */
1742 if (!conn->connauth)
1745 /* Parse the payload */
1746 ret = silc_buffer_unformat(packet->buffer,
1747 SILC_STR_UI_SHORT(&conn_type),
1748 SILC_STR_UI_SHORT(&auth_meth),
1751 auth_meth = SILC_AUTH_NONE;
1753 /* Call the request callback to notify application for received
1754 authentication method information. */
1755 if (conn->connauth->callback)
1756 (*conn->connauth->callback)(client, conn, auth_meth,
1757 conn->connauth->context);
1759 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1761 silc_free(conn->connauth);
1762 conn->connauth = NULL;
1765 /* Timeout task callback called if the server does not reply to our
1766 connection authentication method request in the specified time interval. */
1768 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1770 SilcClientConnection conn = (SilcClientConnection)context;
1771 SilcClient client = conn->client;
1773 if (!conn->connauth)
1776 /* Call the request callback to notify application */
1777 if (conn->connauth->callback)
1778 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1779 conn->connauth->context);
1781 silc_free(conn->connauth);
1782 conn->connauth = NULL;
1785 /* This function can be used to request the current authentication method
1786 from the server. This may be called when connecting to the server
1787 and the client library requests the authentication data from the
1788 application. If the application does not know the current authentication
1789 method it can request it from the server using this function.
1790 The `callback' with `context' will be called after the server has
1791 replied back with the current authentication method. */
1794 silc_client_request_authentication_method(SilcClient client,
1795 SilcClientConnection conn,
1796 SilcConnectionAuthRequest callback,
1799 SilcClientConnAuthRequest connauth;
1802 connauth = silc_calloc(1, sizeof(*connauth));
1803 connauth->callback = callback;
1804 connauth->context = context;
1807 silc_free(conn->connauth);
1809 conn->connauth = connauth;
1811 /* Assemble the request packet and send it to the server */
1812 packet = silc_buffer_alloc(4);
1813 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1814 silc_buffer_format(packet,
1815 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1816 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1818 silc_client_packet_send(client, conn->sock,
1819 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1820 NULL, 0, NULL, NULL,
1821 packet->data, packet->len, FALSE);
1822 silc_buffer_free(packet);
1824 /* Register a timeout in case server does not reply anything back. */
1826 silc_schedule_task_add(client->schedule, conn->sock->sock,
1827 silc_client_request_authentication_method_timeout,
1829 client->internal->params->connauth_request_secs, 0,
1830 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);