LCOV - code coverage report
Current view: top level - openssh-6.6p1 - roaming_client.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 131 0.0 %
Date: 2014-08-01 Functions: 0 6 0.0 %
Branches: 0 48 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: roaming_client.c,v 1.7 2014/01/09 23:20:00 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 2004-2009 AppGate Network Security AB
       4                 :            :  *
       5                 :            :  * Permission to use, copy, modify, and distribute this software for any
       6                 :            :  * purpose with or without fee is hereby granted, provided that the above
       7                 :            :  * copyright notice and this permission notice appear in all copies.
       8                 :            :  *
       9                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10                 :            :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11                 :            :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12                 :            :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13                 :            :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14                 :            :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15                 :            :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "includes.h"
      19                 :            : 
      20                 :            : #include "openbsd-compat/sys-queue.h"
      21                 :            : #include <sys/types.h>
      22                 :            : #include <sys/socket.h>
      23                 :            : 
      24                 :            : #ifdef HAVE_INTTYPES_H
      25                 :            : #include <inttypes.h>
      26                 :            : #endif
      27                 :            : #include <signal.h>
      28                 :            : #include <string.h>
      29                 :            : #include <unistd.h>
      30                 :            : 
      31                 :            : #include <openssl/crypto.h>
      32                 :            : #include <openssl/sha.h>
      33                 :            : 
      34                 :            : #include "xmalloc.h"
      35                 :            : #include "buffer.h"
      36                 :            : #include "channels.h"
      37                 :            : #include "cipher.h"
      38                 :            : #include "dispatch.h"
      39                 :            : #include "clientloop.h"
      40                 :            : #include "log.h"
      41                 :            : #include "match.h"
      42                 :            : #include "misc.h"
      43                 :            : #include "packet.h"
      44                 :            : #include "ssh.h"
      45                 :            : #include "key.h"
      46                 :            : #include "kex.h"
      47                 :            : #include "readconf.h"
      48                 :            : #include "roaming.h"
      49                 :            : #include "ssh2.h"
      50                 :            : #include "sshconnect.h"
      51                 :            : #include "digest.h"
      52                 :            : 
      53                 :            : /* import */
      54                 :            : extern Options options;
      55                 :            : extern char *host;
      56                 :            : extern struct sockaddr_storage hostaddr;
      57                 :            : extern int session_resumed;
      58                 :            : 
      59                 :            : static u_int32_t roaming_id;
      60                 :            : static u_int64_t cookie;
      61                 :            : static u_int64_t lastseenchall;
      62                 :            : static u_int64_t key1, key2, oldkey1, oldkey2;
      63                 :            : 
      64                 :            : void
      65                 :          0 : roaming_reply(int type, u_int32_t seq, void *ctxt)
      66                 :            : {
      67         [ #  # ]:          0 :         if (type == SSH2_MSG_REQUEST_FAILURE) {
      68                 :          0 :                 logit("Server denied roaming");
      69                 :          0 :                 return;
      70                 :            :         }
      71                 :          0 :         verbose("Roaming enabled");
      72                 :          0 :         roaming_id = packet_get_int();
      73                 :          0 :         cookie = packet_get_int64();
      74                 :          0 :         key1 = oldkey1 = packet_get_int64();
      75                 :          0 :         key2 = oldkey2 = packet_get_int64();
      76                 :          0 :         set_out_buffer_size(packet_get_int() + get_snd_buf_size());
      77                 :          0 :         roaming_enabled = 1;
      78                 :            : }
      79                 :            : 
      80                 :            : void
      81                 :          0 : request_roaming(void)
      82                 :            : {
      83                 :          0 :         packet_start(SSH2_MSG_GLOBAL_REQUEST);
      84                 :          0 :         packet_put_cstring(ROAMING_REQUEST);
      85                 :          0 :         packet_put_char(1);
      86                 :          0 :         packet_put_int(get_recv_buf_size());
      87                 :          0 :         packet_send();
      88                 :          0 :         client_register_global_confirm(roaming_reply, NULL);
      89                 :          0 : }
      90                 :            : 
      91                 :            : static void
      92                 :          0 : roaming_auth_required(void)
      93                 :            : {
      94                 :            :         u_char digest[SSH_DIGEST_MAX_LENGTH];
      95                 :            :         Buffer b;
      96                 :            :         u_int64_t chall, oldchall;
      97                 :            : 
      98                 :          0 :         chall = packet_get_int64();
      99                 :          0 :         oldchall = packet_get_int64();
     100         [ #  # ]:          0 :         if (oldchall != lastseenchall) {
     101                 :          0 :                 key1 = oldkey1;
     102                 :          0 :                 key2 = oldkey2;
     103                 :            :         }
     104                 :          0 :         lastseenchall = chall;
     105                 :            : 
     106                 :          0 :         buffer_init(&b);
     107                 :          0 :         buffer_put_int64(&b, cookie);
     108                 :          0 :         buffer_put_int64(&b, chall);
     109         [ #  # ]:          0 :         if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0)
     110                 :          0 :                 fatal("%s: ssh_digest_buffer failed", __func__);
     111                 :          0 :         buffer_free(&b);
     112                 :            : 
     113                 :          0 :         packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
     114                 :          0 :         packet_put_int64(key1 ^ get_recv_bytes());
     115                 :          0 :         packet_put_raw(digest, ssh_digest_bytes(SSH_DIGEST_SHA1));
     116                 :          0 :         packet_send();
     117                 :            : 
     118                 :          0 :         oldkey1 = key1;
     119                 :          0 :         oldkey2 = key2;
     120                 :          0 :         calculate_new_key(&key1, cookie, chall);
     121                 :          0 :         calculate_new_key(&key2, cookie, chall);
     122                 :            : 
     123                 :          0 :         debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
     124                 :          0 :         debug("Sent roaming_auth packet");
     125                 :          0 : }
     126                 :            : 
     127                 :            : int
     128                 :          0 : resume_kex(void)
     129                 :            : {
     130                 :            :         /*
     131                 :            :          * This should not happen - if the client sends the kex method
     132                 :            :          * resume@appgate.com then the kex is done in roaming_resume().
     133                 :            :          */
     134                 :          0 :         return 1;
     135                 :            : }
     136                 :            : 
     137                 :            : static int
     138                 :          0 : roaming_resume(void)
     139                 :            : {
     140                 :            :         u_int64_t recv_bytes;
     141                 :          0 :         char *str = NULL, *kexlist = NULL, *c;
     142                 :            :         int i, type;
     143                 :          0 :         int timeout_ms = options.connection_timeout * 1000;
     144                 :            :         u_int len;
     145                 :          0 :         u_int32_t rnd = 0;
     146                 :            : 
     147                 :          0 :         resume_in_progress = 1;
     148                 :            : 
     149                 :            :         /* Exchange banners */
     150                 :          0 :         ssh_exchange_identification(timeout_ms);
     151                 :          0 :         packet_set_nonblocking();
     152                 :            : 
     153                 :            :         /* Send a kexinit message with resume@appgate.com as only kex algo */
     154                 :          0 :         packet_start(SSH2_MSG_KEXINIT);
     155         [ #  # ]:          0 :         for (i = 0; i < KEX_COOKIE_LEN; i++) {
     156         [ #  # ]:          0 :                 if (i % 4 == 0)
     157                 :          0 :                         rnd = arc4random();
     158                 :          0 :                 packet_put_char(rnd & 0xff);
     159                 :          0 :                 rnd >>= 8;
     160                 :            :         }
     161                 :          0 :         packet_put_cstring(KEX_RESUME);
     162         [ #  # ]:          0 :         for (i = 1; i < PROPOSAL_MAX; i++) {
     163                 :            :                 /* kex algorithm added so start with i=1 and not 0 */
     164                 :          0 :                 packet_put_cstring(""); /* Not used when we resume */
     165                 :            :         }
     166                 :          0 :         packet_put_char(1); /* first kex_packet follows */
     167                 :          0 :         packet_put_int(0); /* reserved */
     168                 :          0 :         packet_send();
     169                 :            : 
     170                 :            :         /* Assume that resume@appgate.com will be accepted */
     171                 :          0 :         packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
     172                 :          0 :         packet_put_int(roaming_id);
     173                 :          0 :         packet_send();
     174                 :            : 
     175                 :            :         /* Read the server's kexinit and check for resume@appgate.com */
     176         [ #  # ]:          0 :         if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
     177                 :          0 :                 debug("expected kexinit on resume, got %d", type);
     178                 :          0 :                 goto fail;
     179                 :            :         }
     180         [ #  # ]:          0 :         for (i = 0; i < KEX_COOKIE_LEN; i++)
     181                 :          0 :                 (void)packet_get_char();
     182                 :          0 :         kexlist = packet_get_string(&len);
     183         [ #  # ]:          0 :         if (!kexlist
     184         [ #  # ]:          0 :             || (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
     185                 :          0 :                 debug("server doesn't allow resume");
     186                 :          0 :                 goto fail;
     187                 :            :         }
     188                 :          0 :         free(str);
     189         [ #  # ]:          0 :         for (i = 1; i < PROPOSAL_MAX; i++) {
     190                 :            :                 /* kex algorithm taken care of so start with i=1 and not 0 */
     191                 :          0 :                 free(packet_get_string(&len));
     192                 :            :         }
     193                 :          0 :         i = packet_get_char(); /* first_kex_packet_follows */
     194 [ #  # ][ #  # ]:          0 :         if (i && (c = strchr(kexlist, ',')))
     195                 :          0 :                 *c = 0;
     196 [ #  # ][ #  # ]:          0 :         if (i && strcmp(kexlist, KEX_RESUME)) {
     197                 :          0 :                 debug("server's kex guess (%s) was wrong, skipping", kexlist);
     198                 :          0 :                 (void)packet_read(); /* Wrong guess - discard packet */
     199                 :            :         }
     200                 :            : 
     201                 :            :         /*
     202                 :            :          * Read the ROAMING_AUTH_REQUIRED challenge from the server and
     203                 :            :          * send ROAMING_AUTH
     204                 :            :          */
     205         [ #  # ]:          0 :         if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
     206                 :          0 :                 debug("expected roaming_auth_required, got %d", type);
     207                 :          0 :                 goto fail;
     208                 :            :         }
     209                 :          0 :         roaming_auth_required();
     210                 :            : 
     211                 :            :         /* Read ROAMING_AUTH_OK from the server */
     212         [ #  # ]:          0 :         if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
     213                 :          0 :                 debug("expected roaming_auth_ok, got %d", type);
     214                 :          0 :                 goto fail;
     215                 :            :         }
     216                 :          0 :         recv_bytes = packet_get_int64() ^ oldkey2;
     217                 :          0 :         debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
     218                 :          0 :         resend_bytes(packet_get_connection_out(), &recv_bytes);
     219                 :            : 
     220                 :          0 :         resume_in_progress = 0;
     221                 :            : 
     222                 :          0 :         session_resumed = 1; /* Tell clientloop */
     223                 :            : 
     224                 :          0 :         return 0;
     225                 :            : 
     226                 :            : fail:
     227                 :          0 :         free(kexlist);
     228         [ #  # ]:          0 :         if (packet_get_connection_in() == packet_get_connection_out())
     229                 :          0 :                 close(packet_get_connection_in());
     230                 :            :         else {
     231                 :          0 :                 close(packet_get_connection_in());
     232                 :          0 :                 close(packet_get_connection_out());
     233                 :            :         }
     234                 :            :         return 1;
     235                 :            : }
     236                 :            : 
     237                 :            : int
     238                 :          0 : wait_for_roaming_reconnect(void)
     239                 :            : {
     240                 :            :         static int reenter_guard = 0;
     241                 :          0 :         int timeout_ms = options.connection_timeout * 1000;
     242                 :            :         int c;
     243                 :            : 
     244         [ #  # ]:          0 :         if (reenter_guard != 0)
     245                 :          0 :                 fatal("Server refused resume, roaming timeout may be exceeded");
     246                 :          0 :         reenter_guard = 1;
     247                 :            : 
     248                 :          0 :         fprintf(stderr, "[connection suspended, press return to resume]");
     249                 :          0 :         fflush(stderr);
     250                 :          0 :         packet_backup_state();
     251                 :            :         /* TODO Perhaps we should read from tty here */
     252         [ #  # ]:          0 :         while ((c = fgetc(stdin)) != EOF) {
     253         [ #  # ]:          0 :                 if (c == 'Z' - 64) {
     254                 :          0 :                         kill(getpid(), SIGTSTP);
     255                 :          0 :                         continue;
     256                 :            :                 }
     257         [ #  # ]:          0 :                 if (c != '\n' && c != '\r')
     258                 :          0 :                         continue;
     259                 :            : 
     260         [ #  # ]:          0 :                 if (ssh_connect(host, NULL, &hostaddr, options.port,
     261                 :            :                     options.address_family, 1, &timeout_ms,
     262         [ #  # ]:          0 :                     options.tcp_keep_alive, options.use_privileged_port) == 0 &&
     263                 :          0 :                     roaming_resume() == 0) {
     264                 :          0 :                         packet_restore_state();
     265                 :          0 :                         reenter_guard = 0;
     266                 :          0 :                         fprintf(stderr, "[connection resumed]\n");
     267                 :          0 :                         fflush(stderr);
     268                 :          0 :                         return 0;
     269                 :            :                 }
     270                 :            : 
     271                 :          0 :                 fprintf(stderr, "[reconnect failed, press return to retry]");
     272                 :          0 :                 fflush(stderr);
     273                 :            :         }
     274                 :          0 :         fprintf(stderr, "[exiting]\n");
     275                 :          0 :         fflush(stderr);
     276                 :          0 :         exit(0);
     277                 :            : }

Generated by: LCOV version 1.9