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
27 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth);
28 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange);
29
30 extern char *silc_version_string;
31
32 /*
33  * Key Exhange protocol functions
34  */
35
36 /* Function that is called when SKE protocol sends packets to network. */
37
38 static void silc_client_protocol_ke_send_packet(SilcSKE ske,
39                                                 SilcBuffer packet,
40                                                 SilcPacketType type,
41                                                 void *context)
42 {
43   SilcProtocol protocol = (SilcProtocol)context;
44   SilcClientKEInternalContext *ctx = 
45     (SilcClientKEInternalContext *)protocol->context;
46   SilcClient client = (SilcClient)ctx->client;
47
48   /* Send the packet immediately */
49   silc_client_packet_send(client, ske->sock, type, NULL, 0, NULL, NULL,
50                           packet->data, packet->len, TRUE);
51
52 }
53
54 /* Callback that is called when we have received KE2 payload from
55    responder. We try to verify the public key now. */
56
57 static SilcSKEStatus 
58 silc_client_protocol_ke_verify_key(SilcSKE ske,
59                                    unsigned char *pk_data,
60                                    unsigned int pk_len,
61                                    SilcSKEPKType pk_type,
62                                    void *context)
63 {
64   SilcProtocol protocol = (SilcProtocol)context;
65   SilcClientKEInternalContext *ctx = 
66     (SilcClientKEInternalContext *)protocol->context;
67   SilcClient client = (SilcClient)ctx->client;
68
69   SILC_LOG_DEBUG(("Start"));
70
71   /* Verify server key from user. */
72   if (!client->ops->verify_server_key(client, ctx->sock->user_data, 
73                                       pk_data, pk_len, pk_type))
74     return SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
75
76   return SILC_SKE_STATUS_OK;
77 }
78
79 /* Sets the negotiated key material into use for particular connection. */
80
81 static void silc_client_protocol_ke_set_keys(SilcSKE ske,
82                                              SilcSocketConnection sock,
83                                              SilcSKEKeyMaterial *keymat,
84                                              SilcCipher cipher,
85                                              SilcPKCS pkcs,
86                                              SilcHash hash)
87 {
88   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
89   SilcHash nhash;
90
91   SILC_LOG_DEBUG(("Setting new keys into use"));
92
93   /* Allocate cipher to be used in the communication */
94   silc_cipher_alloc(cipher->cipher->name, &conn->send_key);
95   silc_cipher_alloc(cipher->cipher->name, &conn->receive_key);
96
97   conn->send_key->cipher->set_key(conn->send_key->context, 
98                                  keymat->send_enc_key, 
99                                  keymat->enc_key_len);
100   conn->send_key->set_iv(conn->send_key, keymat->send_iv);
101   conn->receive_key->cipher->set_key(conn->receive_key->context, 
102                                     keymat->receive_enc_key, 
103                                     keymat->enc_key_len);
104   conn->receive_key->set_iv(conn->receive_key, keymat->receive_iv);
105
106   /* Allocate PKCS to be used */
107 #if 0
108   /* XXX Do we ever need to allocate PKCS for the connection??
109      If yes, we need to change KE protocol to get the initiators
110      public key. */
111   silc_pkcs_alloc(pkcs->pkcs->name, &conn->public_Key);
112   silc_pkcs_set_public_key(conn->public_key, ske->ke2_payload->pk_data, 
113                            ske->ke2_payload->pk_len);
114 #endif
115
116   /* Save HMAC key to be used in the communication. */
117   silc_hash_alloc(hash->hash->name, &nhash);
118   silc_hmac_alloc(nhash, &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 #if 0
183         SilcBuffer start_payload;
184
185
186         /* Start the key exchange by processing the received security
187            properties packet from initiator. */
188         status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
189                                           start_payload,
190                                           silc_client_protocol_ke_send_packet,
191                                           context);
192 #endif
193       } else {
194         SilcSKEStartPayload *start_payload;
195
196         /* Assemble security properties. */
197         silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, 
198                                               silc_version_string,
199                                               &start_payload);
200
201         /* Start the key exchange by sending our security properties
202            to the remote end. */
203         status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
204                                           start_payload,
205                                           silc_client_protocol_ke_send_packet,
206                                           context);
207       }
208
209       if (status != SILC_SKE_STATUS_OK) {
210         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
211                           status));
212         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
213                         status));
214
215         protocol->state = SILC_PROTOCOL_STATE_ERROR;
216         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
217         return;
218       }
219
220       /* Advance the state of the protocol. */
221       protocol->state++;
222     }
223     break;
224   case 2:
225     {
226       /* 
227        * Phase 1 
228        */
229       if (ctx->responder == TRUE) {
230 #if 0
231         status = 
232           silc_ske_responder_phase_1(ctx->ske, 
233                                      ctx->ske->start_payload,
234                                      silc_server_protocol_ke_send_packet,
235                                      context);
236 #endif
237       } else {
238         /* Call Phase-1 function. This processes the Key Exchange Start
239            paylaod reply we just got from the responder. The callback
240            function will receive the processed payload where we will
241            save it. */
242         status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer, 
243                                             NULL, NULL);
244       }
245
246       if (status != SILC_SKE_STATUS_OK) {
247         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
248                           status));
249         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
250                         status));
251
252         protocol->state = SILC_PROTOCOL_STATE_ERROR;
253         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
254         return;
255       }
256
257       /* Advance the state of the protocol and call the next state. */
258       protocol->state++;
259       protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
260     }
261     break;
262   case 3:
263     {
264       /* 
265        * Phase 2 
266        */
267       if (ctx->responder == TRUE) {
268 #if 0
269         status = 
270           silc_ske_responder_phase_2(ctx->ske, 
271                                      ctx->ske->start_payload,
272                                      silc_server_protocol_ke_send_packet,
273                                      context);
274 #endif
275       } else {
276         /* Call the Phase-2 function. This creates Diffie Hellman
277            key exchange parameters and sends our public part inside
278            Key Exhange 1 Payload to the responder. */
279         status = 
280           silc_ske_initiator_phase_2(ctx->ske,
281                                      client->public_key,
282                                      silc_client_protocol_ke_send_packet,
283                                      context);
284       }
285
286       if (status != SILC_SKE_STATUS_OK) {
287         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
288                           status));
289         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
290                         status));
291
292         protocol->state = SILC_PROTOCOL_STATE_ERROR;
293         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
294         return;
295       }
296
297       /* Advance the state of the protocol. */
298       protocol->state++;
299     }
300     break;
301   case 4:
302     {
303       /* 
304        * Finish protocol
305        */
306       if (ctx->responder == TRUE) {
307         status = 0;
308 #if 0
309         status = 
310           silc_ske_responder_phase_2(ctx->ske, 
311                                      ctx->ske->start_payload,
312                                      silc_server_protocol_ke_send_packet,
313                                      context);
314 #endif
315       } else {
316         /* Finish the protocol. This verifies the Key Exchange 2 payload
317            sent by responder. */
318         status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
319                                            silc_client_protocol_ke_verify_key,
320                                            context, NULL, NULL);
321       }
322
323       if (status != SILC_SKE_STATUS_OK) {
324
325         if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
326           client->ops->say(client, conn, 
327                            "Received unsupported server %s public key",
328                            ctx->sock->hostname);
329         } else {
330           client->ops->say(client, conn,
331                            "Error during key exchange protocol with server %s",
332                            ctx->sock->hostname);
333         }
334         protocol->state = SILC_PROTOCOL_STATE_ERROR;
335         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
336         return;
337       }
338       
339       /* Send Ok to the other end. We will end the protocol as server
340          sends Ok to us when we will take the new keys into use. */
341       silc_ske_end(ctx->ske, silc_client_protocol_ke_send_packet, context);
342       
343       /* End the protocol on the next round */
344       protocol->state = SILC_PROTOCOL_STATE_END;
345     }
346     break;
347
348   case SILC_PROTOCOL_STATE_END:
349     {
350       /* 
351        * End protocol
352        */
353       SilcSKEKeyMaterial *keymat;
354       int key_len = silc_cipher_get_key_len(ctx->ske->prop->cipher, NULL);
355       int hash_len = ctx->ske->prop->hash->hash->hash_len;
356
357       /* Process the key material */
358       keymat = silc_calloc(1, sizeof(*keymat));
359       silc_ske_process_key_material(ctx->ske, 16, key_len, hash_len, 
360                                     keymat);
361
362       /* Take the negotiated keys into use. */
363       silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
364                                        ctx->ske->prop->cipher,
365                                        ctx->ske->prop->pkcs,
366                                        ctx->ske->prop->hash);
367
368       silc_ske_free_key_material(keymat);
369
370       /* Protocol has ended, call the final callback */
371       if (protocol->final_callback)
372         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
373       else
374         silc_protocol_free(protocol);
375     }
376     break;
377
378   case SILC_PROTOCOL_STATE_ERROR:
379     /*
380      * Error during protocol
381      */
382     
383     /* Send abort notification */
384     silc_ske_abort(ctx->ske, ctx->ske->status, 
385                    silc_client_protocol_ke_send_packet,
386                    context);
387
388     /* On error the final callback is always called. */
389     if (protocol->final_callback)
390       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
391     else
392       silc_protocol_free(protocol);
393     break;
394
395   case SILC_PROTOCOL_STATE_FAILURE:
396     /*
397      * Received failure from remote.
398      */
399
400     /* On error the final callback is always called. */
401     if (protocol->final_callback)
402       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
403     else
404       silc_protocol_free(protocol);
405     break;
406   case SILC_PROTOCOL_STATE_UNKNOWN:
407     break;
408   }
409 }
410
411 /*
412  * Connection Authentication protocol functions
413  */
414
415 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
416 {
417   SilcProtocol protocol = (SilcProtocol)context;
418   SilcClientConnAuthInternalContext *ctx = 
419     (SilcClientConnAuthInternalContext *)protocol->context;
420   SilcClient client = (SilcClient)ctx->client;
421   SilcClientConnection conn = ctx->sock->user_data;
422
423   SILC_LOG_DEBUG(("Start"));
424
425   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
426     protocol->state = SILC_PROTOCOL_STATE_START;
427
428   switch(protocol->state) {
429   case SILC_PROTOCOL_STATE_START:
430     {
431       /* 
432        * Start protocol. We send authentication data to the server
433        * to be authenticated.
434        */
435       SilcBuffer packet;
436       int payload_len = 0;
437       unsigned char *auth_data = NULL;
438       unsigned int auth_data_len = 0;
439
440       switch(ctx->auth_meth) {
441       case SILC_AUTH_NONE:
442         /* No authentication required */
443         break;
444
445       case SILC_AUTH_PASSWORD:
446         /* Password authentication */
447         if (ctx->auth_data && ctx->auth_data_len) {
448           auth_data = ctx->auth_data;
449           auth_data_len = ctx->auth_data_len;
450           break;
451         }
452
453         client->ops->say(client, conn, 
454                          "Password authentication required by server %s",
455                          ctx->sock->hostname);
456         auth_data = client->ops->ask_passphrase(client, conn);
457         auth_data_len = strlen(auth_data);
458         break;
459
460       case SILC_AUTH_PUBLIC_KEY:
461         /* XXX */
462         break;
463       }
464
465       payload_len = 4 + auth_data_len;
466       packet = silc_buffer_alloc(payload_len);
467       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
468       silc_buffer_format(packet,
469                          SILC_STR_UI_SHORT(payload_len),
470                          SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
471                          SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
472                          SILC_STR_END);
473
474       /* Send the packet to server */
475       silc_client_packet_send(client, ctx->sock,
476                               SILC_PACKET_CONNECTION_AUTH,
477                               NULL, 0, NULL, NULL,
478                               packet->data, packet->len, TRUE);
479
480       if (auth_data) {
481         memset(auth_data, 0, auth_data_len);
482         silc_free(auth_data);
483       }
484       silc_buffer_free(packet);
485       
486       /* Next state is end of protocol */
487       protocol->state = SILC_PROTOCOL_STATE_END;
488     }
489     break;
490
491   case SILC_PROTOCOL_STATE_END:
492     {
493       /* 
494        * End protocol. Nothing special to be done here.
495        */
496
497       /* Protocol has ended, call the final callback */
498       if (protocol->final_callback)
499         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
500       else
501         silc_protocol_free(protocol);
502     }
503     break;
504
505   case SILC_PROTOCOL_STATE_ERROR:
506     {
507       /* 
508        * Error. Send notify to remote.
509        */
510       unsigned char error[4];
511
512       SILC_PUT32_MSB(SILC_AUTH_FAILED, error);
513
514       /* Error in protocol. Send FAILURE packet. Although I don't think
515          this could ever happen on client side. */
516       silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
517                               NULL, 0, NULL, NULL, error, 4, TRUE);
518
519       /* On error the final callback is always called. */
520       if (protocol->final_callback)
521         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
522       else
523         silc_protocol_free(protocol);
524     }
525
526   case SILC_PROTOCOL_STATE_FAILURE:
527     /*
528      * Received failure from remote.
529      */
530
531     /* On error the final callback is always called. */
532     if (protocol->final_callback)
533       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
534     else
535       silc_protocol_free(protocol);
536     break;
537
538   case SILC_PROTOCOL_STATE_UNKNOWN:
539     break;
540   }
541 }
542
543 /* Registers protocols used in client */
544
545 void silc_client_protocols_register(void)
546 {
547   silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
548                          silc_client_protocol_connection_auth);
549   silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
550                          silc_client_protocol_key_exchange);
551 }
552
553 /* Unregisters protocols */
554
555 void silc_client_protocols_unregister(void)
556 {
557   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
558                            silc_client_protocol_connection_auth);
559   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
560                            silc_client_protocol_key_exchange);
561 }