Change code to use new SilcPacketContext reference count system.
[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 - 2000 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 /* XXX TODO */
123
124 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
125                                      unsigned int len)
126 {
127   return SILC_SKE_STATUS_OK;
128 }
129
130 /* Performs key exchange protocol. This is used for both initiator
131    and responder key exchange. This may be called recursively. */
132
133 SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
134 {
135   SilcProtocol protocol = (SilcProtocol)context;
136   SilcClientKEInternalContext *ctx = 
137     (SilcClientKEInternalContext *)protocol->context;
138   SilcClient client = (SilcClient)ctx->client;
139   SilcClientConnection conn = ctx->sock->user_data;
140   SilcSKEStatus status = 0;
141
142   SILC_LOG_DEBUG(("Start"));
143
144   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
145     protocol->state = SILC_PROTOCOL_STATE_START;
146
147   switch(protocol->state) {
148   case SILC_PROTOCOL_STATE_START:
149     {
150       /*
151        * Start Protocol
152        */
153       SilcSKE ske;
154
155       /* Allocate Key Exchange object */
156       ske = silc_ske_alloc();
157       ctx->ske = ske;
158       ske->rng = client->rng;
159       
160       if (ctx->responder == TRUE) {
161 #if 0
162         SilcBuffer start_payload;
163
164
165         /* Start the key exchange by processing the received security
166            properties packet from initiator. */
167         status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
168                                           start_payload,
169                                           silc_client_protocol_ke_send_packet,
170                                           context);
171 #endif
172       } else {
173         SilcSKEStartPayload *start_payload;
174
175         /* Assemble security properties. */
176         silc_ske_assemble_security_properties(ske, SILC_SKE_SP_FLAG_NONE, 
177                                               silc_version_string,
178                                               &start_payload);
179
180         /* Start the key exchange by sending our security properties
181            to the remote end. */
182         status = silc_ske_initiator_start(ske, ctx->rng, ctx->sock,
183                                           start_payload,
184                                           silc_client_protocol_ke_send_packet,
185                                           context);
186       }
187
188       if (status != SILC_SKE_STATUS_OK) {
189         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
190                           status));
191         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
192                         status));
193
194         protocol->state = SILC_PROTOCOL_STATE_ERROR;
195         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
196         return;
197       }
198
199       /* Advance the state of the protocol. */
200       protocol->state++;
201     }
202     break;
203   case 2:
204     {
205       /* 
206        * Phase 1 
207        */
208       if (ctx->responder == TRUE) {
209 #if 0
210         status = 
211           silc_ske_responder_phase_1(ctx->ske, 
212                                      ctx->ske->start_payload,
213                                      silc_server_protocol_ke_send_packet,
214                                      context);
215 #endif
216       } else {
217         /* Call Phase-1 function. This processes the Key Exchange Start
218            paylaod reply we just got from the responder. The callback
219            function will receive the processed payload where we will
220            save it. */
221         status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer, 
222                                             NULL, NULL);
223       }
224
225       if (status != SILC_SKE_STATUS_OK) {
226         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
227                           status));
228         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
229                         status));
230
231         protocol->state = SILC_PROTOCOL_STATE_ERROR;
232         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
233         return;
234       }
235
236       /* Advance the state of the protocol and call the next state. */
237       protocol->state++;
238       protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
239     }
240     break;
241   case 3:
242     {
243       /* 
244        * Phase 2 
245        */
246       if (ctx->responder == TRUE) {
247 #if 0
248         status = 
249           silc_ske_responder_phase_2(ctx->ske, 
250                                      ctx->ske->start_payload,
251                                      silc_server_protocol_ke_send_packet,
252                                      context);
253 #endif
254       } else {
255         /* Call the Phase-2 function. This creates Diffie Hellman
256            key exchange parameters and sends our public part inside
257            Key Exhange 1 Payload to the responder. */
258         status = 
259           silc_ske_initiator_phase_2(ctx->ske,
260                                      client->public_key,
261                                      silc_client_protocol_ke_send_packet,
262                                      context);
263       }
264
265       if (status != SILC_SKE_STATUS_OK) {
266         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
267                           status));
268         SILC_LOG_DEBUG(("Error (type %d) during Key Exchange protocol",
269                         status));
270
271         protocol->state = SILC_PROTOCOL_STATE_ERROR;
272         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
273         return;
274       }
275
276       /* Advance the state of the protocol. */
277       protocol->state++;
278     }
279     break;
280   case 4:
281     {
282       /* 
283        * Finish protocol
284        */
285       if (ctx->responder == TRUE) {
286         status = 0;
287 #if 0
288         status = 
289           silc_ske_responder_phase_2(ctx->ske, 
290                                      ctx->ske->start_payload,
291                                      silc_server_protocol_ke_send_packet,
292                                      context);
293 #endif
294       } else {
295         /* Finish the protocol. This verifies the Key Exchange 2 payload
296            sent by responder. */
297         status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer,
298                                            silc_client_protocol_ke_verify_key,
299                                            context, NULL, NULL);
300       }
301
302       if (status != SILC_SKE_STATUS_OK) {
303
304         if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) {
305           client->ops->say(client, conn, 
306                            "Received unsupported server %s public key",
307                            ctx->sock->hostname);
308         } else {
309           client->ops->say(client, conn,
310                            "Error during key exchange protocol with server %s",
311                            ctx->sock->hostname);
312         }
313         protocol->state = SILC_PROTOCOL_STATE_ERROR;
314         protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
315         return;
316       }
317       
318       /* Send Ok to the other end. We will end the protocol as server
319          sends Ok to us when we will take the new keys into use. */
320       silc_ske_end(ctx->ske, silc_client_protocol_ke_send_packet, context);
321       
322       /* End the protocol on the next round */
323       protocol->state = SILC_PROTOCOL_STATE_END;
324     }
325     break;
326
327   case SILC_PROTOCOL_STATE_END:
328     {
329       /* 
330        * End protocol
331        */
332       SilcSKEKeyMaterial *keymat;
333
334       /* Process the key material */
335       keymat = silc_calloc(1, sizeof(*keymat));
336       silc_ske_process_key_material(ctx->ske, 16, (16 * 8), 16, keymat);
337
338       /* Take the negotiated keys into use. */
339       silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, keymat,
340                                        ctx->ske->prop->cipher,
341                                        ctx->ske->prop->pkcs,
342                                        ctx->ske->prop->hash);
343
344       /* Protocol has ended, call the final callback */
345       if (protocol->final_callback)
346         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
347       else
348         silc_protocol_free(protocol);
349     }
350     break;
351
352   case SILC_PROTOCOL_STATE_ERROR:
353     /*
354      * Error during protocol
355      */
356     
357     /* Send abort notification */
358     silc_ske_abort(ctx->ske, ctx->ske->status, 
359                    silc_client_protocol_ke_send_packet,
360                    context);
361
362     /* On error the final callback is always called. */
363     if (protocol->final_callback)
364       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
365     else
366       silc_protocol_free(protocol);
367     break;
368
369   case SILC_PROTOCOL_STATE_FAILURE:
370     /*
371      * Received failure from remote.
372      */
373
374     /* On error the final callback is always called. */
375     if (protocol->final_callback)
376       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
377     else
378       silc_protocol_free(protocol);
379     break;
380   case SILC_PROTOCOL_STATE_UNKNOWN:
381     break;
382   }
383 }
384
385 /*
386  * Connection Authentication protocol functions
387  */
388
389 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
390 {
391   SilcProtocol protocol = (SilcProtocol)context;
392   SilcClientConnAuthInternalContext *ctx = 
393     (SilcClientConnAuthInternalContext *)protocol->context;
394   SilcClient client = (SilcClient)ctx->client;
395   SilcClientConnection conn = ctx->sock->user_data;
396
397   SILC_LOG_DEBUG(("Start"));
398
399   if (protocol->state == SILC_PROTOCOL_STATE_UNKNOWN)
400     protocol->state = SILC_PROTOCOL_STATE_START;
401
402   switch(protocol->state) {
403   case SILC_PROTOCOL_STATE_START:
404     {
405       /* 
406        * Start protocol. We send authentication data to the server
407        * to be authenticated.
408        */
409       SilcBuffer packet;
410       int payload_len = 0;
411       unsigned char *auth_data = NULL;
412       unsigned int auth_data_len = 0;
413
414       switch(ctx->auth_meth) {
415       case SILC_PROTOCOL_CONN_AUTH_NONE:
416         /* No authentication required */
417         break;
418
419       case SILC_PROTOCOL_CONN_AUTH_PASSWORD:
420         /* Password authentication */
421         if (ctx->auth_data && ctx->auth_data_len) {
422           auth_data = ctx->auth_data;
423           auth_data_len = ctx->auth_data_len;
424           break;
425         }
426
427         client->ops->say(client, conn, 
428                          "Password authentication required by server %s",
429                          ctx->sock->hostname);
430         auth_data = client->ops->ask_passphrase(client, conn);
431         auth_data_len = strlen(auth_data);
432         break;
433
434       case SILC_PROTOCOL_CONN_AUTH_PUBLIC_KEY:
435         /* XXX */
436         break;
437       }
438
439       payload_len = 4 + auth_data_len;
440       packet = silc_buffer_alloc(payload_len);
441       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
442       silc_buffer_format(packet,
443                          SILC_STR_UI_SHORT(payload_len),
444                          SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
445                          SILC_STR_UI_XNSTRING(auth_data, auth_data_len),
446                          SILC_STR_END);
447
448       /* Send the packet to server */
449       silc_client_packet_send(client, ctx->sock,
450                               SILC_PACKET_CONNECTION_AUTH,
451                               NULL, 0, NULL, NULL,
452                               packet->data, packet->len, TRUE);
453
454       if (auth_data) {
455         memset(auth_data, 0, auth_data_len);
456         silc_free(auth_data);
457       }
458       silc_buffer_free(packet);
459       
460       /* Next state is end of protocol */
461       protocol->state = SILC_PROTOCOL_STATE_END;
462     }
463     break;
464
465   case SILC_PROTOCOL_STATE_END:
466     {
467       /* 
468        * End protocol. Nothing special to be done here.
469        */
470
471       /* Protocol has ended, call the final callback */
472       if (protocol->final_callback)
473         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
474       else
475         silc_protocol_free(protocol);
476     }
477     break;
478
479   case SILC_PROTOCOL_STATE_ERROR:
480     {
481       /* 
482        * Error. Send notify to remote.
483        */
484       unsigned char error[4];
485
486       SILC_PUT32_MSB(SILC_CONN_AUTH_FAILED, error);
487
488       /* Error in protocol. Send FAILURE packet. Although I don't think
489          this could ever happen on client side. */
490       silc_client_packet_send(client, ctx->sock, SILC_PACKET_FAILURE,
491                               NULL, 0, NULL, NULL, error, 4, TRUE);
492
493       /* On error the final callback is always called. */
494       if (protocol->final_callback)
495         protocol->execute_final(client->timeout_queue, 0, protocol, fd);
496       else
497         silc_protocol_free(protocol);
498     }
499
500   case SILC_PROTOCOL_STATE_FAILURE:
501     /*
502      * Received failure from remote.
503      */
504
505     /* On error the final callback is always called. */
506     if (protocol->final_callback)
507       protocol->execute_final(client->timeout_queue, 0, protocol, fd);
508     else
509       silc_protocol_free(protocol);
510     break;
511
512   case SILC_PROTOCOL_STATE_UNKNOWN:
513     break;
514   }
515 }
516
517 /* Registers protocols used in client */
518
519 void silc_client_protocols_register(void)
520 {
521   silc_protocol_register(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
522                          silc_client_protocol_connection_auth);
523   silc_protocol_register(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
524                          silc_client_protocol_key_exchange);
525 }
526
527 /* Unregisters protocols */
528
529 void silc_client_protocols_unregister(void)
530 {
531   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
532                            silc_client_protocol_connection_auth);
533   silc_protocol_unregister(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
534                            silc_client_protocol_key_exchange);
535 }