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