updates.
[silc.git] / lib / silcclient / protocol.c
1 /*
2
3   protocol.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * Client side of the protocols.
22  */
23 /* $Id$ */
24
25 #include "clientlibincludes.h"
26 #include "client_internal.h"
27
28 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
29 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
30
31 extern char *silc_version_string;
32
33 /*
34  * Key Exhange protocol functions
35  */
36
37 /* Function that is called when SKE protocol sends packets to network. */
38
39 void silc_client_protocol_ke_send_packet(SilcSKE ske,
40                                          SilcBuffer packet,
41                                          SilcPacketType type,
42                                          void *context)
43 {
44   SilcProtocol protocol = (SilcProtocol)context;
45   SilcClientKEInternalContext *ctx = 
46     (SilcClientKEInternalContext *)protocol->context;
47   SilcClient client = (SilcClient)ctx->client;
48
49   /* Send the packet immediately */
50   silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
51                           packet->data, packet->len, TRUE);
52
53 }
54
55 /* Callback that is called when we have received KE2 payload from
56    responder. We try to verify the public key now. */
57
58 static SilcSKEStatus 
59 silc_client_protocol_ke_verify_key(SilcSKE ske,
60                                    unsigned char *pk_data,
61                                    unsigned int pk_len,
62                                    SilcSKEPKType pk_type,
63                                    void *context)
64 {
65   SilcProtocol protocol = (SilcProtocol)context;
66   SilcClientKEInternalContext *ctx = 
67     (SilcClientKEInternalContext *)protocol->context;
68   SilcClient client = (SilcClient)ctx->client;
69
70   SILC_LOG_DEBUG(("Start"));
71
72   /* Verify server key from user. */
73   if (!client->ops->verify_server_key(client, ctx->sock->user_data, 
74                                       pk_data, pk_len, pk_type))
75     return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
76
77   return SILC_SKE_STATUS_OK;
78 }
79
80 /* Sets the negotiated key material into use for particular connection. */
81
82 void silc_client_protocol_ke_set_keys(SilcSKE ske,
83                                       SilcSocketConnection sock,
84                                       SilcSKEKeyMaterial *keymat,
85                                       SilcCipher cipher,
86                                       SilcPKCS pkcs,
87                                       SilcHash hash,
88                                       SilcHmac hmac)
89 {
90   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
91
92   SILC_LOG_DEBUG(("Setting new keys into use"));
93
94   /* Allocate cipher to be used in the communication */
95   silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
96   silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
97
98   conn->send_key->cipher->set_key(conn->send_key->context, 
99                                  keymat->send_enc_key, 
100                                  keymat->enc_key_len);
101   conn->send_key->set_iv(conn->send_key, keymat->send_iv);
102   conn->receive_key->cipher->set_key(conn->receive_key->context, 
103                                     keymat->receive_enc_key, 
104                                     keymat->enc_key_len);
105   conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
106
107   /* Allocate PKCS to be used */
108 #if 0
109   /* XXX Do we ever need to allocate PKCS for the connection??
110      If yes, we need to change KE protocol to get the initiators
111      public key. */
112   silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
113   silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data, 
114                            ske->ke2_payload->pk_len);
115 #endif
116
117   /* Save HMAC key to be used in the communication. */
118   silc_hmac_alloc(hmac->hmac->name, NULL, &conn->hmac);
119   silc_hmac_set_key(conn->hmac, keymat->hmac_key, keymat->hmac_key_len);
120 }
121
122 /* Checks the version string of the server. */
123
124 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
125                                      unsigned int len)
126 {
127   SilcClientConnection conn = (SilcClientConnection)ske->sock->user_data;
128   SilcClient client = (SilcClient)ske->user_data;
129   SilcSKEStatus status = SILC_SKE_STATUS_OK;
130
131   /* Check for initial version string */
132   if (!strstr(version, "SILC-1.0-"))
133     status = SILC_SKE_STATUS_BAD_VERSION;
134
135   /* Check software version */
136
137   if (len < strlen(silc_version_string))
138     status = SILC_SKE_STATUS_BAD_VERSION;
139
140   /* XXX for now there is no other tests due to the abnormal version
141      string that is used */
142
143   if (status != SILC_SKE_STATUS_OK)
144     client->ops->say(client, conn, 
145                      "We don't support server version `%s'", version);
146
147   return status;
148 }
149
150 /* Performs key exchange protocol. This is used for both initiator
151    and responder key exchange. This may be called recursively. */
152
153 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
154 {
155   SilcProtocol protocol = (SilcProtocol)context;
156   SilcClientKEInternalContext *ctx = 
157     (SilcClientKEInternalContext *)protocol->context;
158   SilcClient client = (SilcClient)ctx->client;
159   SilcClientConnection conn = ctx->sock->user_data;
160   SilcSKEStatus status = 0;
161
162   SILC_LOG_DEBUG(("Start"));
163
164   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
165     protocol->state = SILC_PROTOCOL_STATE_START;
166
167   switch(protocol->state) {
168   case SILC_PROTOCOL_STATE_START:
169     {
170       /*
171        * Start Protocol
172        */
173       SilcSKE ske;
174
175       /* Allocate Key Exchange object */
176       ske = silc_ske_alloc();
177       ctx->ske = ske;
178       ske->rng = client->rng;
179       ske->user_data = (void *)client;
180       
181       if (ctx->responder == TRUE) {
182         /* Start the key exchange by processing the received security
183            properties packet from initiator. */
184         status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
185                                           silc_version_string,
186                                           ctx->packet->buffer, NULL, NULL);
187       } else {
188         SilcSKEStartPayload *start_payload;
189
190         /* Assemble security properties. */
191         silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, 
192                                               silc_version_string,
193                                               &start_payload);
194
195         /* Start the key exchange by sending our security properties
196            to the remote end. */
197         status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
198                                           start_payload,
199                                           ctx->send_packet,
200                                           context);
201       }
202
203       if (status != SILC_SKE_STATUS_OK) {
204         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
205                           status));
206         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
207                         status));
208
209         protocol->state = SILC_PROTOCOL_STATE_ERROR;
210         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
211         return;
212       }
213
214       /* Advance protocol state and call the next state if we are responder */
215       protocol->state++;
216       if (ctx->responder == TRUE)
217         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
218     }
219     break;
220   case 2:
221     {
222       /* 
223        * Phase 1 
224        */
225       if (ctx->responder == TRUE) {
226         /* Sends the selected security properties to the initiator. */
227         status = 
228           silc_ske_responder_phase_1(ctx->ske, 
229                                      ctx->ske->start_payload,
230                                      ctx->send_packet,
231                                      context);
232       } else {
233         /* Call Phase-1 function. This processes the Key Exchange Start
234            paylaod reply we just got from the responder. The callback
235            function will receive the processed payload where we will
236            save it. */
237         status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer, 
238                                             NULL, NULL);
239       }
240
241       if (status != SILC_SKE_STATUS_OK) {
242         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
243                           status));
244         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
245                         status));
246
247         protocol->state = SILC_PROTOCOL_STATE_ERROR;
248         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
249         return;
250       }
251
252       /* Advance protocol state and call next state if we are initiator */
253       protocol->state++;
254       if (ctx->responder == FALSE)
255         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
256     }
257     break;
258   case 3:
259     {
260       /* 
261        * Phase 2 
262        */
263       if (ctx->responder == TRUE) {
264         /* Process the received Key Exchange 1 Payload packet from
265            the initiator. This also creates our parts of the Diffie
266            Hellman algorithm. */
267         status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer, 
268                                             NULL, NULL);
269       } else {
270         /* Call the Phase-2 function. This creates Diffie Hellman
271            key exchange parameters and sends our public part inside
272            Key Exhange 1 Payload to the responder. */
273         status = 
274           silc_ske_initiator_phase_2(ctx->ske,
275                                      client->public_key,
276                                      ctx->send_packet,
277                                      context);
278       }
279
280       if (status != SILC_SKE_STATUS_OK) {
281         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
282                           status));
283         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
284                         status));
285
286         protocol->state = SILC_PROTOCOL_STATE_ERROR;
287         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
288         return;
289       }
290
291       /* Advance protocol state and call the next state if we are responder */
292       protocol->state++;
293       if (ctx->responder == TRUE)
294         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 100000);
295     }
296     break;
297   case 4:
298     {
299       /* 
300        * Finish protocol
301        */
302       if (ctx->responder == TRUE) {
303         /* This creates the key exchange material and sends our
304            public parts to the initiator inside Key Exchange 2 Payload. */
305         status = 
306           silc_ske_responder_finish(ctx->ske, 
307                                     client->public_key, client->private_key,
308                                     SILC_SKE_PK_TYPE_SILC,
309                                     ctx->send_packet,
310                                     context);
311         status = 0;
312       } else {
313         /* Finish the protocol. This verifies the Key Exchange 2 payload
314            sent by responder. */
315         status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
316                                            silc_client_protocol_ke_verify_key,
317                                            context, NULL, NULL);
318       }
319
320       if (status != SILC_SKE_STATUS_OK) {
321
322         if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
323           client->ops->say(client, conn, 
324                            "Received unsupported server %s public key",
325                            ctx->sock->hostname);
326         } else {
327           client->ops->say(client, conn,
328                            "Error during key exchange protocol with server %s",
329                            ctx->sock->hostname);
330         }
331         protocol->state = SILC_PROTOCOL_STATE_ERROR;
332         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
333         return;
334       }
335       
336       /* Send Ok to the other end. We will end the protocol as server
337          sends Ok to us when we will take the new keys into use. */
338       if (ctx->responder == FALSE)
339         silc_ske_end(ctx->ske, ctx->send_packet, context);
340       
341       /* End the protocol on the next round */
342       protocol->state = SILC_PROTOCOL_STATE_END;
343     }
344     break;
345
346   case SILC_PROTOCOL_STATE_END:
347     {
348       /* 
349        * End protocol
350        */
351       SilcSKEKeyMaterial *keymat;
352       int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher);
353       int hash_len = ctx->ske->prop->hash->hash->hash_len;
354
355       /* Process the key material */
356       keymat = silc_calloc(1, sizeof(*keymat));
357       status = silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len,
358                                              keymat);
359       if (status != SILC_SKE_STATUS_OK) {
360         protocol->state = SILC_PROTOCOL_STATE_ERROR;
361         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 300000);
362         silc_ske_free_key_material(keymat);
363         return;
364       }
365       ctx->keymat = keymat;
366
367       /* Send Ok to the other end if we are responder. If we are initiator
368          we have sent this already. */
369       if (ctx->responder == TRUE)
370         silc_ske_end(ctx->ske, ctx->send_packet, context);
371
372       /* Unregister the timeout task since the protocol has ended. 
373          This was the timeout task to be executed if the protocol is
374          not completed fast enough. */
375       if (ctx->timeout_task)
376         silc_task_unregister(client->timeout_queue, ctx->timeout_task);
377
378       /* Protocol has ended, call the final callback */
379       if (protocol->final_callback)
380         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
381       else
382         silc_protocol_free(protocol);
383     }
384     break;
385
386   case SILC_PROTOCOL_STATE_ERROR:
387     /*
388      * Error during protocol
389      */
390     
391     /* Send abort notification */
392     silc_ske_abort(ctx->ske, ctx->ske->status, 
393                    ctx->send_packet, context);
394
395     /* On error the final callback is always called. */
396     if (protocol->final_callback)
397       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
398     else
399       silc_protocol_free(protocol);
400     break;
401
402   case SILC_PROTOCOL_STATE_FAILURE:
403     /*
404      * Received failure from remote.
405      */
406
407     /* Unregister the timeout task since the protocol has ended. 
408        This was the timeout task to be executed if the protocol is
409        not completed fast enough. */
410     if (ctx->timeout_task)
411       silc_task_unregister(client->timeout_queue, ctx->timeout_task);
412
413     /* On error the final callback is always called. */
414     if (protocol->final_callback)
415       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
416     else
417       silc_protocol_free(protocol);
418     break;
419   case SILC_PROTOCOL_STATE_UNKNOWN:
420     break;
421   }
422 }
423
424 /*
425  * Connection Authentication protocol functions
426  */
427
428 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
429 {
430   SilcProtocol protocol = (SilcProtocol)context;
431   SilcClientConnAuthInternalContext *ctx = 
432     (SilcClientConnAuthInternalContext *)protocol->context;
433   SilcClient client = (SilcClient)ctx->client;
434   SilcClientConnection conn = ctx->sock->user_data;
435
436   SILC_LOG_DEBUG(("Start"));
437
438   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
439     protocol->state = SILC_PROTOCOL_STATE_START;
440
441   switch(protocol->state) {
442   case SILC_PROTOCOL_STATE_START:
443     {
444       /* 
445        * Start protocol. We send authentication data to the server
446        * to be authenticated.
447        */
448       SilcBuffer packet;
449       int payload_len = 0;
450       unsigned char *auth_data = NULL;
451       unsigned int auth_data_len = 0;
452
453       switch(ctx->auth_meth) {
454       case SILC_AUTH_NONE:
455         /* No authentication required */
456         break;
457
458       case SILC_AUTH_PASSWORD:
459         /* Password authentication */
460         if (ctx->auth_data && ctx->auth_data_len) {
461           auth_data = ctx->auth_data;
462           auth_data_len = ctx->auth_data_len;
463           break;
464         }
465
466         client->ops->say(client, conn, 
467                          "Password authentication required by server %s",
468                          ctx->sock->hostname);
469         auth_data = client->ops->ask_passphrase(client, conn);
470         auth_data_len = strlen(auth_data);
471         break;
472
473       case SILC_AUTH_PUBLIC_KEY:
474         /* XXX */
475         break;
476       }
477
478       payload_len = 4 + auth_data_len;
479       packet = silc_buffer_alloc(payload_len);
480       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
481       silc_buffer_format(packet,
482                          SILC_STR_UI_SHORT(payload_len),
483                          SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
484                          SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
485                          SILC_STR_END);
486
487       /* Send the packet to server */
488       silc_client_packet_send(client, ctx->sock,
489                               SILC_PACKET_CONNECTION_AUTH,
490                               NULL, 0, NULL, NULL,
491                               packet->data, packet->len, TRUE);
492
493       if (auth_data) {
494         memset(auth_data, 0, auth_data_len);
495         silc_free(auth_data);
496       }
497       silc_buffer_free(packet);
498       
499       /* Next state is end of protocol */
500       protocol->state = SILC_PROTOCOL_STATE_END;
501     }
502     break;
503
504   case SILC_PROTOCOL_STATE_END:
505     {
506       /* 
507        * End protocol. Nothing special to be done here.
508        */
509
510       /* Protocol has ended, call the final callback */
511       if (protocol->final_callback)
512         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
513       else
514         silc_protocol_free(protocol);
515     }
516     break;
517
518   case SILC_PROTOCOL_STATE_ERROR:
519     {
520       /* 
521        * Error. Send notify to remote.
522        */
523       unsigned char error[4];
524
525       SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
526
527       /* Error in protocol. Send FAILURE packet. Although I don't think
528          this could ever happen on client side. */
529       silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
530                               NULL, 0, NULL, NULL, error, 4, TRUE);
531
532       /* On error the final callback is always called. */
533       if (protocol->final_callback)
534         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
535       else
536         silc_protocol_free(protocol);
537     }
538
539   case SILC_PROTOCOL_STATE_FAILURE:
540     /*
541      * Received failure from remote.
542      */
543
544     /* On error the final callback is always called. */
545     if (protocol->final_callback)
546       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
547     else
548       silc_protocol_free(protocol);
549     break;
550
551   case SILC_PROTOCOL_STATE_UNKNOWN:
552     break;
553   }
554 }
555
556 /* Registers protocols used in client */
557
558 void silc_client_protocols_register(void)
559 {
560   silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
561                          silc_client_protocol_connection_auth);
562   silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
563                          silc_client_protocol_key_exchange);
564 }
565
566 /* Unregisters protocols */
567
568 void silc_client_protocols_unregister(void)
569 {
570   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
571                            silc_client_protocol_connection_auth);
572   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
573                            silc_client_protocol_key_exchange);
574 }