5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "clientlibincludes.h"
22 #include "client_internal.h"
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_rekey_callback);
29 SILC_TASK_CALLBACK(silc_client_rekey_final);
31 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
33 static void silc_client_packet_parse_type(SilcClient client,
34 SilcSocketConnection sock,
35 SilcPacketContext *packet);
36 void silc_client_resolve_auth_method(bool success,
37 SilcProtocolAuthMeth auth_meth,
38 const unsigned char *auth_data,
39 uint32 auth_data_len, void *context);
41 /* Allocates new client object. This has to be done before client may
42 work. After calling this one must call silc_client_init to initialize
43 the client. The `application' is application specific user data pointer
44 and caller must free it. */
46 SilcClient silc_client_alloc(SilcClientOperations *ops,
47 SilcClientParams *params,
49 const char *silc_version)
51 SilcClient new_client;
53 new_client = silc_calloc(1, sizeof(*new_client));
54 new_client->application = application;
56 new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
57 new_client->internal->ops = ops;
58 new_client->internal->params =
59 silc_calloc(1, sizeof(*new_client->internal->params));
60 new_client->internal->silc_client_version = strdup(silc_version);
63 memcpy(new_client->internal->params, params, sizeof(*params));
65 if (!new_client->internal->params->task_max)
66 new_client->internal->params->task_max = 200;
68 if (!new_client->internal->params->rekey_secs)
69 new_client->internal->params->rekey_secs = 3600;
71 if (!new_client->internal->params->connauth_request_secs)
72 new_client->internal->params->connauth_request_secs = 2;
74 new_client->internal->params->
75 nickname_format[sizeof(new_client->internal->
76 params->nickname_format) - 1] = 0;
81 /* Frees client object and its internals. */
83 void silc_client_free(SilcClient client)
87 silc_rng_free(client->rng);
89 silc_free(client->internal->params);
90 silc_free(client->internal->silc_client_version);
91 silc_free(client->internal);
96 /* Initializes the client. This makes all the necessary steps to make
97 the client ready to be run. One must call silc_client_run to run the
98 client. Returns FALSE if error occured, TRUE otherwise. */
100 int silc_client_init(SilcClient client)
102 SILC_LOG_DEBUG(("Initializing client"));
104 /* Initialize hash functions for client to use */
105 silc_hash_alloc("md5", &client->internal->md5hash);
106 silc_hash_alloc("sha1", &client->internal->sha1hash);
108 /* Initialize none cipher */
109 silc_cipher_alloc("none", &client->internal->none_cipher);
111 /* Initialize random number generator */
112 client->rng = silc_rng_alloc();
113 silc_rng_init(client->rng);
114 silc_rng_global_init(client->rng);
116 /* Register protocols */
117 silc_client_protocols_register();
119 /* Initialize the scheduler */
121 silc_schedule_init(client->internal->params->task_max ?
122 client->internal->params->task_max : 200);
123 if (!client->schedule)
126 /* Register commands */
127 silc_client_commands_register(client);
132 /* Stops the client. This is called to stop the client and thus to stop
135 void silc_client_stop(SilcClient client)
137 SILC_LOG_DEBUG(("Stopping client"));
139 silc_schedule_stop(client->schedule);
140 silc_schedule_uninit(client->schedule);
142 silc_client_protocols_unregister();
143 silc_client_commands_unregister(client);
145 SILC_LOG_DEBUG(("Client stopped"));
148 /* Runs the client. This starts the scheduler from the utility library.
149 When this functions returns the execution of the appliation is over. */
151 void silc_client_run(SilcClient client)
153 SILC_LOG_DEBUG(("Running client"));
155 /* Start the scheduler, the heart of the SILC client. When this returns
156 the program will be terminated. */
157 silc_schedule(client->schedule);
160 /* Runs the client and returns immeadiately. This function is used when
161 the SILC Client object indicated by the `client' is run under some
162 other scheduler, or event loop or main loop. On GUI applications,
163 for example this may be desired to use to run the client under the
164 GUI application's main loop. Typically the GUI application would
165 register an idle task that calls this function multiple times in
166 a second to quickly process the SILC specific data. */
168 void silc_client_run_one(SilcClient client)
170 /* Run the scheduler once. */
171 silc_schedule_one(client->schedule, 0);
174 static void silc_client_entry_destructor(SilcIDCache cache,
175 SilcIDCacheEntry entry)
177 silc_free(entry->name);
180 /* Allocates and adds new connection to the client. This adds the allocated
181 connection to the connection table and returns a pointer to it. A client
182 can have multiple connections to multiple servers. Every connection must
183 be added to the client using this function. User data `context' may
184 be sent as argument. This function is normally used only if the
185 application performed the connecting outside the library. The library
186 however may use this internally. */
188 SilcClientConnection silc_client_add_connection(SilcClient client,
193 SilcClientConnection conn;
196 conn = silc_calloc(1, sizeof(*conn));
198 /* Initialize ID caches */
199 conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT,
200 silc_client_entry_destructor);
201 conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
202 conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
203 conn->client = client;
204 conn->remote_host = strdup(hostname);
205 conn->remote_port = port;
206 conn->context = context;
207 conn->pending_commands = silc_dlist_init();
208 conn->ftp_sessions = silc_dlist_init();
210 /* Add the connection to connections table */
211 for (i = 0; i < client->internal->conns_count; i++)
212 if (client->internal->conns && !client->internal->conns[i]) {
213 client->internal->conns[i] = conn;
217 client->internal->conns =
218 silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
219 * (client->internal->conns_count + 1));
220 client->internal->conns[client->internal->conns_count] = conn;
221 client->internal->conns_count++;
226 /* Removes connection from client. Frees all memory. */
228 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
232 for (i = 0; i < client->internal->conns_count; i++)
233 if (client->internal->conns[i] == conn) {
235 silc_idcache_free(conn->client_cache);
236 silc_idcache_free(conn->channel_cache);
237 silc_idcache_free(conn->server_cache);
238 if (conn->pending_commands)
239 silc_dlist_uninit(conn->pending_commands);
240 silc_free(conn->remote_host);
241 silc_dlist_uninit(conn->ftp_sessions);
244 client->internal->conns[i] = NULL;
248 /* Adds listener socket to the listener sockets table. This function is
249 used to add socket objects that are listeners to the client. This should
250 not be used to add other connection objects. */
252 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
256 if (!client->internal->sockets) {
257 client->internal->sockets =
258 silc_calloc(1, sizeof(*client->internal->sockets));
259 client->internal->sockets[0] = silc_socket_dup(sock);
260 client->internal->sockets_count = 1;
264 for (i = 0; i < client->internal->sockets_count; i++) {
265 if (client->internal->sockets[i] == NULL) {
266 client->internal->sockets[i] = silc_socket_dup(sock);
271 client->internal->sockets =
272 silc_realloc(client->internal->sockets,
273 sizeof(*client->internal->sockets) *
274 (client->internal->sockets_count + 1));
275 client->internal->sockets[client->internal->sockets_count] =
276 silc_socket_dup(sock);
277 client->internal->sockets_count++;
280 /* Deletes listener socket from the listener sockets table. */
282 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
286 if (!client->internal->sockets)
289 for (i = 0; i < client->internal->sockets_count; i++) {
290 if (client->internal->sockets[i] == sock) {
291 silc_socket_free(sock);
292 client->internal->sockets[i] = NULL;
299 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
303 /* XXX In the future we should give up this non-blocking connect all
304 together and use threads instead. */
305 /* Create connection to server asynchronously */
306 sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
310 /* Register task that will receive the async connect and will
312 ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
313 silc_client_connect_to_server_start,
316 SILC_TASK_PRI_NORMAL);
317 silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
324 /* Connects to remote server. This is the main routine used to connect
325 to SILC server. Returns -1 on error and the created socket otherwise.
326 The `context' is user context that is saved into the SilcClientConnection
327 that is created after the connection is created. Note that application
328 may handle the connecting process outside the library. If this is the
329 case then this function is not used at all. When the connecting is
330 done the `connect' client operation is called. */
332 int silc_client_connect_to_server(SilcClient client, int port,
333 char *host, void *context)
335 SilcClientInternalConnectContext *ctx;
336 SilcClientConnection conn;
339 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
342 conn = silc_client_add_connection(client, host, port, context);
344 client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
345 "Connecting to port %d of server %s", port, host);
347 /* Allocate internal context for connection process. This is
348 needed as we are doing async connecting. */
349 ctx = silc_calloc(1, sizeof(*ctx));
350 ctx->client = client;
352 ctx->host = strdup(host);
356 /* Do the actual connecting process */
357 sock = silc_client_connect_to_server_internal(ctx);
359 silc_client_del_connection(client, conn);
363 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
364 key material between client and server. This function can be called
365 directly if application is performing its own connecting and does not
366 use the connecting provided by this library. This function is normally
367 used only if the application performed the connecting outside the library.
368 The library however may use this internally. */
370 bool silc_client_start_key_exchange(SilcClient client,
371 SilcClientConnection conn,
374 SilcProtocol protocol;
375 SilcClientKEInternalContext *proto_ctx;
378 /* Allocate new socket connection object */
379 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
381 /* Sometimes when doing quick reconnects the new socket may be same as
382 the old one and there might be pending stuff for the old socket.
383 If new one is same then those pending sutff might cause problems.
384 Make sure they do not do that. */
385 silc_schedule_task_del_by_fd(client->schedule, fd);
387 conn->nickname = (client->nickname ? strdup(client->nickname) :
388 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 /* Send NICK command if the nickname was set by the application (and is
1504 not same as the username). */
1505 if (client->nickname && strcmp(client->nickname, client->username))
1506 silc_client_command_send(client, conn, SILC_COMMAND_NICK,
1507 ++conn->cmd_ident, 1, 1,
1508 client->nickname, strlen(client->nickname));
1510 /* Issue INFO command to fetch the real server name and server information
1512 silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1513 silc_client_command_reply_info_i, 0,
1515 sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1516 silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1517 conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1518 silc_buffer_free(sidp);
1520 /* Notify application of successful connection. We do it here now that
1521 we've received the Client ID and are allowed to send traffic. */
1522 client->internal->ops->connect(client, conn, TRUE);
1526 /* Processed received Channel ID for a channel. This is called when client
1527 joins to channel and server replies with channel ID. The ID is cached.
1528 Returns the created channel entry. This is also called when received
1529 channel ID in for example USERS command reply that we do not have. */
1531 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1532 SilcSocketConnection sock,
1537 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1538 SilcChannelEntry channel;
1540 SILC_LOG_DEBUG(("New channel ID"));
1542 channel = silc_calloc(1, sizeof(*channel));
1543 channel->channel_name = channel_name;
1544 channel->id = silc_id_payload_get_id(idp);
1545 channel->mode = mode;
1546 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1548 /* Put it to the ID cache */
1549 silc_idcache_add(conn->channel_cache, channel->channel_name,
1550 (void *)channel->id, (void *)channel, 0, NULL);
1555 /* Removes a client entry from all channel it has joined. This really is
1556 a performance killer (client_entry should have pointers to channel
1559 void silc_client_remove_from_channels(SilcClient client,
1560 SilcClientConnection conn,
1561 SilcClientEntry client_entry)
1563 SilcIDCacheEntry id_cache;
1564 SilcIDCacheList list;
1565 SilcChannelEntry channel;
1566 SilcChannelUser chu;
1568 if (!silc_idcache_get_all(conn->channel_cache, &list))
1571 silc_idcache_list_first(list, &id_cache);
1572 channel = (SilcChannelEntry)id_cache->context;
1576 /* Remove client from channel */
1577 silc_list_start(channel->clients);
1578 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1579 if (chu->client == client_entry) {
1580 silc_list_del(channel->clients, chu);
1586 if (!silc_idcache_list_next(list, &id_cache))
1589 channel = (SilcChannelEntry)id_cache->context;
1592 silc_idcache_list_free(list);
1595 /* Replaces `old' client entries from all channels to `new' client entry.
1596 This can be called for example when nickname changes and old ID entry
1597 is replaced from ID cache with the new one. If the old ID entry is only
1598 updated, then this fucntion needs not to be called. */
1600 void silc_client_replace_from_channels(SilcClient client,
1601 SilcClientConnection conn,
1602 SilcClientEntry old,
1603 SilcClientEntry new)
1605 SilcIDCacheEntry id_cache;
1606 SilcIDCacheList list;
1607 SilcChannelEntry channel;
1608 SilcChannelUser chu;
1610 if (!silc_idcache_get_all(conn->channel_cache, &list))
1613 silc_idcache_list_first(list, &id_cache);
1614 channel = (SilcChannelEntry)id_cache->context;
1618 /* Replace client entry */
1619 silc_list_start(channel->clients);
1620 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1621 if (chu->client == old) {
1627 if (!silc_idcache_list_next(list, &id_cache))
1630 channel = (SilcChannelEntry)id_cache->context;
1633 silc_idcache_list_free(list);
1636 /* Registers failure timeout to process the received failure packet
1639 void silc_client_process_failure(SilcClient client,
1640 SilcSocketConnection sock,
1641 SilcPacketContext *packet)
1645 if (sock->protocol) {
1646 if (packet->buffer->len >= 4)
1647 SILC_GET32_MSB(failure, packet->buffer->data);
1649 /* Notify application */
1650 client->internal->ops->failure(client, sock->user_data, sock->protocol,
1655 /* A timeout callback for the re-key. We will be the initiator of the
1658 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1660 SilcSocketConnection sock = (SilcSocketConnection)context;
1661 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1662 SilcClient client = (SilcClient)conn->rekey->context;
1663 SilcProtocol protocol;
1664 SilcClientRekeyInternalContext *proto_ctx;
1666 SILC_LOG_DEBUG(("Start"));
1668 /* Allocate internal protocol context. This is sent as context
1670 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1671 proto_ctx->client = (void *)client;
1672 proto_ctx->sock = silc_socket_dup(sock);
1673 proto_ctx->responder = FALSE;
1674 proto_ctx->pfs = conn->rekey->pfs;
1676 /* Perform rekey protocol. Will call the final callback after the
1677 protocol is over. */
1678 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY,
1679 &protocol, proto_ctx, silc_client_rekey_final);
1680 sock->protocol = protocol;
1682 /* Run the protocol */
1683 silc_protocol_execute(protocol, client->schedule, 0, 0);
1685 /* Re-register re-key timeout */
1686 silc_schedule_task_add(client->schedule, sock->sock,
1687 silc_client_rekey_callback,
1688 context, conn->rekey->timeout, 0,
1689 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1692 /* The final callback for the REKEY protocol. This will actually take the
1693 new key material into use. */
1695 SILC_TASK_CALLBACK(silc_client_rekey_final)
1697 SilcProtocol protocol = (SilcProtocol)context;
1698 SilcClientRekeyInternalContext *ctx =
1699 (SilcClientRekeyInternalContext *)protocol->context;
1700 SilcClient client = (SilcClient)ctx->client;
1701 SilcSocketConnection sock = ctx->sock;
1703 SILC_LOG_DEBUG(("Start"));
1705 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1706 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1707 /* Error occured during protocol */
1708 silc_protocol_cancel(protocol, client->schedule);
1709 silc_protocol_free(protocol);
1710 sock->protocol = NULL;
1712 silc_packet_context_free(ctx->packet);
1714 silc_ske_free(ctx->ske);
1715 silc_socket_free(ctx->sock);
1720 /* Purge the outgoing data queue to assure that all rekey packets really
1721 go to the network before we quit the protocol. */
1722 silc_client_packet_queue_purge(client, sock);
1725 silc_protocol_free(protocol);
1726 sock->protocol = NULL;
1728 silc_packet_context_free(ctx->packet);
1730 silc_ske_free(ctx->ske);
1731 silc_socket_free(ctx->sock);
1735 /* Processes incoming connection authentication method request packet.
1736 It is a reply to our previously sent request. The packet can be used
1737 to resolve the authentication method for the current session if the
1738 client does not know it beforehand. */
1740 void silc_client_connection_auth_request(SilcClient client,
1741 SilcSocketConnection sock,
1742 SilcPacketContext *packet)
1744 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1745 uint16 conn_type, auth_meth;
1748 /* If we haven't send our request then ignore this one. */
1749 if (!conn->connauth)
1752 /* Parse the payload */
1753 ret = silc_buffer_unformat(packet->buffer,
1754 SILC_STR_UI_SHORT(&conn_type),
1755 SILC_STR_UI_SHORT(&auth_meth),
1758 auth_meth = SILC_AUTH_NONE;
1760 /* Call the request callback to notify application for received
1761 authentication method information. */
1762 if (conn->connauth->callback)
1763 (*conn->connauth->callback)(client, conn, auth_meth,
1764 conn->connauth->context);
1766 silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1768 silc_free(conn->connauth);
1769 conn->connauth = NULL;
1772 /* Timeout task callback called if the server does not reply to our
1773 connection authentication method request in the specified time interval. */
1775 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1777 SilcClientConnection conn = (SilcClientConnection)context;
1778 SilcClient client = conn->client;
1780 if (!conn->connauth)
1783 /* Call the request callback to notify application */
1784 if (conn->connauth->callback)
1785 (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1786 conn->connauth->context);
1788 silc_free(conn->connauth);
1789 conn->connauth = NULL;
1792 /* This function can be used to request the current authentication method
1793 from the server. This may be called when connecting to the server
1794 and the client library requests the authentication data from the
1795 application. If the application does not know the current authentication
1796 method it can request it from the server using this function.
1797 The `callback' with `context' will be called after the server has
1798 replied back with the current authentication method. */
1801 silc_client_request_authentication_method(SilcClient client,
1802 SilcClientConnection conn,
1803 SilcConnectionAuthRequest callback,
1806 SilcClientConnAuthRequest connauth;
1809 connauth = silc_calloc(1, sizeof(*connauth));
1810 connauth->callback = callback;
1811 connauth->context = context;
1814 silc_free(conn->connauth);
1816 conn->connauth = connauth;
1818 /* Assemble the request packet and send it to the server */
1819 packet = silc_buffer_alloc(4);
1820 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1821 silc_buffer_format(packet,
1822 SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1823 SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1825 silc_client_packet_send(client, conn->sock,
1826 SILC_PACKET_CONNECTION_AUTH_REQUEST,
1827 NULL, 0, NULL, NULL,
1828 packet->data, packet->len, FALSE);
1829 silc_buffer_free(packet);
1831 /* Register a timeout in case server does not reply anything back. */
1833 silc_schedule_task_add(client->schedule, conn->sock->sock,
1834 silc_client_request_authentication_method_timeout,
1836 client->internal->params->connauth_request_secs, 0,
1837 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);