Added preliminary Symbian support.
[silc.git] / lib / silcclient / client_keyagr.c
1 /*
2
3   client_keyagr.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 - 2006 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 #include "silc.h"
21 #include "silcclient.h"
22 #include "client_internal.h"
23
24 /************************** Types and definitions ***************************/
25
26 /* Key agreement context, used by responder */
27 struct SilcClientKeyAgreementStruct {
28   SilcClient client;                      /* Client */
29   SilcClientConnection conn;              /* Server connection */
30   SilcKeyAgreementCallback completion;    /* Key agreement completion */
31   void *context;                          /* User context */
32   SilcClientConnectionParams params;      /* Connection parameters */
33   SilcPublicKey public_key;               /* Responder public key */
34   SilcPrivateKey private_key;             /* Responder private key */
35   SilcNetListener tcp_listener;           /* TCP listener */
36   SilcPacketStream udp_listener;          /* UDP listener */
37   SilcPacketStream stream;                /* Remote connection (TCP or UDP) */
38   SilcAsyncOperation op;                  /* SKE operation */
39   SilcSKE ske;                            /* SKE */
40 };
41
42 /************************ Static utility functions **************************/
43
44 /* Destroyes key agreement session */
45
46 static void silc_client_keyagr_free(SilcClient client,
47                                     SilcClientConnection conn,
48                                     SilcClientEntry client_entry)
49 {
50   SilcClientKeyAgreement ke = client_entry->internal.ke;
51
52   silc_schedule_task_del_by_context(conn->internal->schedule, client_entry);
53
54   if (ke->op)
55     silc_async_abort(ke->op, NULL, NULL);
56   if (ke->ske)
57     silc_ske_free(ke->ske);
58   if (ke->tcp_listener)
59     silc_net_close_listener(ke->tcp_listener);
60   silc_packet_stream_destroy(ke->stream);
61   silc_packet_stream_destroy(ke->udp_listener);
62
63   client_entry->internal.ke = NULL;
64   client_entry->internal.prv_resp = FALSE;
65   silc_client_unref_client(client, conn, client_entry);
66
67   silc_free(ke);
68 }
69
70 /* Key agreement timeout callback */
71
72 SILC_TASK_CALLBACK(silc_client_keyagr_timeout)
73 {
74   SilcClientEntry client_entry = context;
75   SilcClientKeyAgreement ke = client_entry->internal.ke;
76
77   SILC_LOG_DEBUG(("Key agreement %p timeout", ke));
78
79   ke->completion(ke->client, ke->conn, client_entry,
80                  SILC_KEY_AGREEMENT_TIMEOUT, NULL, ke->context);
81
82   silc_client_keyagr_free(ke->client, ke->conn, client_entry);
83 }
84
85 /* Client resolving callback.  Continues with the key agreement processing */
86
87 static void silc_client_keyagr_resolved(SilcClient client,
88                                         SilcClientConnection conn,
89                                         SilcStatus status,
90                                         SilcDList clients,
91                                         void *context)
92 {
93   /* If no client found, ignore the packet, a silent error */
94   if (!clients)
95     silc_fsm_next(context, silc_client_key_agreement_error);
96
97   /* Continue processing the packet */
98   SILC_FSM_CALL_CONTINUE(context);
99 }
100
101 /* Called after application has verified remote host's public key.  Responder
102    function. */
103
104 static void silc_client_keyagr_verify_key_cb(SilcBool success, void *context)
105 {
106   VerifyKeyContext verify = context;
107
108   /* Call the completion callback back to the SKE */
109   verify->completion(verify->ske, success ? SILC_SKE_STATUS_OK :
110                      SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
111                      verify->completion_context);
112
113   silc_free(verify);
114 }
115
116 /* Verify remote host's public key.  Responder function. */
117
118 static void silc_client_keyagr_verify_key(SilcSKE ske,
119                                           SilcPublicKey public_key,
120                                           void *context,
121                                           SilcSKEVerifyCbCompletion completion,
122                                           void *completion_context)
123 {
124   SilcClientEntry client_entry = context;
125   SilcClientKeyAgreement ke = client_entry->internal.ke;
126   SilcClientConnection conn = ke->conn;
127   SilcClient client = conn->client;
128   VerifyKeyContext verify;
129
130   /* If we provided repository for SKE and we got here the key was not
131      found from the repository. */
132   if (ke->params.repository && !ke->params.verify_notfound) {
133     completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
134                completion_context);
135     return;
136   }
137
138   SILC_LOG_DEBUG(("Verify remote public key"));
139
140   verify = silc_calloc(1, sizeof(*verify));
141   if (!verify) {
142     completion(ske, SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY,
143                completion_context);
144     return;
145   }
146   verify->ske = ske;
147   verify->completion = completion;
148   verify->completion_context = completion_context;
149
150   /* Verify public key in application */
151   client->internal->ops->verify_public_key(client, conn,
152                                            SILC_CONN_CLIENT, public_key,
153                                            silc_client_keyagr_verify_key_cb,
154                                            verify);
155 }
156
157 /* Key exchange protocol completion callback.  Responder function. */
158
159 static void silc_client_keyagr_completion(SilcSKE ske,
160                                           SilcSKEStatus status,
161                                           SilcSKESecurityProperties prop,
162                                           SilcSKEKeyMaterial keymat,
163                                           SilcSKERekeyMaterial rekey,
164                                           void *context)
165 {
166   SilcClientEntry client_entry = context;
167   SilcClientKeyAgreement ke = client_entry->internal.ke;
168   SilcClientConnection conn = ke->conn;
169   SilcClient client = conn->client;
170
171   if (status != SILC_SKE_STATUS_OK) {
172     /* Key exchange failed */
173     ke->completion(client, conn, client_entry,
174                    status == SILC_SKE_STATUS_TIMEOUT ?
175                    SILC_KEY_AGREEMENT_TIMEOUT :
176                    SILC_KEY_AGREEMENT_FAILURE, NULL, ke->context);
177     silc_client_keyagr_free(client, conn, client_entry);
178     return;
179   }
180
181   /* Returns the negotiated key material to application.  Key agreement
182      was successful. */
183   ke->completion(client, conn, client_entry, SILC_KEY_AGREEMENT_OK,
184                  keymat, ke->context);
185
186   silc_client_keyagr_free(client, conn, client_entry);
187 }
188
189 /* Starts key agreement as responder.  */
190
191 static void silc_client_process_key_agreement(SilcClient client,
192                                               SilcClientConnection conn,
193                                               SilcClientEntry client_entry)
194 {
195   SilcClientKeyAgreement ke = client_entry->internal.ke;
196   SilcSKEParamsStruct params;
197
198   SILC_LOG_DEBUG(("Processing key agrement %p session", ke));
199
200   /* Allocate SKE */
201   ke->ske = silc_ske_alloc(client->rng, conn->internal->schedule,
202                            ke->params.repository, ke->public_key,
203                            ke->private_key, client_entry);
204   if (!ke->ske) {
205     ke->completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
206                    NULL, ke->context);
207     silc_client_keyagr_free(client, conn, client_entry);
208     return;
209   }
210
211   /* Set SKE parameters */
212   params.version = client->internal->silc_client_version;
213   params.flags = SILC_SKE_SP_FLAG_MUTUAL;
214   if (ke->params.udp) {
215     params.flags |= SILC_SKE_SP_FLAG_IV_INCLUDED;
216     params.session_port = ke->params.local_port;
217   }
218
219   silc_ske_set_callbacks(ke->ske, silc_client_keyagr_verify_key,
220                          silc_client_keyagr_completion, client_entry);
221
222   /* Start key exchange as responder */
223   ke->op = silc_ske_responder(ke->ske, ke->stream, &params);
224   if (!ke->op) {
225     ke->completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
226                    NULL, ke->context);
227     silc_client_keyagr_free(client, conn, client_entry);
228   }
229 }
230
231 /* TCP network listener callback.  Accepts new key agreement connection.
232    Responder function. */
233
234 static void silc_client_tcp_accept(SilcNetStatus status,
235                                    SilcStream stream,
236                                    void *context)
237 {
238   SilcClientEntry client_entry = context;
239   SilcClientKeyAgreement ke = client_entry->internal.ke;
240
241   /* Create packet stream */
242   ke->stream = silc_packet_stream_create(ke->client->internal->packet_engine,
243                                          ke->conn->internal->schedule, stream);
244   if (!ke->stream) {
245     silc_stream_destroy(stream);
246     return;
247   }
248
249   /* Process session */
250   silc_client_process_key_agreement(ke->client, ke->conn, client_entry);
251 }
252
253 /* UDP network listener callback.  Accepts new key agreement session.
254    Responder function. */
255
256 static SilcBool silc_client_udp_accept(SilcPacketEngine engine,
257                                        SilcPacketStream stream,
258                                        SilcPacket packet,
259                                        void *callback_context,
260                                        void *stream_context)
261 {
262   SilcClientEntry client_entry = callback_context;
263   SilcClientKeyAgreement ke = client_entry->internal.ke;
264   SilcUInt16 port;
265   const char *ip;
266
267   /* We want only key exchange packet.  Eat other packets so that default
268      packet callback doesn't get them. */
269   if (packet->type != SILC_PACKET_KEY_EXCHANGE) {
270     silc_packet_free(packet);
271     return TRUE;
272   }
273
274   /* Create packet stream for this remote UDP session */
275   if (!silc_packet_get_sender(packet, &ip, &port)) {
276     silc_packet_free(packet);
277     return TRUE;
278   }
279   ke->stream = silc_packet_stream_add_remote(stream, ip, port, packet);
280   if (!ke->stream) {
281     silc_packet_free(packet);
282     return TRUE;
283   }
284
285   /* Process session */
286   silc_client_process_key_agreement(ke->client, ke->conn, client_entry);
287   return TRUE;
288 }
289
290 /* Client connect completion callback.  Initiator function. */
291
292 static void silc_client_keyagr_perform_cb(SilcClient client,
293                                           SilcClientConnection conn,
294                                           SilcClientConnectionStatus status,
295                                           SilcStatus error,
296                                           const char *message,
297                                           void *context)
298 {
299   SilcClientEntry client_entry = context;
300   SilcClientKeyAgreement ke = client_entry->internal.ke;
301   SilcSKEKeyMaterial keymat;
302
303   ke->op = NULL;
304
305   switch (status) {
306   case SILC_CLIENT_CONN_SUCCESS:
307     SILC_LOG_DEBUG(("Key agreement %p successful", ke));
308
309     keymat = silc_ske_get_key_material(conn->internal->ske);
310     ke->completion(ke->client, ke->conn, client_entry, SILC_KEY_AGREEMENT_OK,
311                    keymat, ke->context);
312     break;
313
314   case SILC_CLIENT_CONN_ERROR_TIMEOUT:
315     SILC_LOG_DEBUG(("Key agreement %p timeout", ke));
316     ke->completion(ke->client, ke->conn, client_entry,
317                    SILC_KEY_AGREEMENT_TIMEOUT, NULL, ke->context);
318     break;
319
320   default:
321     SILC_LOG_DEBUG(("Key agreement %p error %d", ke, status));
322     ke->completion(ke->client, ke->conn, client_entry,
323                    SILC_KEY_AGREEMENT_FAILURE, NULL, ke->context);
324     break;
325   }
326
327   /* Close the created connection */
328   if (conn)
329     silc_client_close_connection(ke->client, conn);
330
331   silc_client_keyagr_free(ke->client, ke->conn, client_entry);
332 }
333
334 /* Packet stream callbacks */
335 static SilcPacketCallbacks silc_client_keyagr_stream_cb =
336 {
337   silc_client_udp_accept, NULL, NULL
338 };
339
340 /*************************** Key Agreement API ******************************/
341
342 /* Sends key agreement packet to remote client.  If IP addresses are provided
343    creates also listener for Ã­ncoming key agreement connection.  Supports
344    both TCP and UDP transports. */
345
346 void silc_client_send_key_agreement(SilcClient client,
347                                     SilcClientConnection conn,
348                                     SilcClientEntry client_entry,
349                                     SilcClientConnectionParams *params,
350                                     SilcPublicKey public_key,
351                                     SilcPrivateKey private_key,
352                                     SilcKeyAgreementCallback completion,
353                                     void *context)
354 {
355   SilcClientKeyAgreement ke = NULL;
356   SilcBuffer buffer;
357   SilcUInt16 port = 0, protocol = 0;
358   char *local_ip = NULL;
359   SilcStream stream;
360
361   SILC_LOG_DEBUG(("Sending key agreement"));
362
363   if (!client_entry)
364     return;
365   if (conn->internal->disconnected)
366     return;
367
368   if (client_entry->internal.ke) {
369     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ALREADY_STARTED,
370                NULL, context);
371     return;
372   }
373
374   if (client_entry == conn->local_entry) {
375     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
376                NULL, context);
377     return;
378   }
379
380   /* If local IP is provided, create listener */
381   if (params && (params->local_ip || params->bind_ip)) {
382     ke = silc_calloc(1, sizeof(*ke));
383     if (!ke) {
384       completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
385                  NULL, context);
386       return;
387     }
388
389     /* Create network listener */
390     if (params->udp) {
391       /* UDP listener */
392       stream = silc_net_udp_connect(params->bind_ip ? params->bind_ip :
393                                     params->local_ip, params->local_port,
394                                     NULL, 0, conn->internal->schedule);
395       ke->udp_listener =
396         silc_packet_stream_create(client->internal->packet_engine,
397                                   conn->internal->schedule, stream);
398       if (!ke->udp_listener) {
399         client->internal->ops->say(
400                      client, conn, SILC_CLIENT_MESSAGE_ERROR,
401                      "Cannot create UDP listener on %s on port %d: %s",
402                      params->bind_ip ? params->bind_ip :
403                      params->local_ip, params->local_port, strerror(errno));
404         completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
405                    NULL, context);
406         if (stream)
407           silc_stream_destroy(stream);
408         silc_free(ke);
409         return;
410       }
411       silc_packet_stream_link(ke->udp_listener,
412                               &silc_client_keyagr_stream_cb,
413                               client_entry, 1000000,
414                               SILC_PACKET_ANY, -1);
415
416       port = params->local_port;
417       if (!port) {
418         /* Get listener port */
419         SilcSocket sock;
420         silc_socket_stream_get_info(stream, &sock, NULL, NULL, NULL);
421         port = silc_net_get_local_port(sock);
422       }
423     } else {
424       /* TCP listener */
425       ke->tcp_listener =
426         silc_net_tcp_create_listener(params->bind_ip ?
427                                      (const char **)&params->bind_ip :
428                                      (const char **)&params->local_ip,
429                                      1, params->local_port, FALSE, FALSE,
430                                      conn->internal->schedule,
431                                      silc_client_tcp_accept,
432                                      client_entry);
433       if (!ke->tcp_listener) {
434         client->internal->ops->say(
435                      client, conn, SILC_CLIENT_MESSAGE_ERROR,
436                      "Cannot create listener on %s on port %d: %s",
437                      params->bind_ip ? params->bind_ip :
438                      params->local_ip, params->local_port, strerror(errno));
439         completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
440                    NULL, context);
441         silc_free(ke);
442         return;
443       }
444
445       port = params->local_port;
446       if (!port) {
447         /* Get listener port */
448         SilcUInt16 *ports;
449         ports = silc_net_listener_get_port(ke->tcp_listener, NULL);
450         port = ports[0];
451         silc_free(ports);
452       }
453     }
454
455     local_ip = params->local_ip;
456     protocol = params->udp;
457
458     ke->client = client;
459     ke->conn = conn;
460     ke->completion = completion;
461     ke->context = context;
462     ke->params = *params;
463     ke->public_key = public_key;
464     ke->private_key = private_key;
465     silc_client_ref_client(client, conn, client_entry);
466     client_entry->internal.ke = ke;
467     client_entry->internal.prv_resp = TRUE;
468   }
469
470   /* Encode the key agreement payload */
471   buffer = silc_key_agreement_payload_encode(local_ip, protocol, port);
472   if (!buffer) {
473     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
474                NULL, context);
475     silc_client_keyagr_free(client, conn, client_entry);
476     return;
477   }
478
479   /* Send the key agreement packet to the client */
480   if (!silc_packet_send_ext(conn->stream, SILC_PACKET_KEY_AGREEMENT, 0,
481                             0, NULL, SILC_ID_CLIENT, &client_entry->id,
482                             silc_buffer_datalen(buffer), NULL, NULL)) {
483     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
484                NULL, context);
485     silc_client_keyagr_free(client, conn, client_entry);
486     silc_buffer_free(buffer);
487     return;
488   }
489
490   /* Add key agreement timeout task */
491   if (params && params->timeout_secs)
492     silc_schedule_task_add_timeout(conn->internal->schedule,
493                                    silc_client_keyagr_timeout,
494                                    client_entry, params->timeout_secs, 0);
495
496   silc_buffer_free(buffer);
497 }
498
499 /* Perform key agreement protocol as initiator.  Conneects to remote host. */
500
501 void silc_client_perform_key_agreement(SilcClient client,
502                                        SilcClientConnection conn,
503                                        SilcClientEntry client_entry,
504                                        SilcClientConnectionParams *params,
505                                        SilcPublicKey public_key,
506                                        SilcPrivateKey private_key,
507                                        char *hostname, int port,
508                                        SilcKeyAgreementCallback completion,
509                                        void *context)
510 {
511   SilcClientKeyAgreement ke;
512
513   SILC_LOG_DEBUG(("Performing key agreement"));
514
515   if (!client_entry || !hostname || !port) {
516     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
517                NULL, context);
518     return;
519   }
520
521   if (client_entry == conn->local_entry) {
522     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
523                NULL, context);
524     return;
525   }
526
527   ke = silc_calloc(1, sizeof(*ke));
528   if (!ke) {
529     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
530                NULL, context);
531     return;
532   }
533   ke->client = client;
534   ke->conn = conn;
535   ke->completion = completion;
536   ke->context = context;
537   silc_client_ref_client(client, conn, client_entry);
538   client_entry->internal.ke = ke;
539
540   if (params)
541     params->no_authentication = TRUE;
542
543   /* Connect to the remote client.  Performs key exchange automatically. */
544   if (!silc_client_connect_to_client(client, params, public_key,
545                                      private_key, hostname, port,
546                                      silc_client_keyagr_perform_cb,
547                                      client_entry)) {
548     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
549                NULL, context);
550     silc_client_keyagr_free(client, conn, client_entry);
551     return;
552   }
553 }
554
555 /* Same as above but caller has created connection. */
556
557 void
558 silc_client_perform_key_agreement_stream(SilcClient client,
559                                          SilcClientConnection conn,
560                                          SilcClientEntry client_entry,
561                                          SilcClientConnectionParams *params,
562                                          SilcPublicKey public_key,
563                                          SilcPrivateKey private_key,
564                                          SilcStream stream,
565                                          SilcKeyAgreementCallback completion,
566                                          void *context)
567 {
568   SilcClientKeyAgreement ke;
569
570   SILC_LOG_DEBUG(("Performing key agreement"));
571
572   if (!client_entry || !stream) {
573     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
574                NULL, context);
575     return;
576   }
577
578   if (client_entry == conn->local_entry) {
579     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
580                NULL, context);
581     return;
582   }
583
584   ke = silc_calloc(1, sizeof(*ke));
585   if (!ke) {
586     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
587                NULL, context);
588     return;
589   }
590   ke->client = client;
591   ke->conn = conn;
592   ke->completion = completion;
593   ke->context = context;
594   silc_client_ref_client(client, conn, client_entry);
595   client_entry->internal.ke = ke;
596
597   if (params)
598     params->no_authentication = TRUE;
599
600   /* Perform key exchange protocol */
601   if (!silc_client_key_exchange(client, params, public_key,
602                                 private_key, stream, SILC_CONN_CLIENT,
603                                 silc_client_keyagr_perform_cb,
604                                 client_entry)) {
605     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
606                NULL, context);
607     silc_client_keyagr_free(client, conn, client_entry);
608     return;
609   }
610 }
611
612 /* This function can be called to unbind the hostname and the port for
613    the key agreement protocol. However, this function has effect only
614    before the key agreement protocol has been performed. After it has
615    been performed the library will automatically unbind the port. The
616    `client_entry' is the client to which we sent the key agreement
617    request. */
618
619 void silc_client_abort_key_agreement(SilcClient client,
620                                      SilcClientConnection conn,
621                                      SilcClientEntry client_entry)
622 {
623   SilcClientKeyAgreement ke;
624
625   if (!client_entry || !client_entry->internal.ke)
626     return;
627
628   ke = client_entry->internal.ke;
629
630   SILC_LOG_DEBUG(("Abort key agreement %p"));
631
632   ke->completion(client, conn, client_entry,
633                  SILC_KEY_AGREEMENT_ABORTED, NULL, ke->context);
634
635   silc_client_keyagr_free(client, conn, client_entry);
636 }
637
638 /* Key agreement packet received */
639
640 SILC_FSM_STATE(silc_client_key_agreement)
641 {
642   SilcClientConnection conn = fsm_context;
643   SilcClient client = conn->client;
644   SilcPacket packet = state_context;
645   SilcClientID remote_id;
646   SilcClientEntry remote_client;
647   SilcKeyAgreementPayload payload;
648
649   if (packet->src_id_type != SILC_ID_CLIENT) {
650     /** Invalid packet */
651     silc_fsm_next(fsm, silc_client_key_agreement_error);
652     SILC_FSM_CONTINUE;
653   }
654
655   if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
656                       &remote_id, sizeof(remote_id))) {
657     /** Invalid source ID */
658     silc_fsm_next(fsm, silc_client_key_agreement_error);
659     SILC_FSM_CONTINUE;
660   }
661
662   /* Check whether we know this client already */
663   remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
664   if (!remote_client || !remote_client->nickname[0]) {
665     /** Resolve client info */
666     silc_client_unref_client(client, conn, remote_client);
667     SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
668                                          client, conn, &remote_id, NULL,
669                                          silc_client_keyagr_resolved, fsm));
670     /* NOT REACHED */
671   }
672
673   /* Parse the key agreement payload */
674   payload = silc_key_agreement_payload_parse(silc_buffer_data(&packet->buffer),
675                                              silc_buffer_len(&packet->buffer));
676   if (!payload) {
677     /** Malformed Payload */
678     SILC_LOG_DEBUG(("Malformed key agreement payload"));
679     silc_fsm_next(fsm, silc_client_key_agreement_error);
680     SILC_FSM_CONTINUE;
681   }
682
683   /* If remote did not provide connection endpoint, we will assume that we
684      will provide it and will be responder. */
685   if (!silc_key_agreement_get_hostname(payload))
686     remote_client->internal.prv_resp = TRUE;
687   else
688     remote_client->internal.prv_resp = FALSE;
689
690   /* Notify application for key agreement request */
691   client->internal->ops->key_agreement(
692                                    client, conn, remote_client,
693                                    silc_key_agreement_get_hostname(payload),
694                                    silc_key_agreement_get_protocol(payload),
695                                    silc_key_agreement_get_port(payload));
696
697   silc_key_agreement_payload_free(payload);
698
699   silc_packet_free(packet);
700   SILC_FSM_FINISH;
701 }
702
703 /* Key agreement packet processing error */
704
705 SILC_FSM_STATE(silc_client_key_agreement_error)
706 {
707   SilcPacket packet = state_context;
708   silc_packet_free(packet);
709   SILC_FSM_FINISH;
710 }