Example #1
0
static void pm_dpd_dead_peer_timer(void *context)
{
  SshPm pm = (SshPm) context;
  SshADTHandle h, next;
  SshPmDpdDeadPeerEntry e;
  int npeers = 0;

  for (h = ssh_adt_enumerate_start(pm->dpd_dead_bag);
       h != SSH_ADT_INVALID;
       h = next)
    {
      next = ssh_adt_enumerate_next(pm->dpd_dead_bag, h);

      e = ssh_adt_get(pm->dpd_dead_bag, h);
      if (--e->ttl == 0)
        {
          ssh_adt_delete(pm->dpd_dead_bag, h);
          npeers++;
        }
    }

  if (ssh_adt_num_objects(pm->dpd_dead_bag) > 0)
    {
      /* The bag has still entries left.  Keep the timer running. */
      ssh_register_timeout(&pm->dpd_timer,
                           10L, 0L,
                           pm_dpd_dead_peer_timer, pm);
    }

  SSH_DEBUG(SSH_D_MIDOK, ("DPD; Timer reclaimed %d peers, %d left",
                          npeers,
                          ssh_adt_num_objects(pm->dpd_dead_bag) - npeers));
}
Example #2
0
/* This function provides dual functionality. First,
   if the "flag" value is TRUE in which case we raise
   all the events. Secondly, if the flag value is FALSE
   then we unregister all the events registered in the
   hevent_list */
static void signal_event_test(void *ctx)
{
  BOOL flag = (BOOL) ctx;

  /* if flag is true then raise the events */
  if (flag)
    {
      int i = 0;
      for (; i < sizeof(hevents) / sizeof(HANDLE); i++)
        {
          if (hevents[i])
            SetEvent(hevents[i]);
        }
    }
  else /* Otherwise unregister all the events */
    {
      int j = 0;
      for (; j < sizeof(hevents) / sizeof(HANDLE); j++)
        {
          if (hevents[j])
            {
              ssh_event_loop_unregister_handle(hevents[j]);
            }
        }
      /* Uninit the perf related data */
      ssh_register_timeout(NULL, 0, 0, perf_main_uninit, NULL);
    }
  return;
}
Example #3
0
void ssh_pm_dpd_peer_dead(SshPm pm, const SshIpAddr addr,
                          Boolean down)
{
  SshPmDpdDeadPeerEntry e;
  unsigned char addrstring[SSH_IP_ADDR_STRING_SIZE];

  if (pm->dpd_dead_bag &&
      !ssh_pm_dpd_peer_dead_p(pm, addr))
    {
      if ((e = ssh_malloc(sizeof(*e))) != NULL)
        {
          e->addr = *addr;
          e->down = down;
          e->ttl = pm->dpd_dead_ttl;

          ssh_adt_insert(pm->dpd_dead_bag, e);

          if (ssh_adt_num_objects(pm->dpd_dead_bag) == 1)
            ssh_register_timeout(&pm->dpd_timer,
                                 10L, 0L,
                                 pm_dpd_dead_peer_timer, pm);

          SSH_DEBUG(SSH_D_HIGHSTART,
                    ("DPD; Peer %@: marked as dead", ssh_ipaddr_render, addr));

	  ssh_ipaddr_print(addr, addrstring, sizeof(addrstring));
	  if (pm->dpd_status_callback)
	    (*pm->dpd_status_callback)(pm,
				       addrstring,
				       pm->dpd_status_callback_context);
        }
    }
}
void ssh_stream_fd_destroy(void *context)
{
  SshFdStream sdata = (SshFdStream)context;
  
  /* Mark it as destroyed. */
  assert(!sdata->destroyed);
  sdata->destroyed = TRUE;
  sdata->callback = NULL_FNPTR;

  /* Unregister the descriptors from the event loop. */
  if (sdata->readfd >= 0)
    ssh_io_unregister_fd(sdata->readfd, sdata->keep_nonblocking);
  if (sdata->readfd != sdata->writefd && sdata->writefd >= 0)
    ssh_io_unregister_fd(sdata->writefd, sdata->keep_nonblocking);

  /* Close the file descriptors if appropriate. */
  if (sdata->close_on_destroy)
    {
      if (sdata->readfd >= 0)
        close(sdata->readfd);
      if (sdata->readfd != sdata->writefd && sdata->writefd >= 0)
        close(sdata->writefd);
      sdata->writefd = -1;
      sdata->readfd = -1;
    }

  ssh_register_timeout(&sdata->destroy_timeout, 0L, 0L,
                       ssh_stream_fd_destroy_real, sdata);
}
Example #5
0
void perf_main(int number)
{
  /* We have array of 100 events. */
  int nevent = 100;

  /* Do the performance test related init */
  perf_main_init(number);

  /* Register the timeout test */
  register_timeout_test((void *)ntimes);

  /* Register the event test */
  ssh_register_timeout(NULL, 0, 0, register_event_test,(void *)nevent);

#if 0
  ssh_register_timeout(NUL, 2, 0, register_cancel_timeout_test, 
                        (void*)timeout_list);
#endif
}
Example #6
0
/* Decay timer */
void ssh_decay_counter_timer(void *context)
{
  SshDecayCounter counter = context;
  SshTime now;

  counter->current *= counter->multiplier;
  counter->current /= 1000000;
  counter->last_value = counter->current / counter->divisior;
  SSH_DEBUG(SSH_D_LOWOK, ("Updating decay counter, value = %ld",
                          (unsigned long) counter->last_value));

  counter->next_time += counter->timer;
  now = ssh_time();
  if (counter->next_time < now)
    ssh_register_timeout(&counter->tmout, 0, 0, 
			 ssh_decay_counter_timer, context);
  else
    ssh_register_timeout(&counter->tmout, 
			 (long)(counter->next_time - now), 0,
                         ssh_decay_counter_timer, context);
}
SshTimeout
ssh_register_threaded_timeout(SshTimeout timeout,
                              long seconds, long microseconds,
                              SshTimeoutCallback callback,
                              void *context)
{
  /* In Win32 implementation the ssh_xregister_timeout is already a
     thread safe function. That is why we can call it directly without
     any synchronization in here */
  return ssh_register_timeout(timeout,
                              seconds, microseconds,
                              callback, context);
}
Example #8
0
static void register_cancel_timeout_test(void *ctx)
{
#if 0
  SshTimeout t = NULL;
  
  if (!t_flag && timeout_list)
    t_handle = ssh_adt_enumerate_start(timeout_list);

  if (t_handle != SSH_ADT_INVALID)
    {
      t = ssh_adt_get(timeout_list, t_handle);
      t_handle = ssh_adt_enumerate_next(timeout_list, t_handle);
      if (t)
        ssh_register_timeout(NULL, 0, 0, cancel_timeout, t);
    }
#endif /* 0 */
}
Example #9
0
void ssh_pipe_sigchld_handler(pid_t pid, int status, void *context)
{
    SshPipeStream pipes = (SshPipeStream)context;

    ssh_debug("ssh_pipe_sigchld_handler: pid %d status %d", (int)pid, status);

    /* Sanity checks... */
    if (pipes->status_returned)
        ssh_fatal("ssh_pipe_sigchld_handler: status already returned");

    /* Record the exit status. */
    pipes->status_returned = TRUE;
    pipes->exit_status = status;

    /* Schedule a callback from the bottom of the event loop.  Note that if
       the stream is destroyed, before the event is delivered, we'll cancel
       the timeout before destroying the context. */
    ssh_register_timeout(0L, 0L, ssh_pipe_sigchld_do_callback, (void *)pipes);
}
Example #10
0
static void register_timeout_test(void *ctx)
{
  int i, count;
  count = (int)ctx;

  fprintf(stderr, "\n\tStarting performance test for Event Loop\n");
  fprintf(stderr, "\n");

  for (i = 1; i <= count; i++)
    {
      SshTimeout t = NULL;
      /* Let the default time to fire the callback be 5 seconds */
      t = ssh_register_timeout(NULL, 5, 00000, timeout_callback, (void*)i);
#if 0
      if (t)
        ssh_adt_insert_to(timeout_list, SSH_ADT_END, t);
#endif /* 0 */
    }
}
Example #11
0
/* Allocate new decaying counter, and initialize it to zero. This will start
   timers to process counter. The decaying counter will calculate running
   average from the last `interval' seconds  */
SshDecayCounter ssh_decay_counter_allocate(SshDecayCounterType type,
                                           SshTime interval)
{
  SshDecayCounter counter;

  if ((counter = ssh_calloc(1, sizeof(*counter))) == NULL)
    return NULL;

  if (interval <= 100)
    {
      counter->timer = interval / 10;
      counter->multiplier = ssh_decay_counter_consts[type][0].multiplier;
      counter->divisior = ssh_decay_counter_consts[type][0].divisior *
        counter->timer / 1000;
    }
  else if (interval <= 300)
    {
      counter->timer = interval / 30;
      counter->multiplier = ssh_decay_counter_consts[type][1].multiplier;
      counter->divisior = ssh_decay_counter_consts[type][1].divisior *
        counter->timer / 1000;
    }
  else
    {
      counter->timer = interval / 60;
      counter->multiplier = ssh_decay_counter_consts[type][2].multiplier;
      counter->divisior = ssh_decay_counter_consts[type][2].divisior *
        counter->timer / 1000;
    }
  counter->next_time = ssh_time() + counter->timer;
  SSH_DEBUG(SSH_D_HIGHSTART, ("Allocated counter, interval = %ld "
                              "(timer = %ld), multiplier = %ld, "
                              "divisior = %ld",
                              (unsigned long) interval,
                              (unsigned long) counter->timer,
                              (unsigned long) counter->multiplier,
                              (unsigned long) counter->divisior));
  ssh_register_timeout(&counter->tmout, 
		       (long)counter->timer, 0, ssh_decay_counter_timer,
                        counter);
  return counter;
}
Example #12
0
void
ssh_pm_send_ipsec_delete_notification_requests(SshPm pm, SshPmP1 p1)
{
  SSH_PM_ASSERT_P1(p1);

  if (p1->delete_notification_requests == NULL)
    return;

  /* Send delete notifications from a zero timeout. Take a reference to
     protect the p1 from disappearing. */
  ssh_pm_ike_sa_take_ref(pm->sad_handle, p1->ike_sa);
  if (ssh_register_timeout(NULL, 0, 0,
			   pm_send_ipsec_delete_notification_requests, p1)
      == NULL)
    {
      SSH_DEBUG(SSH_D_FAIL,
		("Failed to send delayed delete notifications for p1 %p", p1));
      ssh_pm_free_ipsec_delete_notification_requests(p1);
      ssh_pm_ike_sa_free_ref(pm->sad_handle, p1->ike_sa);
    }
}
Example #13
0
/* Timeout callback */
static void timeout_callback(void *ctx)
{
  tmo_counter++;

  /* Note the starting time for first timeout_callback */
  if (tmo_counter == 1)
    {
      /* Get the start time using the performance counter */
      qpc->perf_start(&start);

#ifdef DEBUG_LIGHT
      fprintf(stderr, "\tSetting the start time for timeouts: %I64d\n", start);
#endif
    }

  /* All of the timeout_callback are done. Note the end time */
  if (ntimes == tmo_counter)
    {
      /* Get the end time using the performance counter */
      qpc->perf_stop(&stop);

#ifdef DEBUG_LIGHT
      fprintf(stderr, "\tSetting the end time for timeouts: %I64d\n", stop);
#endif
      /* Output the performance details of timeout */
      PERF_OUTPUT_TIMEOUT_RESULT();

      /* Signal the event test to perform */
      ssh_register_timeout(NULL, 1, 0, signal_event_test, (void*)TRUE);

      start = stop = 0;
      return;
    }
  else
    {
      return;
    }
}
Example #14
0
void engine_audit_busy(SshEngine engine)
{
#if SSH_PM_AUDIT_REQUESTS_PER_SECOND == 0
#ifdef SSH_IPSEC_UNIFIED_ADDRESS_SPACE
  SshEngineAuditPollRequest c;

  ssh_kernel_mutex_assert_is_locked(engine->flow_control_table_lock);
  if ((c = ssh_malloc(sizeof(*c))) == NULL)
    return;
  c->engine = engine;

  ssh_engine_record_upcall(engine);
  ssh_register_timeout(c->timeout, 0L, 0L,
		       engine_audit_request_poll_now, c);
#else /* SSH_IPSEC_UNIFIED_ADDRESS_SPACE */
  ssh_engine_send(engine, FALSE, TRUE,
		  SSH_ENCODE_UINT32((SshUInt32) 0),
		  SSH_ENCODE_CHAR((unsigned int)SSH_EPA_AUDIT_POLL_REQUEST),
		  SSH_ENCODE_UINT32(0),
		  SSH_FORMAT_END);
#endif /* SSH_IPSEC_UNIFIED_ADDRESS_SPACE */
#endif /* SSH_PM_AUDIT_REQUESTS_PER_SECOND */
  return;
}
Example #15
0
static void event_callback(void *context)
{
  if (e_count == 0 && !e_flag)
    {
      /* Get the start time using performance counter */
      qpc->perf_start(&start_time); 

#ifdef DEBUG_LIGHT
      fprintf(stderr, "\tSetting the start_time for events: %I64d\n", 
              start_time);
#endif
      e_flag = TRUE;
    }
  e_count++;

  if (100 == e_count)
    {
      repeat_counter++;
      e_count = 0;
      if (repeat_counter > repeat_ntimes_event_test)
        {
          /* Get the end time using performance counter */
          qpc->perf_stop(&end_time);

          /* Output the performance details */
#ifdef DEBUG_LIGHT
          fprintf(stderr, "\tSetting the end_time for events: %I64d\n",
                  end_time);
#endif
          PERF_OUTPUT_EVENT_RESULT();

          /* Signal to unregister all the events registered. 
             signal_event_test() will unregistered the events */
          ssh_register_timeout(NULL, 0, 0, signal_event_test, (void*) FALSE);
          return;
        }
      else
        {
          if (repeat_counter == repeat_ntimes_event_test)
            {
              /* Get the end time using performance counter */
              qpc->perf_stop(&end_time);

#ifdef DEBUG_LIGHT
              fprintf(stderr, "\tSetting the end_time for events: %I64d\n",
                      end_time);
#endif
              PERF_OUTPUT_EVENT_RESULT();

              /* Signal to unregister all the events registered. 
                 signal_event_test() will unregistered the events */
              ssh_register_timeout(NULL, 0, 00000, signal_event_test, 
                                  (void*) FALSE);
              return;
            }
          else
            {
              e_count = 0;
              e_over++;
              /* Restart the event test */
              ssh_register_timeout(NULL, 0, 00000, signal_event_test, 
                                   (void*) TRUE);
              return;
            }
        }
    }

  if ((ntimes-1) == e_count)
    {
      /* Get the end time using performance counter */
      qpc->perf_stop(&end_time);

      /* Output the performance details */
#ifdef DEBUG_LIGHT
      fprintf(stderr, "\tSetting the end_time for events: %I64d\n", end_time);
#endif
      PERF_OUTPUT_EVENT_RESULT();

      /* Unregister the events registered */
      ssh_register_timeout(NULL, 0, 00000, signal_event_test, (void*) FALSE);
      return;
    }
}
Example #16
0
void signer_received_packet(SshPacketType type,
                            const unsigned char *data, size_t len,
                            void *context)
{
    /* Received. */
    unsigned int msg_byte; /* This is unsigned int because
                            SSH_FORMAT_CHAR expects uint; caused a
                            rather nasty bug during development (I
                            used SshUInt8, which wasn't long
                            enough => ssh_decode_array blew the
                            stack).*/
    char *userauth_str, *hostbased_str, *recv_pubkey_alg, *recv_hostname;
    char *recv_username;
    unsigned char *recv_pubkeyblob;
    size_t recv_pubkeyblob_len;
    /* Dug up by us. */
    char *pubkey_alg, *hostname, *username;
    unsigned char *pubkeyblob;
    size_t pubkeyblob_len;
    size_t hostname_len;

    /* Internal stuff*/
    SshSigner signer = (SshSigner) context;
    char hostkeyfile[512];
    char *comment;
    SshPrivateKey privkey;
    size_t sig_len, length_return;
    unsigned char *signature_buffer;
    SshCryptoStatus result;
    SshUser real_user;

    SSH_TRACE(2, ("Packet received."));

    switch(type)
    {
    case SSH_AUTH_HOSTBASED_PACKET:
        /* Check packet out, and if it's ok, sign it and send
           signature to ssh2. */

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(3, ("packet:"), \
                          data, len);
#endif /* HEXDUMPS */

        if (ssh_decode_array(data, len,
                             /* session id */
                             SSH_FORMAT_UINT32_STR, NULL, NULL,
                             /* SSH_MSG_USERAUTH_REQUEST (must be checked)*/
                             SSH_FORMAT_CHAR, &msg_byte,
                             /* user name */
                             SSH_FORMAT_UINT32_STR, NULL, NULL,
                             /* service "ssh-userauth" (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &userauth_str, NULL,
                             /* "hostbased" (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &hostbased_str, NULL,
                             /* public key algorithm for hostkey (must
                                be checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_pubkey_alg, NULL,
                             /* public hostkey and certificates (must be
                                checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_pubkeyblob,
                             &recv_pubkeyblob_len,
                             /* client host name (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_hostname, NULL,
                             /* user name on client host (must be checked) */
                             SSH_FORMAT_UINT32_STR, &recv_username, NULL,
                             SSH_FORMAT_END) != len || len == 0)
        {
            /* There was an error. */
            SSH_TRACE(0, ("Invalid packet."));
            goto error;
        }

        /* Get pubkeyblob, pubkeyblob_len, pubkey_alg, hostname and
           username. */

        /* Dig up hosts publickey. */
        if(signer->config->public_host_key_file[0] != '/')
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR,
                     signer->config->public_host_key_file);
        }
        else
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s",
                     signer->config->public_host_key_file);
        }

        SSH_TRACE(2, ("place to look for public key: %s", hostkeyfile));

        /* This pubkey*-stuff is for the client _host's_ public
           hostkey. */
        /* Getting pubkeyblob, pubkeyblob_len */
        SSH_DEBUG(4, ("Reading pubkey-blob from %s...", hostkeyfile));
        if (ssh2_key_blob_read(signer->effective_user_data, hostkeyfile, NULL,
                               &pubkeyblob,
                               &pubkeyblob_len, NULL)
                != SSH_KEY_MAGIC_PUBLIC)
        {
            SSH_TRACE(1, ("Reading public key failed."));
            goto error;
        }

        SSH_DEBUG(4, ("done."));

        if ((pubkey_alg =
                    ssh_pubkeyblob_type(pubkeyblob, pubkeyblob_len))
                == NULL)
        {
            SSH_TRACE(1, ("Couldn't figure out public key algorithm."));
            goto error;
        }

        /* Getting hostname. */
        hostname = ssh_xmalloc(MAXHOSTNAMELEN + 1);
        ssh_tcp_get_host_name(hostname, MAXHOSTNAMELEN + 1);
        hostname_len = strlen(hostname);
        /* Sanity check */
        SSH_ASSERT(hostname_len + 2 < MAXHOSTNAMELEN);
        /* We want FQDN. */
        hostname[hostname_len] = '.';
        hostname[hostname_len + 1] = '\0';

        /* Getting username. */
        real_user = ssh_user_initialize(NULL, FALSE);
        username = ssh_xstrdup(ssh_user_name(real_user));
        ssh_user_free(real_user, FALSE);

        /* Check all parameters. */
        if (msg_byte != SSH_MSG_USERAUTH_REQUEST)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("msg_byte != SSH_MSG_USERAUTH_REQUEST " \
                          "(msg_byte = %d)", msg_byte));
            goto error;
        }
        if (strcmp(userauth_str, SSH_USERAUTH_SERVICE) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("userauth_str != \"ssh-userauth\" (it was '%s')", \
                          userauth_str));
            goto error;
        }
        if (strcmp(hostbased_str, SSH_AUTH_HOSTBASED) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("hostbased_str != \"hostbased\" (it was '%s')", \
                          hostbased_str));
            goto error;
        }
        /* XXX has to be change when adding support for multiple hostkeys */
        if (strcmp(recv_pubkey_alg, pubkey_alg) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client gave us invalid pubkey-algorithms for our " \
                          "hostkey."));
            goto error;
        }

        if (recv_pubkeyblob_len == pubkeyblob_len)
        {
            if (memcmp(recv_pubkeyblob, pubkeyblob, pubkeyblob_len) != 0)
            {
                SSH_TRACE(1, ("Invalid packet."));
                SSH_DEBUG(1, ("client gave us wrong (or corrupted) " \
                              "public key."));
#ifdef HEXDUMPS
                SSH_DEBUG_HEXDUMP(3, ("client gave us:"), \
                                  recv_pubkeyblob, pubkeyblob_len);
                SSH_DEBUG_HEXDUMP(3, ("our pubkey:"), \
                                  recv_pubkeyblob, pubkeyblob_len);
#endif /* HEXDUMPS */
                goto error;
            }
        }
        else
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client gave us wrong (or corrupted) public key. " \
                          "Lengths differ (received: %d ; ours: %d)", \
                          recv_pubkeyblob_len, pubkeyblob_len));
            goto error;
        }

        if (strcmp(recv_hostname, hostname) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Wethinks the client gave us the wrong hostname. " \
                          "(client's opinion: '%s' ours: '%s'", \
                          recv_hostname, hostname));
            goto error;
        }
        if (strcmp(recv_username, username) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client definitely gave us the wrong user name. " \
                          "(it says: '%s' we know: '%s')", recv_username, \
                          username));
            goto error;
        }

        /* Sign the packet and send it to client. */

        /* If we've gotten this far, the packet is ok, and it can be
           signed. */

        SSH_TRACE(0, ("Received packet ok."));
        if(signer->config->public_host_key_file[0] != '/')
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR,
                     signer->config->host_key_file);
        }
        else
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s",
                     signer->config->host_key_file);
        }

        SSH_TRACE(2, ("place to look for private key: %s", hostkeyfile));

        if ((privkey = ssh_privkey_read(signer->effective_user_data, hostkeyfile, "",
                                        &comment, NULL)) == NULL)
            ssh_fatal("ssh_privkey_read from %s failed.", hostkeyfile);

        /* Check how big a chunk our private key can sign (this is
           purely a sanity check, as both of our signature schemas do
           their own hashing) */
        sig_len = ssh_private_key_max_signature_input_len(privkey);

        SSH_TRACE(2, ("max input length for signing: %d", sig_len));

        if (sig_len == 0)
        {
            SSH_TRACE(0, ("private key not capable of signing! " \
                          "(definitely an error)"));
            goto error;
        }
        else if (sig_len != -1 && sig_len < len)
        {
            SSH_TRACE(0, ("private key can't sign our data. (too much " \
                          "data (data_len %d, max input len for signing " \
                          "%d))", len, sig_len));
            goto error;
        }

        /* Now check how much we much buffer we must allocate for the
           signature. */
        sig_len = ssh_private_key_max_signature_output_len(privkey);

        SSH_TRACE(2, ("max output length for signature: %d", sig_len));

        signature_buffer = ssh_xcalloc(sig_len, sizeof(unsigned char));

        /* Do the actual signing. */

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(5, ("Signing following data"),
                          data + 4, len - 4);
#endif /* HEXDUMPS */

        if ((result = ssh_private_key_sign(privkey,
                                           data,
                                           len,
                                           signature_buffer,
                                           sig_len,
                                           &length_return,
                                           signer->random_state))
                != SSH_CRYPTO_OK)
        {
            SSH_TRACE(0, ("ssh_private_key_sign() returned %d.", result));
            goto error;
        }

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(5, ("Signature"), signature_buffer, length_return);
#endif /* HEXDUMPS */
        /* Send it to client. */
        signer->packet_payload = signature_buffer;
        signer->packet_payload_len = length_return;
        signer->packet_waiting = TRUE;

        if (ssh_packet_wrapper_can_send(signer->wrapper))
            signer_can_send(signer);

        /* XXX free dynamically allocated data. */
        ssh_xfree(username);

        break;
    case SSH_AUTH_HOSTBASED_SIGNATURE:
        /* We shouldn't get this type of packet. This is an error.*/
        SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE. This " \
                      "is an error."));
        goto error;
        break;
    case SSH_AUTH_HOSTBASED_ERROR:
        /* We shouldn't be getting this either. This is an error. */
        SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE_ERROR. " \
                      "This is an error. (This message can be sent by " \
                      "ssh-signer2 only)"));
        goto error;
        break;
    }
    return;

    /* We come here after errors. */
error:
    /* Send error message to ssh2, and wait for ssh2 to send
       EOF. */
    ssh_packet_wrapper_send_encode(signer->wrapper, SSH_AUTH_HOSTBASED_ERROR,
                                   SSH_FORMAT_END);

    /* Init a 5 second timeout. If ssh2 hasn't disconnected at
       that time, close stream.*/
    ssh_register_timeout(5L, 0L, signer_destroy_timeout, signer);

    return;
}
Example #17
0
/* Opens a connection to the specified host, and calls the callback
   when the connection has been established or has failed.  If
   connecting is successful, the callback will be called with error
   set to SSH_TCP_OK and an SshStream object for the connection passed
   in in the stream argument.  Otherwise, error will indicate the
   reason for the connection failing, and the stream will be NULL.

   Note that the callback may be called either during this
   call or some time later.

   Returns SshOperationHandle that can be used to abort the tcp open.

   The `host_name_or_address' argument may be a numeric IP address or a
   host name (domain name), in which case it is looked up from the name
   servers.

   The params structure can either be NULL or memset to zero to get default
   parameters. All data inside the params is copied during this call, so it can
   be freed immediately when this function returns. */
SshOperationHandle ssh_tcp_connect(const unsigned char *host_name_or_address,
                                   const unsigned char *port_or_service,
                                   const SshTcpConnectParams params,
                                   SshTcpCallback callback,
                                   void *context)
{
    ConnectContext c;

    c = ssh_calloc(1, sizeof(*c));
    if (c == NULL)
    {
        SSH_DEBUG(1, ("Failed to allocate TCP connection context."));
        (*callback)(SSH_TCP_FAILURE, NULL, context);
        return NULL;
    }

    if (params && params->local_address)
    {
        c->local_address = ssh_strdup(params->local_address);
        if (c->local_address == NULL)
        {
error_local:
            (*callback)(SSH_TCP_FAILURE, NULL, context);
            tcp_connect_destroy_ctx(c);
            return NULL;
        }

        if (params->local_port_or_service)
        {
            c->local_port
                = ssh_inet_get_port_by_service(params->local_port_or_service,
                                               ssh_custr("tcp"));
            if (c->local_port == 0)
                goto error_local;
        }
        c->local_reusable = params->local_reusable;
    }

    c->host_name = ssh_strdup(host_name_or_address);
    c->host_port = ssh_inet_get_port_by_service(port_or_service,
                   ssh_custr("tcp"));
    c->host_addresses = NULL;
    c->next_address = NULL;

    if (c->host_name == NULL || c->host_port == 0)
    {
        (*callback)(SSH_TCP_FAILURE, NULL, context);
        tcp_connect_destroy_ctx(c);
        return NULL;
    }

    if (params && (params->protocol_mask != 0))
        c->protocol_mask = params->protocol_mask;
    else
        c->protocol_mask = (~0);

    c->user_callback = callback;
    c->user_context = context;
    if (params && params->connection_timeout != 0)
    {
        ssh_register_timeout(&c->timeout,
                             params->connection_timeout, 0,
                             tcp_connect_time_out, c);
    }

    c->connection_attempts = 1;
    if (params && params->connection_attempts != 0)
        c->connection_attempts = params->connection_attempts;

    c->attempts_done = 0;

    c->stream = NULL;

    /* Initialize socks-related data. */
    if (params &&
            params->socks_server_url != NULL &&
            ssh_usstrcmp(params->socks_server_url, "") != 0)
    {
        unsigned char *scheme, *port;

        if (ssh_url_parse_and_decode_relaxed(params->socks_server_url, &scheme,
                                             &(c->socks_host), &port,
                                             &(c->user_name), NULL,
                                             &(c->socks_exceptions)))
        {
            if (scheme != NULL && ssh_usstrcmp(scheme, "socks") != 0)
                ssh_warning("Socks server scheme not socks");
            if (scheme != NULL)
                ssh_free(scheme);

            if (c->socks_host != NULL)
            {
                if ((c->socks_buf = ssh_buffer_allocate()) == NULL)
                {
                    (*callback)(SSH_TCP_FAILURE, NULL, context);
                    tcp_connect_destroy_ctx(c);
                    return NULL;
                }
                c->socks_addresses = NULL;
                if (port == NULL || ssh_usstrcmp(port, "") == 0)
                    c->socks_port = 1080; /* The standard socks port. */
                else
                    c->socks_port = ssh_inet_get_port_by_service(port,
                                    ssh_custr("tcp"));
            }
            if (port != NULL)
                ssh_free(port);
        }
        else
        {
            ssh_warning("Socks server URL is malformed.");
        }
    }
    else
        c->socks_host = NULL;

    if (params)
        c->socks_type = params->socks_type;

    c->upper_handle = NULL;
    c->handle = NULL;

    c->fsm = ssh_fsm_create(c);
    if (c->fsm == NULL)
    {
        SSH_DEBUG(2, ("Creating FSM failed."));
        (*callback)(SSH_TCP_FAILURE, NULL, context);
        tcp_connect_destroy_ctx(c);
        return NULL;
    }
    c->thread = ssh_fsm_thread_create(c->fsm, tcp_connect_start,
                                      NULL_FNPTR, NULL_FNPTR, NULL);
    if (c->thread == NULL)
    {
        SSH_DEBUG(2, ("Creating thread failed."));
        (*callback)(SSH_TCP_FAILURE, NULL, context);
        ssh_fsm_destroy(c->fsm);
        tcp_connect_destroy_ctx(c);
        return NULL;
    }
    c->upper_handle = ssh_operation_register(ssh_tcp_connect_aborted, c);
    return c->upper_handle;
}