More client library rewrites (key agreement, plus other).
[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
366   if (client_entry->internal.ke) {
367     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ALREADY_STARTED,
368                NULL, context);
369     return;
370   }
371
372   if (client_entry == conn->local_entry) {
373     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
374                NULL, context);
375     return;
376   }
377
378   /* If local IP is provided, create listener */
379   if (params && (params->local_ip || params->bind_ip)) {
380     ke = silc_calloc(1, sizeof(*ke));
381     if (!ke) {
382       completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
383                  NULL, context);
384       return;
385     }
386
387     /* Create network listener */
388     if (params->udp) {
389       /* UDP listener */
390       stream = silc_net_udp_connect(params->bind_ip ? params->bind_ip :
391                                     params->local_ip, params->local_port,
392                                     NULL, 0, conn->internal->schedule);
393       ke->udp_listener =
394         silc_packet_stream_create(client->internal->packet_engine,
395                                   conn->internal->schedule, stream);
396       if (!ke->udp_listener) {
397         client->internal->ops->say(
398                      client, conn, SILC_CLIENT_MESSAGE_ERROR,
399                      "Cannot create UDP listener on %s on port %d: %s",
400                      params->bind_ip ? params->bind_ip :
401                      params->local_ip, params->local_port, strerror(errno));
402         completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
403                    NULL, context);
404         if (stream)
405           silc_stream_destroy(stream);
406         silc_free(ke);
407         return;
408       }
409       silc_packet_stream_link(ke->udp_listener,
410                               &silc_client_keyagr_stream_cb,
411                               client_entry, 1000000,
412                               SILC_PACKET_ANY, -1);
413
414       port = params->local_port;
415       if (!port) {
416         /* Get listener port */
417         int sock;
418         silc_socket_stream_get_info(stream, &sock, NULL, NULL, NULL);
419         port = silc_net_get_local_port(sock);
420       }
421     } else {
422       /* TCP listener */
423       ke->tcp_listener =
424         silc_net_tcp_create_listener(params->bind_ip ?
425                                      (const char **)&params->bind_ip :
426                                      (const char **)&params->local_ip,
427                                      1, params->local_port, FALSE, FALSE,
428                                      conn->internal->schedule,
429                                      silc_client_tcp_accept,
430                                      client_entry);
431       if (!ke->tcp_listener) {
432         client->internal->ops->say(
433                      client, conn, SILC_CLIENT_MESSAGE_ERROR,
434                      "Cannot create listener on %s on port %d: %s",
435                      params->bind_ip ? params->bind_ip :
436                      params->local_ip, params->local_port, strerror(errno));
437         completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
438                    NULL, context);
439         silc_free(ke);
440         return;
441       }
442
443       port = params->local_port;
444       if (!port) {
445         /* Get listener port */
446         SilcUInt16 *ports;
447         ports = silc_net_listener_get_port(ke->tcp_listener, NULL);
448         port = ports[0];
449         silc_free(ports);
450       }
451     }
452
453     local_ip = params->local_ip;
454     protocol = params->udp;
455
456     ke->client = client;
457     ke->conn = conn;
458     ke->completion = completion;
459     ke->context = context;
460     ke->params = *params;
461     ke->public_key = public_key;
462     ke->private_key = private_key;
463     silc_client_ref_client(client, conn, client_entry);
464     client_entry->internal.ke = ke;
465     client_entry->internal.prv_resp = TRUE;
466   }
467
468   /* Encode the key agreement payload */
469   buffer = silc_key_agreement_payload_encode(local_ip, protocol, port);
470   if (!buffer) {
471     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
472                NULL, context);
473     silc_client_keyagr_free(client, conn, client_entry);
474     return;
475   }
476
477   /* Send the key agreement packet to the client */
478   if (!silc_packet_send_ext(conn->stream, SILC_PACKET_KEY_AGREEMENT, 0,
479                             0, NULL, SILC_ID_CLIENT, &client_entry->id,
480                             silc_buffer_datalen(buffer), NULL, NULL)) {
481     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
482                NULL, context);
483     silc_client_keyagr_free(client, conn, client_entry);
484     silc_buffer_free(buffer);
485     return;
486   }
487
488   /* Add key agreement timeout task */
489   if (params && params->timeout_secs)
490     silc_schedule_task_add_timeout(conn->internal->schedule,
491                                    silc_client_keyagr_timeout,
492                                    client_entry, params->timeout_secs, 0);
493
494   silc_buffer_free(buffer);
495 }
496
497 /* Perform key agreement protocol as initiator.  Conneects to remote host. */
498
499 void silc_client_perform_key_agreement(SilcClient client,
500                                        SilcClientConnection conn,
501                                        SilcClientEntry client_entry,
502                                        SilcClientConnectionParams *params,
503                                        SilcPublicKey public_key,
504                                        SilcPrivateKey private_key,
505                                        char *hostname, int port,
506                                        SilcKeyAgreementCallback completion,
507                                        void *context)
508 {
509   SilcClientKeyAgreement ke;
510
511   SILC_LOG_DEBUG(("Performing key agreement"));
512
513   if (!client_entry || !hostname || !port) {
514     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
515                NULL, context);
516     return;
517   }
518
519   if (client_entry == conn->local_entry) {
520     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
521                NULL, context);
522     return;
523   }
524
525   ke = silc_calloc(1, sizeof(*ke));
526   if (!ke) {
527     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
528                NULL, context);
529     return;
530   }
531   ke->client = client;
532   ke->conn = conn;
533   ke->completion = completion;
534   ke->context = context;
535   silc_client_ref_client(client, conn, client_entry);
536   client_entry->internal.ke = ke;
537
538   if (params)
539     params->no_authentication = TRUE;
540
541   /* Connect to the remote client.  Performs key exchange automatically. */
542   if (!silc_client_connect_to_client(client, params, public_key,
543                                      private_key, hostname, port,
544                                      silc_client_keyagr_perform_cb,
545                                      client_entry)) {
546     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
547                NULL, context);
548     silc_client_keyagr_free(client, conn, client_entry);
549     return;
550   }
551 }
552
553 /* Same as above but caller has created connection. */
554
555 void
556 silc_client_perform_key_agreement_stream(SilcClient client,
557                                          SilcClientConnection conn,
558                                          SilcClientEntry client_entry,
559                                          SilcClientConnectionParams *params,
560                                          SilcPublicKey public_key,
561                                          SilcPrivateKey private_key,
562                                          SilcStream stream,
563                                          SilcKeyAgreementCallback completion,
564                                          void *context)
565 {
566   SilcClientKeyAgreement ke;
567
568   SILC_LOG_DEBUG(("Performing key agreement"));
569
570   if (!client_entry || !stream) {
571     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
572                NULL, context);
573     return;
574   }
575
576   if (client_entry == conn->local_entry) {
577     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_SELF_DENIED,
578                NULL, context);
579     return;
580   }
581
582   ke = silc_calloc(1, sizeof(*ke));
583   if (!ke) {
584     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_NO_MEMORY,
585                NULL, context);
586     return;
587   }
588   ke->client = client;
589   ke->conn = conn;
590   ke->completion = completion;
591   ke->context = context;
592   silc_client_ref_client(client, conn, client_entry);
593   client_entry->internal.ke = ke;
594
595   if (params)
596     params->no_authentication = TRUE;
597
598   /* Perform key exchange protocol */
599   if (!silc_client_key_exchange(client, params, public_key,
600                                 private_key, stream, SILC_CONN_CLIENT,
601                                 silc_client_keyagr_perform_cb,
602                                 client_entry)) {
603     completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR,
604                NULL, context);
605     silc_client_keyagr_free(client, conn, client_entry);
606     return;
607   }
608 }
609
610 /* This function can be called to unbind the hostname and the port for
611    the key agreement protocol. However, this function has effect only
612    before the key agreement protocol has been performed. After it has
613    been performed the library will automatically unbind the port. The
614    `client_entry' is the client to which we sent the key agreement
615    request. */
616
617 void silc_client_abort_key_agreement(SilcClient client,
618                                      SilcClientConnection conn,
619                                      SilcClientEntry client_entry)
620 {
621   SilcClientKeyAgreement ke;
622
623   if (!client_entry || !client_entry->internal.ke)
624     return;
625
626   ke = client_entry->internal.ke;
627
628   SILC_LOG_DEBUG(("Abort key agreement %p"));
629
630   ke->completion(client, conn, client_entry,
631                  SILC_KEY_AGREEMENT_ABORTED, NULL, ke->context);
632
633   silc_client_keyagr_free(client, conn, client_entry);
634 }
635
636 /* Key agreement packet received */
637
638 SILC_FSM_STATE(silc_client_key_agreement)
639 {
640   SilcClientConnection conn = fsm_context;
641   SilcClient client = conn->client;
642   SilcPacket packet = state_context;
643   SilcClientID remote_id;
644   SilcClientEntry remote_client;
645   SilcKeyAgreementPayload payload;
646
647   if (packet->src_id_type != SILC_ID_CLIENT) {
648     /** Invalid packet */
649     silc_fsm_next(fsm, silc_client_key_agreement_error);
650     return SILC_FSM_CONTINUE;
651   }
652
653   if (!silc_id_str2id(packet->src_id, packet->src_id_len, SILC_ID_CLIENT,
654                       &remote_id, sizeof(remote_id))) {
655     /** Invalid source ID */
656     silc_fsm_next(fsm, silc_client_key_agreement_error);
657     return SILC_FSM_CONTINUE;
658   }
659
660   /* Check whether we know this client already */
661   remote_client = silc_client_get_client_by_id(client, conn, &remote_id);
662   if (!remote_client || !remote_client->nickname[0]) {
663     /** Resolve client info */
664     silc_client_unref_client(client, conn, remote_client);
665     SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
666                                          client, conn, &remote_id, NULL,
667                                          silc_client_keyagr_resolved, fsm));
668     /* NOT REACHED */
669   }
670
671   /* Parse the key agreement payload */
672   payload = silc_key_agreement_payload_parse(silc_buffer_data(&packet->buffer),
673                                              silc_buffer_len(&packet->buffer));
674   if (!payload) {
675     /** Malformed Payload */
676     SILC_LOG_DEBUG(("Malformed key agreement payload"));
677     silc_fsm_next(fsm, silc_client_key_agreement_error);
678     return SILC_FSM_CONTINUE;
679   }
680
681   /* If remote did not provide connection endpoint, we will assume that we
682      will provide it and will be responder. */
683   if (!silc_key_agreement_get_hostname(payload))
684     remote_client->internal.prv_resp = TRUE;
685   else
686     remote_client->internal.prv_resp = FALSE;
687
688   /* Notify application for key agreement request */
689   client->internal->ops->key_agreement(
690                                    client, conn, remote_client,
691                                    silc_key_agreement_get_hostname(payload),
692                                    silc_key_agreement_get_protocol(payload),
693                                    silc_key_agreement_get_port(payload));
694
695   silc_key_agreement_payload_free(payload);
696
697   silc_packet_free(packet);
698   return SILC_FSM_FINISH;
699 }
700
701 /* Key agreement packet processing error */
702
703 SILC_FSM_STATE(silc_client_key_agreement_error)
704 {
705   SilcPacket packet = state_context;
706   silc_packet_free(packet);
707   return SILC_FSM_FINISH;
708 }