Esempio n. 1
0
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
  char buf[64];
  int i;
  
  for (i = 0; i < 256; i++)	/* max 256 pty's possible */
    {
      snprintf(buf, sizeof(buf), "/dev/ptyp%d", i);
      *ptyfd = open(buf, O_RDWR|O_NOCTTY);
      if (*ptyfd < 0)
	{
          if (errno == ENODEV)	    /* all used up */
	    {
	      ssh_warning("pty_allocate: all allocated ptys (%d) used", i);
	      return FALSE;
	    }
	  continue;
	}
      
      snprintf(namebuf, SSH_PTY_NAME_SIZE, "/dev/ttyp%d", i);
      
      /* Open the slave side. */

      *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
      if (*ttyfd < 0)
	{
	  ssh_warning("%.100s: %.100s", namebuf, strerror(errno));
	  close(*ptyfd);
	  return FALSE;
	}
      return TRUE;
    }
  ssh_warning("Failed to allocate pty.");
  return FALSE;
}
Esempio n. 2
0
Boolean ssh_channel_start_local_tcp_forward(SshCommon common,
                                            const char *address_to_bind,
                                            const char *port,
                                            const char *connect_to_host,
                                            const char *connect_to_port)
{
  SshLocalTcpForward fwd;
  SshChannelTypeTcpDirect ct;
  long portnumber;
  SshUser user;
  
  SSH_DEBUG(5, ("requesting local forwarding for port %s to %s:%s",
                port, connect_to_host, connect_to_port));

  portnumber = atol(port);
  user = ssh_user_initialize(NULL, FALSE);
    /* If user is not logged in as a privileged user, don't allow
     forwarding of privileged ports. */
  if (portnumber < 1024)
    {
      if (ssh_user_uid(user))
        {
          ssh_warning("Tried to forward " \
                      "privileged port %d as an ordinary user.",
                      portnumber);
          return FALSE;
        }
    }

  if (portnumber >= 65536)
    {
      ssh_warning("Tried to forward " \
                  "port above 65535 (%d).",
                  portnumber);
      return FALSE;
    }
  
  ct = ssh_channel_dtcp_ct(common);

  fwd = ssh_xcalloc(1, sizeof(*fwd));
  fwd->common = common;
  fwd->listener = ssh_tcp_make_listener(address_to_bind, port,
                                        ssh_channel_dtcp_incoming_connection,
                                        (void *)fwd);
  if (!fwd->listener)
    {
      SSH_DEBUG(5, ("creating listener failed"));
      ssh_xfree(fwd);
      return FALSE;
    }

  fwd->port = ssh_xstrdup(port);
  fwd->connect_to_host = ssh_xstrdup(connect_to_host);
  fwd->connect_to_port = ssh_xstrdup(connect_to_port);

  fwd->next = ct->local_forwards;
  ct->local_forwards = fwd;

  return TRUE;
}
Esempio n. 3
0
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
  const char *name;

  *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
  if (*ptyfd < 0)
    {
      ssh_warning("Could not open /dev/ptc: %.100s", strerror(errno));
      return FALSE;
    }
  name = ttyname(*ptyfd);
  if (!name)
    {
      ssh_warning("Open of /dev/ptc returns device for which ttyname fails.");
      return FALSE;
    }
  strcpy(namebuf, name);
  *ttyfd = open(name, O_RDWR|O_NOCTTY);
  if (*ttyfd < 0)
    {
      ssh_warning("Could not open pty slave side %.100s: %.100s", 
	    name, strerror(errno));
      close(*ptyfd);
      return FALSE;
    }
  return TRUE;
}
Esempio n. 4
0
SshLocalListener ssh_local_make_listener(const char *path,
        SshLocalCallback callback,
        void *context)
{
    int sock;
    struct sockaddr_un sunaddr;
    SshLocalListener listener;

    /* Create a socket for the listener. */
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock < 0)
    {
        ssh_warning("Can not create local domain socket: %.200s",
                    strerror(errno));
        return NULL;

    }

    /* Initialize a unix-domain address structure. */
    memset(&sunaddr, 0, sizeof(sunaddr));
    sunaddr.sun_family = AF_UNIX;
    strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));

    /* Bind the socket to the address.  This will create the socket in the file
       system, and will fail if the socket already exists. */
    if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
    {
        close(sock);
        ssh_warning("Can not bind local address %.200s: %.200s",
                    path, strerror(errno));
        return NULL;
    }

    /* Start listening for connections to the socket. */
    if (listen(sock, 5) < 0)
    {
        close(sock);
        ssh_warning("Can not listen to local address %.200s: %.200s",
                    path, strerror(errno));
        return NULL;
    }

    /* Allocate and initialize the listener structure. */
    listener = ssh_xmalloc(sizeof(*listener));
    listener->sock = sock;
    listener->path = ssh_xstrdup(path);
    listener->callback = callback;
    listener->context = context;

    /* ssh_local_listen_callback will call the user supplied callback
       when after new connection is accepted. It also creates stream
       object for the new connection and calls callback. */
    ssh_io_register_fd(sock, ssh_local_listen_callback, (void *)listener);
    ssh_io_set_fd_request(sock, SSH_IO_READ);

    return listener;
}
Esempio n. 5
0
void ssh_channel_ssh1_agent_open(const char *type, int channel_id,
                                const unsigned char *data, size_t len,
                                SshConnOpenCompletionProc completion,
                                void *completion_context, void *context)
{
  SshCommon common = (SshCommon)context;
  SshChannelTypeSsh1Agent ct;
  SshAgentConnection a;

  SSH_DEBUG(5, ("agent channel open request received"));

  ct = ssh_channel_ssh1_agent_ct(common);
  
  if (len != 0)
    {
      SSH_DEBUG(0, ("Bad agent channel open request"));
      (*completion)(SSH_OPEN_CONNECT_FAILED,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  /* Do not allow agent opens at the server. */
  if (!common->client)
    {
      ssh_warning("Refused attempted agent connection to server.");
      (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  /* Do not allow agent opens if we didn't request agent forwarding. */
  if (!ct->agent_requested)
    {
      ssh_warning("Refused attempted agent connection when forwarding not requested.");
      (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }
  
  /* Create a context argument for connecting. */
  a = ssh_xcalloc(1, sizeof(*a));
  a->common = common;
  a->channel_id = channel_id;
  a->completion = completion;
  a->context = completion_context;

  /* Try to connect to the real agent. */
  ssh_agenti_connect(ssh_channel_open_ssh1_agent_connected, TRUE, (void *)a);
}
Esempio n. 6
0
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
  char buf[64];
  int i;
#ifdef __FreeBSD__
  const char *ptymajors = "pqrsPQRS";
  const char *ptyminors = "0123456789abcdefghijklmnopqrstuv";
#else
  const char *ptymajors = 
    "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const char *ptyminors = "0123456789abcdef";
#endif
  int num_minors = strlen(ptyminors);
  int num_ptys = strlen(ptymajors) * num_minors;

  for (i = 0; i < num_ptys; i++)
    {
      snprintf(buf, sizeof(buf), "/dev/pty%c%c", ptymajors[i / num_minors], 
	      ptyminors[i % num_minors]);
      *ptyfd = open(buf, O_RDWR|O_NOCTTY);
      if (*ptyfd < 0)
	continue;
      snprintf(namebuf, SSH_PTY_NAME_SIZE,
	       "/dev/tty%c%c", ptymajors[i / num_minors], 
	       ptyminors[i % num_minors]);

#ifdef HAVE_REVOKE
      if (revoke(namebuf) == -1)
 	ssh_warning("pty_allocate: revoke failed for %.100s", namebuf);
#endif

      /* Open the slave side. */
      *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
      if (*ttyfd < 0)
	{
	  ssh_warning("%.100s: %.100s", namebuf, strerror(errno));
	  close(*ptyfd);
	  /* Try with another pty. */
	  continue;
	}

#if defined(ultrix) || defined(NeXT)
      (void) signal(SIGTTOU, SIG_IGN);  /* corey via nancy */
#endif /* ultrix or NeXT */
      
      return TRUE;
    }
  ssh_warning("Failed to allocate pty.");
  return FALSE;
}
/* Allocate externalkey. aIn this function we also add a default
   provider and enable it. */
static void test_ek_add(void)
{
  SshExternalKey externalkey;

  /* Allocate the externalkey. */
  externalkey = ssh_ek_allocate();

  /* Store the externalkey object to the global variable. 
     Using global variables is dummy, but in this example program, 
     it may be ok. */
  ssh_global_externalkey = externalkey;
  
  /* Register notify callback. */
  ssh_ek_register_notify(externalkey, ssh_externalkey_notify_cb, NULL);

  /* Register authentication callback. */
  ssh_ek_register_authentication_callback(externalkey,
                                          ssh_externalkey_authentication_cb,
                                          NULL);


  /* Add the default provider to externalkey. 
     We decide here what are the providers we want to use. For this
     example, we use the provider in provider_type variable. */
  if (ssh_ek_add_provider(externalkey, provider_type,
                          initialization_string, NULL, 0, NULL) != SSH_EK_OK)
    {
      ssh_warning("Could not add '%s' provider with '%s' in initialization "
                  "string.", provider_type, initialization_string);
      exit(1);
    }
    
  /* And we are done initializing. Externalkey system will call the notify 
     callback to notify us, provider has keys available. */
}
void ssh_engine_from_ipm_run(SshEngine engine,
                             const unsigned char *data, size_t len)
{
    SshUInt32 test_number, flags;

    if (ssh_decode_array(data, len,
                         SSH_FORMAT_UINT32, &test_number,
                         SSH_FORMAT_UINT32, &flags,
                         SSH_FORMAT_END) != len)
    {
        SSH_DEBUG_HEXDUMP(0, ("bad run packet"), data, len);
        return;
    }

    switch (test_number)
    {
    case SSH_INTERCEPTOR_TEST_BASIC:
        ssh_engine_test_basic(engine, flags);
        break;

    default:
        ssh_warning("unknown test %ld", (long)test_number);
        ssh_engine_test_fail(engine, "unknown test %ld", (long)test_number);
        break;
    }
}
Esempio n. 9
0
void ssh_channel_ftcp_open_connected(SshIpError error,
                                     SshStream stream,
                                     void *context)
{
  SshChannelTcpFwdConnect c = (SshChannelTcpFwdConnect)context;

  if (error != SSH_IP_OK)
    {
      ssh_warning("Connecting to %s:%s failed (remote forward, port %s)",
                  c->fwd->connect_to_host, c->fwd->connect_to_port,
                  c->fwd->port);
      (*c->completion)(SSH_OPEN_CONNECT_FAILED,
                       NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                       c->completion_context);
      memset(c, 'F', sizeof(*c));
      ssh_xfree(c);
      return;
    }

  /* Record that we now have a new channel. */
  ssh_common_new_channel(c->fwd->common);
  
  /* Call the completion procedure to indicate that we are done. */
  (*c->completion)(SSH_OPEN_OK,
                   stream, TRUE, TRUE, SSH_TCPIP_WINDOW, NULL, 0,
                   NULL, ssh_channel_tcp_connection_destroy,
                   (void *)c->fwd->common, c->completion_context);
  memset(c, 'F', sizeof(*c));
  ssh_xfree(c);
}
Esempio n. 10
0
Boolean ssh_channel_tcp_forward_cancel(const char *type,
                                       const unsigned char *data,
                                       size_t len,
                                       void *context)
{
  SshCommon common = (SshCommon)context;
  char *address_to_bind;
  SshUInt32 port;
  char port_string[20];
  SshRemoteTcpForward fwd, *fwdp;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("remote TCP/IP cancel request received"));

  ct = ssh_channel_ftcp_ct(common);
  
  /* Don't allow a server to send remote forwarding requests to the client. */
  if (common->client)
    {
      ssh_warning("Remote TCP/IP forwarding cancel from server denied.");
      return FALSE;
    }
  
  /* Parse the request. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG(0, ("bad data"));
      return FALSE;
    }

  /* Convert port number to a string. */
  snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port);

  for (fwdp = &ct->remote_forwards; *fwdp; fwdp = &fwd->next)
    {
      fwd = *fwdp;
      if (strcmp(port_string, fwd->port) == 0 &&
          strcmp(address_to_bind, fwd->address_to_bind) == 0)
        {
          ssh_tcp_destroy_listener(fwd->listener);
          ssh_xfree(fwd->address_to_bind);
          ssh_xfree(fwd->port);
          *fwdp = fwd->next;
          ssh_xfree(fwd);
          ssh_xfree(address_to_bind);
          return TRUE;
        }
    }

  SSH_DEBUG(1, ("port %s address_to_bind %s not found",
                port_string, address_to_bind));
  ssh_xfree(address_to_bind);
  return FALSE;
}
Esempio n. 11
0
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
  char *slave;

  slave = _getpty(ptyfd, O_RDWR, 0622, 0);
  if (slave == NULL)
    {
      ssh_warning("_getpty: %.100s", strerror(errno));
      return FALSE;
    }
  strcpy(namebuf, slave);
  /* Open the slave side. */
  *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
  if (*ttyfd < 0)
    {
      ssh_warning("%.200s: %.100s", namebuf, strerror(errno));
      close(*ptyfd);
      return FALSE;
    }
  return TRUE;
}  
Esempio n. 12
0
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
  int i;

  i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);

  if (i < 0) 
    {
      ssh_warning("openpty: %.100s", strerror(errno));
      return FALSE;
    }
  
  return TRUE;
}  
Esempio n. 13
0
/* Write pem/hexl/binary file from the disk. If the write fails retuns FALSE.
   If the file name starts with :p: then assume file is pem encoded, if it
   starts with :h: then it is assumed to be hexl format, and if it starts with
   :b: then it is assumed to be binary. If no :[bph]: is given then file is
   assumed to be binary. If any other letter is given between colons then
   warning message is printed and operation fails. If the file name is NULL or
   "-" then read from the stdout (":p:-" == stdout in pem encoded format). */
Boolean ssh_write_gen_file(const char *file_name,
                           const char *begin,
                           const char *end,
                           const unsigned char *buf,
                           size_t buf_len)
{
  if (strlen(file_name) < 3 || file_name[0] != ':' || file_name[2] != ':')
    return ssh_write_file(file_name, buf, buf_len);
  if (file_name[1] == 'b')
    return ssh_write_file(file_name + 3, buf, buf_len);
  if (file_name[1] == 'p')
    return ssh_write_file_base64(file_name + 3, begin, end, buf, buf_len);
  if (file_name[1] == 'h')
    return ssh_write_file_hexl(file_name + 3, buf, buf_len);
  ssh_warning("Unknown file format given to ssh_read_gen_file");
  return FALSE;
}
Esempio n. 14
0
/* Read pem/hexl/binary file from the disk. Return mallocated buffer
   and the size of the buffer. If the reading of file failes return
   FALSE. If the file name starts with :p: then assume file is pem
   encoded, if it starts with :h: then it is assumed to be hexl
   format, and if it starts with :b: then it is assumed to be
   binary. If no :[bph]: is given then file is assumed to be
   binary. If any other letter is given between colons then warning
   message is printed and operation fails. If the file name is NULL or
   "-" then read from the stdin (":p:-" == stdin in pem encoded
   format). The size_limit is in bytes. If zero is used, the read file
   will try to read the whole file.

   If the file size exceeds the size_limit (given in bytes), FALSE
   is returned. */
Boolean ssh_read_gen_file_with_limit(const char *file_name,
                                     SshUInt32 size_limit,
                                     unsigned char **buf,
                                     size_t *buf_len)
{
  if (strlen(file_name) < 3 || file_name[0] != ':' || file_name[2] != ':')
    return ssh_read_file_with_limit(file_name, size_limit, buf, buf_len);
  if (file_name[1] == 'b')
    return ssh_read_file_with_limit(file_name + 3, size_limit, buf, buf_len);
  if (file_name[1] == 'p')
    return ssh_read_file_base64_with_limit(file_name + 3, size_limit,
                                           buf, buf_len);
  if (file_name[1] == 'h')
    return ssh_read_file_hexl_with_limit(file_name + 3, size_limit,
                                         buf, buf_len);
  ssh_warning("Unknown file format given to ssh_read_gen_file");
  return FALSE;
}
Esempio n. 15
0
void ssh_engine_packet_from_ipm(SshEngine engine,
                                SshUInt32 type,
                                const unsigned char *data, size_t len)
{
    switch (type)
    {
    case SSH_ENGINE_IPM_TESTER_RUN:
        ssh_engine_from_ipm_run(engine, data, len);
        break;

    case SSH_ENGINE_IPM_TESTER_SET_DEBUG:
        ssh_engine_from_ipm_set_debug(engine, data, len);
        break;

    default:
        ssh_warning("ssh_engine_packet_from_ipm: unexpected packet %d in "
                    "kernel; probably wrong policy manager", len);
        break;
    }
}
Esempio n. 16
0
/* 
 * Calculate difference between time values beg and end and store result
 * to ret.
 */
void ssh_time_measure_difference(SshTimeVal ret,
                                 SshTimeVal beg, 
                                 SshTimeVal end)
{
  SSH_ASSERT(beg != NULL);
  SSH_ASSERT(end != NULL);
  if (SSH_TIME_MEASURE_LT(end->seconds, end->nanoseconds,
                          beg->seconds, beg->nanoseconds))
    {
      SSH_DEBUG(5, ("Negative time difference: beg(%lu %lu) > end(%lu %lu).",
                    (unsigned long)beg->seconds,
                    (unsigned long)beg->nanoseconds,
                    (unsigned long)end->seconds, 
                    (unsigned long)end->nanoseconds));
      if ((end->seconds + 20) < beg->seconds)
        ssh_warning("ssh_time_measure_difference: Negative difference.");
      if (ret != NULL)
        {
          ret->seconds = 0;
          ret->nanoseconds = 0;
        }
      return;
    }
  if (ret == NULL)
    return;
  
  if (beg->nanoseconds <= end->nanoseconds)
    {
      ret->seconds = end->seconds - beg->seconds;
      ret->nanoseconds = end->nanoseconds - beg->nanoseconds;
    }
  else
    {
      ret->seconds = end->seconds - beg->seconds - 1;
      ret->nanoseconds = (((SshUInt32)1000000000) + 
                          (end->nanoseconds - beg->nanoseconds));
    }
  return;
}
Esempio n. 17
0
int main(int argc, char **argv)
{
  int c;
  SshCryptoStatus cs;
  SshCipher cipher;
  Boolean all_ciphers = FALSE, speed_test = FALSE, quiet = FALSE;
  unsigned char *iv = NULL, *key = NULL;
  size_t iv_len = 0, key_len = 0;
  char *cipher_name = NULL, *cipher_names, *hlp, *passphrase = NULL;
  Boolean encrypt_mode = TRUE;
  char *input_file = NULL, *output_file = NULL;
  FILE *fin, *fout;
  Boolean r = TRUE;

  if (strchr(argv[0], '/'))
    av0 = strrchr(argv[0], '/') + 1;
  else
    av0 = argv[0];

  if (strcasecmp(av0, "ssh-encrypt") == 0)
    encrypt_mode = TRUE;
  else if (strcasecmp(av0, "ssh-decrypt") == 0)
    encrypt_mode = FALSE;

  if (ssh_crypto_library_initialize() != SSH_CRYPTO_OK)
    {
      fprintf(stderr, "Can't initialize the cryptographic provider.\n");
      exit(1);
    }
  while ((c = ssh_getopt(argc, argv, "thd:ac:i:k:EDp:", NULL)) != -1)
    {
      switch (c)
        {
        case 'd':
          ssh_debug_set_level_string(ssh_optarg);
          break;
        case 't':
          speed_test = TRUE;
          break;
        case 'a':
          all_ciphers = TRUE;
          break;
        case 'c':
          cipher_name = ssh_xstrdup(ssh_optarg);
          break;
        case 'q':
          quiet = TRUE;
          break;
        case 'i':
          if (iv)
            {
              fprintf(stderr,
                      "%s: No multiple initialization vectors allowed.\n",
                      av0);
              usage();
              exit(-1);
            }
          if (! hex_string_to_data(ssh_optarg, &iv, &iv_len))
            {
              fprintf(stderr, "%s: Bad IV string.\n", av0); 
              exit(-1);
            }
          break;
        case 'k':
          if (key)
            {
              fprintf(stderr, "%s: No multiple keys allowed.\n", av0);
              usage();
              exit(-1);
            }
          if (! hex_string_to_data(ssh_optarg, &key, &key_len))
            {
              fprintf(stderr, "%s: Bad KEY string.\n", av0); 
              exit(-1);
            }
          break;
        case 'p':
          if (passphrase)
            {
              fprintf(stderr, "%s: No multiple passphrases allowed.\n", av0);
              usage();
              exit(-1);
            }
          passphrase = ssh_optarg;
          break;
        case 'E':
          encrypt_mode = TRUE;
          break;
        case 'D':
          encrypt_mode = FALSE;
          break;
        case 'h':
          help_info();
          usage();
          exit(0);
          /*NOTREACHED*/
        default:
          usage();
          exit(-1);
          /*NOTREACHED*/
        }
    }
  argc -= ssh_optind;
  argv += ssh_optind;
  if (speed_test && (argc > 0))
    {
      fprintf(stderr, "%s: Extra parameters.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if (argc > 2)
    {
      fprintf(stderr, "%s: Extra parameters.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if (argc > 1)
    output_file = ssh_xstrdup(argv[1]);
  if (argc > 0)
    input_file = ssh_xstrdup(argv[0]);
  if ((cipher_name != NULL) && all_ciphers)
    {
      fprintf(stderr, "%s: -c and -a can't be used together.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if (all_ciphers && !speed_test)
    {
      fprintf(stderr, "%s: -a can only be used with -t.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if ((cipher_name != NULL) && strchr(cipher_name, ',') && !speed_test)
    {
      fprintf(stderr, "%s: Multiple ciphers only be used with -t.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if (cipher_name == NULL)
    {
      if (speed_test)
        {
          all_ciphers = TRUE; /* Assume `all' if test mode with no ciphers. */
        }
      else
        {
          fprintf(stderr, "Missing -c flag.\n");
          usage();
          exit(-1);
          /*NOTREACHED*/
        }
    }
  if (passphrase && key)
    {
      fprintf(stderr, "%s: Can't use both passphrase and hex key.\n", av0);
      usage();
      exit(-1);
      /*NOTREACHED*/
    }
  if (!key && !passphrase && !speed_test)
    {
      ssh_warning("%s: No key!  Empty passphrase assumed.", av0);
      passphrase = "";
      /*NOTREACHED*/
    }
  if (speed_test)
    {
      fprintf(stderr, "Performing speed tests\n");
      if (all_ciphers)
        {
          cipher_names = ssh_cipher_get_supported();
        }
      else
        {
          /* Steal allocated cipher_name */
          cipher_names = cipher_name;
          cipher_name = NULL;
        }
      hlp = cipher_names;
      while ((cipher_name = ssh_name_list_get_name(hlp)) != NULL)
        {
          hlp += strlen(cipher_name);
          if (*hlp == ',')
            hlp++;
          cipher_speed_test(cipher_name,
                            passphrase,
                            key, key_len,
                            iv, iv_len,
                            encrypt_mode);
          ssh_xfree(cipher_name);

          if (strlen(hlp) == 0)
            break;
        }
      ssh_xfree(cipher_names);
    }
  else
    {
      if (passphrase)
        cs = ssh_cipher_allocate_with_passphrase(cipher_name,
                                                 passphrase,
                                                 encrypt_mode,
                                                 &cipher);
      else
        cs = ssh_cipher_allocate(cipher_name,
                                 key,
                                 key_len,
                                 encrypt_mode,
                                 &cipher);
      if (cs != SSH_CRYPTO_OK)
        {
          switch (cs)
            {
            case SSH_CRYPTO_UNSUPPORTED:
              fprintf(stderr, "%s: Unsupported cipher \"%s\".\n", av0, 
                      cipher_name);
              usage();
              exit(-1);
            case SSH_CRYPTO_KEY_TOO_SHORT:
              fprintf(stderr, "%s: Key too short for \"%s\".\n", av0, 
                      cipher_name);
              usage();
              exit(-1);
            default:
              fprintf(stderr, "%s: Cipher allocate failed.\n", av0);
              exit(-1);
            }
          /*NOTREACHED*/
        }
      if (iv != NULL)
        {
          if (ssh_cipher_get_iv_length(ssh_cipher_name(cipher)) == iv_len)
            ssh_cipher_set_iv(cipher, iv);
          else
            {
              fprintf(stderr, "%s: Weird IV length.\n", av0);
              exit(-1);
            }
        }
      if (input_file != NULL)
        {
          fin = fopen(input_file, "r");
          if (fin == NULL)
            {
              fprintf(stderr, "%s: Cannot open input file \"%s\".\n", 
                      av0, input_file);
              exit(-1);
            }
        }
      else
        {
          fin = stdin;
        }
      if (output_file != NULL)
        {
          struct stat st;
          if (stat(output_file, &st) >= 0)
            {
              fprintf(stderr, "%s: Output file \"%s\" exists.\n", av0, 
                      output_file);
              exit(-1);
            }
          fout = fopen(output_file, "w");
          if (fout == NULL)
            {    
              fprintf(stderr, "%s: Cannot open output file \"%s\".\n", 
                      av0, output_file);
              exit(-1);
            }
        }
      else
        {
          fout = stdout;
        }
      if (encrypt_mode)
        r = cipher_encrypt(cipher, fin, fout);
      else
        r = cipher_decrypt(cipher, fin, fout);
      if (input_file)
        fclose(fin);
      if (output_file)
        {
          fclose(fout);
          if (! r)
            (void)unlink(output_file);
        }
      ssh_cipher_free(cipher);
      ssh_xfree(cipher_name);
    }

  ssh_xfree(input_file);
  ssh_xfree(output_file);
  ssh_xfree(key);
  ssh_xfree(iv);

  ssh_crypto_library_uninitialize();
  ssh_util_uninit();
  return((r == TRUE) ? 0 : -1);
}
Esempio n. 18
0
Boolean ssh_channel_remote_tcp_forward_request(const char *type,
                                               const unsigned char *data,
                                               size_t len,
                                               void *context)
{
  SshCommon common = (SshCommon)context;
  char *address_to_bind;
  SshUInt32 port;
  char port_string[20];
  SshRemoteTcpForward fwd;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("remote TCP/IP forwarding request received"));
  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Remote TCP/IP forwarding request received from host \"%s\", "\
                "by authenticated user \"%s\".",
                common->remote_host,
                ssh_user_name(common->user_data));
  
  ct = ssh_channel_ftcp_ct(common);
  
  /* Don't allow a server to send remote forwarding requests to the client. */
  if (common->client)
    {
      ssh_warning("Remote TCP/IP forwarding request from server denied.");
      return FALSE;
    }
  
  /* Parse the request. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG(0, ("bad data"));
      return FALSE;
    }

  /* Convert port number to a string. */
  snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port);

  /* If user is not logged in as a privileged user, don't allow
     forwarding of privileged ports. */
  if (port < 1024)
    {
      if (ssh_user_uid(common->user_data))
        {
          SSH_TRACE(2, ("User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port));
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_WARNING,
                        "User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port);
          return FALSE;
        }
      else
        {
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_NOTICE,
                        "Privileged user \"%s\" forwarding a privileged port.",
                        ssh_user_name(common->user_data));
        }
    }

  if (port >= 65536)
    {
      SSH_TRACE(2, ("User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port));
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_WARNING,
                    "User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port);
      return FALSE;
    }
  
      
  /* Create a socket listener. */
  fwd = ssh_xcalloc(1, sizeof(*fwd));
  fwd->listener = ssh_tcp_make_listener(address_to_bind, port_string,
                                        ssh_channel_ftcp_incoming_connection,
                                        (void *)fwd);
  if (fwd->listener == NULL)
    {
      ssh_debug("Creating remote listener for %s:%s failed.",
                address_to_bind, port_string);
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_NOTICE,
                    "Creating remote listener for %s:%s failed.",
                    address_to_bind, port_string);
      
      ssh_xfree(address_to_bind);
      ssh_xfree(fwd);
      return FALSE;
    }

  /* Fill the remaining fields. */
  fwd->common = common;
  fwd->address_to_bind = address_to_bind;
  fwd->port = ssh_xstrdup(port_string);
  fwd->connect_to_host = NULL;
  fwd->connect_to_port = NULL;

  /* Add to list of forwardings. */
  fwd->next = ct->remote_forwards;
  ct->remote_forwards = fwd;

  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Port %ld set up for remote forwarding.",
                (unsigned long) port);
  
  return TRUE;
}  
Esempio n. 19
0
/* Sends the updated interface information to the engine. This is called
   at the initialization of the interceptor and whenever the status of any
   interface changes. 

   This function grabs 'if_table_lock' (for reading) and 'interceptor_lock'. 
*/
static void
ssh_interceptor_send_interfaces(SshInterceptor interceptor)
{
  SshInterceptorInternalInterface iface;
  SshInterceptorInterface *ifarray;
  SshInterceptorInterfacesCB interfaces_callback;
  struct net_device *dev;
  struct in_device *inet_dev = NULL;
  struct in_ifaddr *addr;
  int num, n, count, i, hashvalue;
#ifdef SSH_LINUX_INTERCEPTOR_IPV6
  struct inet6_dev *inet6_dev = NULL;
  struct inet6_ifaddr *addr6;
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */

  /* Grab 'if_table_lock' for reading the interface table. */
  read_lock(&interceptor->nf->if_table_lock);

  num = interceptor->nf->if_table_size;
  if (!num)
    {
      read_unlock(&interceptor->nf->if_table_lock);
      SSH_DEBUG(4, ("No interfaces to report."));
      return;
    }

  /* Allocate temporary memory for the table that is 
     passed to the engine. This is mallocated, since
     we want to minimise stack usage. */
  ifarray = ssh_malloc(sizeof(*ifarray) * num);
  if (ifarray == NULL)
    {
      read_unlock(&interceptor->nf->if_table_lock);
      return;
    }
  memset(ifarray, 0, sizeof(*ifarray) * num);

  /* Iterate over the slots of the iface hashtable. */
  n = 0;
  for (hashvalue = 0; hashvalue < SSH_LINUX_IFACE_HASH_SIZE; hashvalue++)
    {

      /* Iterate over the chain of iface entries in a hashtable slot. */
      for (iface = interceptor->nf->if_hash[hashvalue]; 
	   iface != NULL; 
	   iface = iface->next)
	{	  
	  /* Ignore devices that are not up. */
	  dev = iface->dev;
	  if (dev == NULL || !(dev->flags & IFF_UP))
	    continue;
	  
	  /* Disable net_device features that quicksec does not support */
	  if (dev->features & NETIF_F_TSO)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_TSO",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_TSO;
	    }

#ifdef LINUX_HAS_NETIF_F_GSO
	  /* Disable net_device features that quicksec does not support */
	  if (dev->features & NETIF_F_GSO)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_GSO",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_GSO;
	    }
#endif /* LINUX_HAS_NETIF_F_GSO */

#ifdef LINUX_HAS_NETIF_F_TSO6
	  /* Disable net_device features that quicksec does not support */
	  if (dev->features & NETIF_F_TSO6)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_TSO6",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_TSO6;
	    }
#endif /* LINUX_HAS_NETIF_F_TSO6 */

#ifdef LINUX_HAS_NETIF_F_TSO_ECN
	  /* Disable net_device features that quicksec does not support */
	  if (dev->features & NETIF_F_TSO_ECN)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_TSO_ECN",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_TSO_ECN;
	    }
#endif /* LINUX_HAS_NETIF_F_TSO_ECN */

#ifdef LINUX_HAS_NETIF_F_GSO_ROBUST
	  /* Disable net_device features that quicksec does not support */
	  if (dev->features & NETIF_F_GSO_ROBUST)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_GSO_ROBUST",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_GSO_ROBUST;
	    }
#endif /* LINUX_HAS_NETIF_F_GSO_ROBUST */

#ifdef LINUX_HAS_NETIF_F_UFO
	  if (dev->features & NETIF_F_UFO)
	    {
	      ssh_warning("Warning: Interface %d [%s], dropping unsupported "
			  "feature NETIF_F_UFO",
			  iface->ifindex, (dev->name ? dev->name : "<none>"));
	      dev->features &= ~NETIF_F_UFO;
	    }
#endif /* LINUX_HAS_NETIF_F_UFO */

	  /* Count addresses */
	  count = 0;

	  /* Increment refcount to make sure the device does not disappear. */ 
	  inet_dev = in_dev_get(dev);
	  if (inet_dev)
	    {
	      /* Count the device's IPv4 addresses */
	      for (addr = inet_dev->ifa_list; addr != NULL;
		   addr = addr->ifa_next)
		{
		  count++;
		}
	    }

#ifdef SSH_LINUX_INTERCEPTOR_IPV6
	  /* Increment refcount to make sure the device does not disappear. */
	  inet6_dev = in6_dev_get(dev);
	  if (inet6_dev)
	    {
	      /* Count the device's IPv6 addresses */
	      for (addr6 = inet6_dev->addr_list ; addr6 != NULL;
		   addr6 = addr6->if_next)
		{
		  count++;
		}
	    }
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */
	  
	  /* Fill interface entry. */

	  ifarray[n].ifnum = iface->ifindex;
	  ifarray[n].to_protocol.flags = 
	    SSH_INTERCEPTOR_MEDIA_INFO_NO_FRAGMENT;
	  ifarray[n].to_protocol.mtu_ipv4 = dev->mtu;
	  ifarray[n].to_adapter.flags = 0;
	  ifarray[n].to_adapter.mtu_ipv4 = dev->mtu;

#ifdef WITH_IPV6
	  ifarray[n].to_adapter.mtu_ipv6 = dev->mtu;
	  ifarray[n].to_protocol.mtu_ipv6 = dev->mtu;
#endif /* WITH_IPV6 */

#ifndef SSH_IPSEC_IP_ONLY_INTERCEPTOR
	  ifarray[n].to_adapter.media = ssh_interceptor_media_type(dev->type);
	  ifarray[n].to_protocol.media = ssh_interceptor_media_type(dev->type);
#else /* !SSH_IPSEC_IP_ONLY_INTERCEPTOR */
	  ifarray[n].to_adapter.media = SSH_INTERCEPTOR_MEDIA_PLAIN;
	  ifarray[n].to_protocol.media = SSH_INTERCEPTOR_MEDIA_PLAIN;
#endif /* !SSH_IPSEC_IP_ONLY_INTERCEPTOR */

	  strncpy(ifarray[n].name, dev->name, 15);

	  /* Set interface type and link status. */
	  if (dev->flags & IFF_POINTOPOINT)
	    ifarray[n].flags |= SSH_INTERFACE_FLAG_POINTOPOINT;
	  if (dev->flags & IFF_BROADCAST)
	    ifarray[n].flags |= SSH_INTERFACE_FLAG_BROADCAST;
	  if (!netif_carrier_ok(dev))
	    ifarray[n].flags |= SSH_INTERFACE_FLAG_LINK_DOWN;

	  ifarray[n].num_addrs = count;
	  ifarray[n].addrs = NULL;

	  /* Add addresses to interface entry. */
	  if (count > 0)
	    {
	      ifarray[n].addrs = ssh_malloc(sizeof(*ifarray[n].addrs) * count);
	      
	      if (ifarray[n].addrs == NULL)
		{
		  /* Release INET/INET6 devices */
		  if (inet_dev)
		    in_dev_put(inet_dev);
#ifdef SSH_LINUX_INTERCEPTOR_IPV6
		  if (inet6_dev)
		    in6_dev_put(inet6_dev);
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */
		  read_unlock(&interceptor->nf->if_table_lock);
		  goto out;
		}
	      count = 0;
	      if (inet_dev)
		{
		  /* Put the IPv4 addresses */
		  for (addr = inet_dev->ifa_list; 
		       addr != NULL; 
		       addr = addr->ifa_next)
		    {
		      ifarray[n].addrs[count].protocol = SSH_PROTOCOL_IP4;
		      SSH_IP4_DECODE(&ifarray[n].addrs[count].addr.ip.ip,
				     &addr->ifa_local);
		      SSH_IP4_DECODE(&ifarray[n].addrs[count].addr.ip.mask,
				     &addr->ifa_mask);

#if 0



		      if (dev->flags & IFF_POINTOPOINT)
			SSH_IP4_DECODE(&ifarray[n].addrs[count].
				       addr.ip.broadcast,
				       &addr->ifa_address);
		      else
#endif /* 0 */
			SSH_IP4_DECODE(&ifarray[n].addrs[count].
				       addr.ip.broadcast,
				       &addr->ifa_broadcast);
		      count++;
		    }
		}
	      
#ifdef SSH_LINUX_INTERCEPTOR_IPV6
	      if (inet6_dev)
		{
		  /* Put the IPv6 addresses */
		  for (addr6 = inet6_dev->addr_list; 
		       addr6 != NULL;
		       addr6 = addr6->if_next)
		    {
		      ifarray[n].addrs[count].protocol = SSH_PROTOCOL_IP6;
		      
		      SSH_IP6_DECODE(&ifarray[n].addrs[count].addr.ip.ip,
				     &addr6->addr);
		      
		      /* Generate mask from prefix length and IPv6 addr */
		      SSH_IP6_DECODE(&ifarray[n].addrs[count].addr.ip.mask,
				     "\xff\xff\xff\xff\xff\xff\xff\xff"
				     "\xff\xff\xff\xff\xff\xff\xff\xff");
		      ssh_ipaddr_set_bits(&ifarray[n].addrs[count].
					  addr.ip.mask,
					  &ifarray[n].addrs[count].
					  addr.ip.mask,
					  addr6->prefix_len, 0);
		      
		      /* Set the broadcast address to the IPv6 
			 undefined address */
		      SSH_IP6_DECODE(&ifarray[n].addrs[count].
				     addr.ip.broadcast,
				     "\x00\x00\x00\x00\x00\x00\x00\x00"
				     "\x00\x00\x00\x00\x00\x00\x00\x00");
		      
                      /* Copy the ifnum in case of ipv6 to scope_id, since
                         in linux scope_id == ifnum. */
                      ifarray[n].addrs[count].addr.ip.ip.
                        scope_id.scope_id_union.ui32 = ifarray[n].ifnum;
		      count++;
		    }
		}
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */
	    }
#ifndef SSH_IPSEC_IP_ONLY_INTERCEPTOR
	  /* Grab the MAC address */
	  ifarray[n].media_addr_len = dev->addr_len;
	  SSH_ASSERT(dev->addr_len <= sizeof(ifarray[n].media_addr));
	  memcpy(&ifarray[n].media_addr[0], dev->dev_addr, dev->addr_len);
#else /* !SSH_IPSEC_IP_ONLY_INTERCEPTOR */
	  ifarray[n].media_addr[0] = 0;
	  ifarray[n].media_addr_len = 0;
#endif /* !SSH_IPSEC_IP_ONLY_INTERCEPTOR */

	  /* Release INET/INET6 devices */
	  if (inet_dev)
	    in_dev_put(inet_dev);
	  inet_dev = NULL;
#ifdef SSH_LINUX_INTERCEPTOR_IPV6
	  if (inet6_dev)
	    in6_dev_put(inet6_dev);
	  inet6_dev = NULL;
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */

          /* Update the flags to the interface information. First 
             check if this is virtual adapter, and then check all 
             the other possible flags (e.g. broadcast, pointopoint).
             Other flags checking not implemented yet. */
#ifdef SSHDIST_IPSEC_VIRTUAL_ADAPTERS
          ssh_kernel_mutex_lock(interceptor->interceptor_lock);
          for (i = 0; i < SSH_LINUX_MAX_VIRTUAL_ADAPTERS; i++)
            {
              SshVirtualAdapter adapter = interceptor->nf->virtual_adapters[i];
              if (adapter && adapter->dev->ifindex == ifarray[n].ifnum)
                {	
                  ifarray[n].flags |= SSH_INTERFACE_FLAG_VIP;
                  break;
                }
            }
          ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
#endif /* SSHDIST_IPSEC_VIRTUAL_ADAPTERS */          

	  /* Done with the interface entry, 
	     increase ifarray index and continue with next iface. */
	  n++;

	} /* for (iface entry chain iteration) */
    } /* for (hashtable iteration) */

  /* Release if_table lock. */
  read_unlock(&interceptor->nf->if_table_lock);
  
  SSH_ASSERT(n < num);

  /* 'interceptor_lock' protects 'num_interface_callbacks' and
     'interfaces_callback'. */
  ssh_kernel_mutex_lock(interceptor->interceptor_lock);
  interceptor->nf->num_interface_callbacks++;
  interfaces_callback = interceptor->nf->interfaces_callback;
  ssh_kernel_mutex_unlock(interceptor->interceptor_lock);

  /* Call the interface callback. */
  (interfaces_callback)(n, ifarray, interceptor->nf->callback_context);

  ssh_kernel_mutex_lock(interceptor->interceptor_lock);
  interceptor->nf->num_interface_callbacks--;
  ssh_kernel_mutex_unlock(interceptor->interceptor_lock);

out:
  /* Free the array. */
  for (i = 0; i < n; i++)
    {
      if (ifarray[i].addrs != NULL)
        ssh_free(ifarray[i].addrs);
    }
  ssh_free(ifarray);

  return;
}
Esempio n. 20
0
void ssh_channel_ftcp_open_request(const char *type, int channel_id,
                                   const unsigned char *data, size_t len,
                                   SshConnOpenCompletionProc completion,
                                   void *completion_context, void *context)
{
  SshCommon common = (SshCommon)context;
  SshUInt32 port, originator_port;
  char *address_to_bind, *originator_ip;
  char port_string[20];
  SshRemoteTcpForward fwd;
  SshChannelTcpFwdConnect c;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("open request for remote forwarded TCP/IP channel"));

  ct = ssh_channel_ftcp_ct(common);

  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port, 
                       SSH_FORMAT_UINT32_STR, &originator_ip, NULL,
                       SSH_FORMAT_UINT32, &originator_port,
                       SSH_FORMAT_END) != len)
    {
      /* XXX should disconnect? */
      SSH_DEBUG(0, ("bad data"));
      (*completion)(SSH_OPEN_RESOURCE_SHORTAGE,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  snprintf(port_string, sizeof(port_string), "%ld", (long) port);

  ssh_debug("Received remote TCP/IP forward connect for port %s from %s:%ld",
            port_string, originator_ip, (long)originator_port);
  
  for (fwd = ct->remote_forwards; fwd; fwd = fwd->next)
    if (strcmp(fwd->address_to_bind, address_to_bind) == 0 &&
        strcmp(fwd->port, port_string) == 0)
      {
        c = ssh_xcalloc(1, sizeof(*c));
        c->fwd = fwd;
        c->channel_id = channel_id;
        c->completion = completion;
        c->completion_context = completion_context;

        ssh_tcp_connect_with_socks(fwd->connect_to_host, fwd->connect_to_port,
                           NULL, 1, ssh_channel_ftcp_open_connected,
                           (void *)c);

        ssh_xfree(address_to_bind);
        ssh_xfree(originator_ip);
        return;
      }

  ssh_warning("Received remote TCP/IP connect for non-forwarded port %s from %s:%ld",
              port_string, originator_ip, (long)originator_port);

  ssh_xfree(address_to_bind);
  ssh_xfree(originator_ip);
  
  (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                completion_context);
}
Esempio n. 21
0
void ssh_channel_dtcp_open_request(const char *type, int channel_id,
                                   const unsigned char *data, size_t len,
                                   SshConnOpenCompletionProc completion,
                                   void *completion_context, void *context)
{
  SshCommon common = (SshCommon)context;
  char *connect_to_host, connect_to_port[20], *originator_ip;
  SshUInt32 port, originator_port;
  SshDirectTcp tcp;

  SSH_DEBUG(5, ("direct TCP/IP channel open request"));
  
  /* Parse packet data. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &connect_to_host, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_UINT32_STR, &originator_ip, NULL,
                       SSH_FORMAT_UINT32, &originator_port,
                       SSH_FORMAT_END) != len)
    {
      /* XXX disconnect? */
      SSH_DEBUG(0, ("bad data"));
      (*completion)(SSH_OPEN_RESOURCE_SHORTAGE,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  /* We do not currently allow direct connections from server to client. */
  if (common->client)
    {
      ssh_warning("Direct TCP/IP connection request from server "
                  "to %s:%ld denied.",
                  connect_to_host, (long)port);
      /* Free dynamically allocated data. */
      ssh_xfree(originator_ip);
      ssh_xfree(connect_to_host);
      (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }


  /* Convert port number to string. */
  snprintf(connect_to_port, sizeof(connect_to_port), "%ld", (long) port);

  ssh_debug("Direct TCP/IP connect to %s:%s from %s:%ld",
            connect_to_host, connect_to_port, originator_ip,
            (long)originator_port);
  
  /* Save data for callback. */
  tcp = ssh_xcalloc(1, sizeof(*tcp));
  tcp->common = common;
  tcp->channel_id = channel_id;
  tcp->completion = completion;
  tcp->completion_context = completion_context;

  /* Connect to the given host/port. */
  ssh_tcp_connect_with_socks(connect_to_host, connect_to_port, 
                             NULL, 1, ssh_channel_dtcp_connected, 
                             (void *)tcp);

  /* Free dynamically allocated data. */
  ssh_xfree(originator_ip);
  ssh_xfree(connect_to_host);
}
Esempio n. 22
0
Boolean ssh_match_port(SshUInt32 port, const char *pattern)
{
  SshUInt32 lower_port, upper_port;

  /* Check for '*' wildcard */
  if (strcmp(pattern, "*") == 0)
    return 1;

  lower_port = 0;
  upper_port = 65535;

  if (*pattern == '<')
    {
      pattern++;
      upper_port = atoi(pattern);
      if (upper_port == 0)
        goto invalid_number;
      upper_port--;             /* Make range inclusive */
      for (; *pattern && isdigit(*pattern); pattern++)
        ;
    }
  else if (*pattern == '>')
    {
      pattern++;
      lower_port = atoi(pattern);
      if (lower_port == 0)
        goto invalid_number;
      lower_port++;             /* Make range inclusive */
      for (; *pattern && isdigit(*pattern); pattern++)
        ;
    }
  else
    {
      lower_port = atoi(pattern);
      if (lower_port == 0)
        goto invalid_number;
      for (; *pattern && isdigit(*pattern); pattern++)
        ;
      if (*pattern == '.' && *(pattern + 1) == '.')
        {
          pattern += 2;
          upper_port = atoi(pattern);
          if (upper_port == 0)
            goto invalid_number;
          for (; *pattern && isdigit(*pattern); pattern++)
            ;
        }
      else
        {
          upper_port = lower_port;
        }
    }
  if (*pattern)
    {
      ssh_warning("Junk after port pattern: %.20s", pattern);
      return FALSE;
    }

  if ((SshUInt32)lower_port <= (SshUInt32)port &&
      (SshUInt32)port <= (SshUInt32)upper_port)
    return TRUE;

  return FALSE;

invalid_number:
  ssh_warning("Invalid number in port pattern: %.20s", pattern);
  return FALSE;
}
Esempio n. 23
0
/* The interceptor_update_interfaces() function traverses the kernels
   list of interfaces, grabs a refcnt for each one, and updates the
   interceptors 'ifnum->net_device' cache (optimizing away the need to
   grab a lock, traverse dev_base linked list, unlock, for each
   packet). 
   
   This function grabs 'if_table_lock' (for writing) and dev_base lock. */
static void
ssh_interceptor_update_interfaces(SshInterceptor interceptor)
{
  SshInterceptorInternalInterface iface, iface_prev, iface_next;
  struct net_device *dev;
  SshUInt32 i, hashvalue, ifindex;

  /* WARNING: TWO LOCKS HELD AT THE SAME TIME. BE CAREFUL!
     dev_base_lock MUST be held to ensure integrity during traversal
     of list of interfaces in kernel. */
  SSH_LOCK_LINUX_DEV_LIST();

  /* Grab 'if_table_lock' for modifying the interface table. */
  write_lock(&interceptor->nf->if_table_lock);

  /* Increment 'if_generation' */
  interceptor->nf->if_generation++;
  if (interceptor->nf->if_generation == 0)
    interceptor->nf->if_generation++; /* Handle wrapping */

  /* Traverse net_device list, add new interfaces to hashtable,
     and mark existing entries up-to-date. */
  for (dev = SSH_FIRST_NET_DEVICE(); 
       dev != NULL; 
       dev = SSH_NEXT_NET_DEVICE(dev))
    {
      ifindex = (SshUInt32) dev->ifindex;

      /* Ignore the loopback device. */
      if (dev->flags & IFF_LOOPBACK)
	continue;

      /* Ignore interfaces that collide with SSH_INTERCEPTOR_INVALID_IFNUM */
      if (ifindex == SSH_INTERCEPTOR_INVALID_IFNUM)
	{



	  ssh_warning("Interface index collides with "
		      "SSH_INTERCEPTOR_INVALID_IFNUM, "
		      "ignoring interface %d[%s]",
		      ifindex,
		      (dev->name ? dev->name : "<none>"));
	  continue;
	}



















      /* Assert that 'dev->ifindex' is otherwise valid. */ 
      SSH_LINUX_ASSERT_VALID_IFNUM(ifindex);

      /* Lookup interface from the hashtable. */
      for (iface = 
	     interceptor->nf->if_hash[ifindex % SSH_LINUX_IFACE_HASH_SIZE];
	   iface != NULL && iface->ifindex != ifindex;
	   iface = iface->next)
	;

      /* Interface found */
      if (iface)
	{
	  if (iface->dev == dev)
	    {
	      SSH_DEBUG(SSH_D_NICETOKNOW, 
			("Old interface %d[%s]", 
			 ifindex, (dev->name ? dev->name : "<none>")));
	      
	      /* Mark up-to-date. */
	      iface->generation = interceptor->nf->if_generation;
	    }

	  /* Interface index matches, but net_device has changed. */
	  else 
	    {
	      SSH_DEBUG(SSH_D_NICETOKNOW, 
			("Changed interface %d[%s] (from %d[%s])", 
			 ifindex,
			 (dev->name ? dev->name : "<none>"),
			 iface->ifindex,
			 (iface->dev->name ? iface->dev->name : "<none>")));

	      /* Release old net_device. */
	      SSH_ASSERT(iface->dev != NULL);
	      dev_put(iface->dev);
	      /* Hold new net_device. */
	      dev_hold(dev);
	      wmb(); /* Make sure assignments are not reordered. */
	      iface->dev = dev;
	      iface->ifindex = ifindex;
	      iface->context = NULL;
	      /* Mark up-to-date. */
	      iface->generation = interceptor->nf->if_generation;
	    }
	}

      /* Interface not found */
      else
	{
	  SSH_DEBUG(SSH_D_NICETOKNOW, 
		    ("New interface %d[%s]", 
		     ifindex, (dev->name ? dev->name : "<none>")));

	  /* Allocate new interface entry */
	  iface = ssh_interceptor_alloc_iface(interceptor);
	  if (iface)
	    {
	      /* Hold new net_device. */
	      dev_hold(dev);
	      /* Fill interface entry. */
	      iface->ifindex = ifindex;
	      iface->dev = dev;
	      iface->context = NULL;
	      /* Mark up-to-date */
	      iface->generation = interceptor->nf->if_generation;
	      /* Add entry to hashtable. */
	      hashvalue = iface->ifindex % SSH_LINUX_IFACE_HASH_SIZE;
	      iface->next = interceptor->nf->if_hash[hashvalue];
	      wmb();
	      interceptor->nf->if_hash[hashvalue] = iface;
	    }
	  else
	    {
	      SSH_DEBUG(SSH_D_FAIL, 
			("Could not allocate memory for new interface %d[%s]",
			 ifindex, (dev->name ? dev->name : "<none>")));
	    }
	}
    }

  /* Remove old interfaces from the table */
  for (i = 0; i < SSH_LINUX_IFACE_HASH_SIZE; i++)
    {
      iface_prev = NULL;
      for (iface = interceptor->nf->if_hash[i];
	   iface != NULL;
	   iface = iface_next)
	{
	  if (iface->generation != 0 &&
	      iface->generation != interceptor->nf->if_generation)
	    {
	      SSH_DEBUG(SSH_D_NICETOKNOW, 
			("Disappeared interface %d[%s]", 
			 iface->ifindex,
			 (iface->dev->name ? iface->dev->name : "<none>")));

	      /* Release old netdevice */
	      SSH_ASSERT(iface->dev != NULL);
	      dev_put(iface->dev);

#ifdef DEBUG_LIGHT
	      wmb();
	      iface->dev = NULL;
	      iface->ifindex = SSH_INTERCEPTOR_INVALID_IFNUM;	      
#endif /* DEBUG_LIGHT */

	      /* Mark entry freed. */
	      iface->generation = 0;
	      
	      /* Remove entry from hashtable. */
	      if (iface_prev)
		iface_prev->next = iface->next;
	      else
		interceptor->nf->if_hash[i] = iface->next;
	      iface_next = iface->next;
	      iface->next = NULL;
	    }
	  else
	    {
	      iface_prev = iface;
	      iface_next = iface->next;
	    }
	}
    }
  /* Unlock if_table_lock */
  write_unlock(&interceptor->nf->if_table_lock);

  /* Release dev_base_lock. */
  SSH_UNLOCK_LINUX_DEV_LIST();

  /* Notify changes to engine */
  if (interceptor->engine != NULL && interceptor->engine_open == TRUE)
    {
      local_bh_disable();
      ssh_interceptor_send_interfaces(interceptor);
      local_bh_enable();
    }

  return;
}
Esempio n. 24
0
SshPipeStatus ssh_pipe_create_and_fork(SshStream *stdio_return,
                                       SshStream *stderr_return)
{
    int pin[2], pout[2], perr[2];
    pid_t pid;
    SshPipeStream pipes;

    if (pipe(pin) < 0)
        return SSH_PIPE_ERROR;
    if (pipe(pout) < 0)
    {
        close(pin[0]);
        close(pin[1]);
        return SSH_PIPE_ERROR;
    }
    if (stderr_return != NULL && pipe(perr) < 0)
    {
        close(pin[0]);
        close(pin[1]);
        close(pout[0]);
        close(pout[1]);
        return SSH_PIPE_ERROR;
    }

    /* Initialize SIGCHLD handling.  This will ensure the SIGCHLD won't get
       delivered until we register the handler for the new process below. */
    ssh_sigchld_initialize();

    /* Fork a child process. */
    pid = fork();
    if (pid < 0)
    {
        ssh_warning("Fork failed: %s", strerror(errno));
        close(pin[0]);
        close(pin[1]);
        close(pout[0]);
        close(pout[1]);
        if (stderr_return != NULL)
        {
            close(perr[0]);
            close(perr[1]);
        }
        return SSH_PIPE_ERROR;
    }

    /* The remaining processing depends on whether we are the parent or
       the child. */
    if (pid == 0)
    {
        /* Redirect stdin. */
        close(pin[1]);
        if (dup2(pin[0], 0) < 0)
            perror("dup2 stdin");
        close(pin[0]);

        /* Redirect stdout. */
        close(pout[0]);
        if (dup2(pout[1], 1) < 0)
            perror("dup2 stdout");
        close(pout[1]);

        if (stderr_return != NULL)
        {
            /* Redirect stderr. */
            close(perr[0]);
            if (dup2(perr[1], 2) < 0)
                perror("dup2 stderr");
            close(perr[1]);
        }

        *stdio_return = NULL;
        if (stderr_return != NULL)
            *stderr_return = NULL;
        return SSH_PIPE_CHILD_OK;
    }

    /* Parent */
    pipes = ssh_xcalloc(sizeof(*pipes), 1);
    pipes->pid = pid;
    pipes->callback = NULL;
    pipes->callback_context = NULL;

    pipes->status_returned = FALSE;
    pipes->exit_status = -1;

    /* Close the child-side file descriptors. */
    close(pin[0]);
    close(pout[1]);
    if (stderr_return != NULL)
        close(perr[1]);

    /* Register a handler for SIGCHLD for our new child. */
    ssh_sigchld_register(pid, ssh_pipe_sigchld_handler, (void *)pipes);

    /* Wrap the master fd into a stream. */
    pipes->stdio_stream = ssh_stream_fd_wrap2(pout[0], pin[1], TRUE);
    *stdio_return = ssh_stream_create(&ssh_pipe_methods, (void *) pipes);

    /* Create the stderr stream if requested. */
    /* XXX should another context (errpipes?) be allocated for this, so that
       this, too, could be created as above?*/
    if (stderr_return != NULL)
        *stderr_return = ssh_stream_fd_wrap(perr[0], TRUE);

    return SSH_PIPE_PARENT_OK;
}
Esempio n. 25
0
Boolean ssh_pty_internal_make_ctty(int *ttyfd, const char *ttyname)
{
  int fd;

  /* First disconnect from the old controlling tty. */
#ifdef TIOCNOTTY
  fd = open("/dev/tty", O_RDWR|O_NOCTTY);
  if (fd >= 0)
    {
      (void)ioctl(fd, TIOCNOTTY, NULL);
      close(fd);
    }
#endif /* TIOCNOTTY */
  
  /* Verify that we are successfully disconnected from the controlling tty. */
  fd = open("/dev/tty", O_RDWR|O_NOCTTY);
  if (fd >= 0)
    {
      ssh_warning("Failed to disconnect from controlling tty.");
      close(fd);
    }

  /* Make it our controlling tty. */
#ifdef TIOCSCTTY
  ssh_debug("Setting controlling tty using TIOCSCTTY.");
  /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
     EINVAL with these arguments, and there is absolutely no documentation. */
  ioctl(*ttyfd, TIOCSCTTY, NULL);
#endif /* TIOCSCTTY */

#ifdef HAVE_SETPGID
  /* This appears to be necessary on some machines...  */
  setpgid(0, 0);
#endif

  fd = open(ttyname, O_RDWR);
  if (fd < 0)
    ssh_warning("%.100s: %.100s", ttyname, strerror(errno));
  else
    close(fd);

  /* Verify that we now have a controlling tty. */
  fd = open("/dev/tty", O_WRONLY);
  if (fd < 0)
    {
      ssh_warning("open /dev/tty failed; could not set controlling tty: %",
		  strerror(errno));
      return FALSE;
    }
  close(fd);
#if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
  signal(SIGHUP, SIG_IGN);
  vhangup();
  signal(SIGHUP, SIG_DFL);
  fd = open(ttyname, O_RDWR);
  if (fd == -1)
    ssh_warning("pty_make_controlling_tty: reopening controlling tty after vhangup failed for %.100s",
		ttyname);
  close(*ttyfd);
  *ttyfd = fd;
#endif /* HAVE_VHANGUP && !HAVE_REVOKE */
  return TRUE;
}
Esempio n. 26
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;
}
Esempio n. 27
0
Boolean cipher_encrypt(SshCipher cipher, FILE *fin, FILE *fout)
{
  const char *cipher_name = NULL;
  size_t block_len, buf_used, buf_len, tr_len;
  unsigned char *buf = NULL;
  size_t len;
  SshCryptoStatus cs;

  cipher_name = ssh_cipher_name(cipher);
  block_len = ssh_cipher_get_block_length(cipher_name);
  buf_len = CIPHER_BUFFER_LEN;
  while (buf_len % block_len != 0)
    {
      SSH_DEBUG(5, ("Growing test data len to match with cipher block size."));
      buf_len++;
    }
  buf = ssh_xmalloc(buf_len);
  buf_used = 0;
  while (1)
    {
      len = fread(buf + buf_used, 1, buf_len - buf_used, fin);
      buf_used += len;
      if (buf_used >= block_len)
        {
          tr_len = buf_used - (buf_used % block_len);
          cs = ssh_cipher_transform(cipher, buf, buf, tr_len);
          if (cs != SSH_CRYPTO_OK)
            {
              ssh_warning("%s: ssh_cipher_transform failed (%d).",
                          av0, (int)cs);
              goto encrypt_failed;
            }
          if (fwrite(buf, 1, tr_len, fout) != tr_len)
            {
              ssh_warning("%s: File write failed.", av0);
              goto encrypt_failed;
            }
          buf_used -= tr_len;
          if (buf_used > 0)
            memcpy(buf, buf + tr_len, buf_used);
        }
      if (feof(fin))
        {
          SSH_ASSERT(block_len > buf_used);
          if (block_len > 1)
            {
              memset(buf + buf_used, buf_used, block_len - buf_used);
              cs = ssh_cipher_transform(cipher,
                                        buf,
                                        buf,
                                        block_len);
              if (cs != SSH_CRYPTO_OK)
                {
                  ssh_warning("%s: ssh_cipher_transform failed (%d).",
                              av0, (int)cs);
                  goto encrypt_failed;
                }
              if (fwrite(buf, 1, block_len, fout) != block_len)
                {
                  ssh_warning("%s: File write failed.", av0);
                  goto encrypt_failed;
                }
            }
          break;
        }
    }
  ssh_xfree(buf);
  return TRUE;

 encrypt_failed:
  ssh_xfree(buf);
  return FALSE;
}
Esempio n. 28
0
Boolean cipher_decrypt(SshCipher cipher, FILE *fin, FILE *fout)
{
  const char *cipher_name = NULL;
  size_t block_len, buf_used, buf_len;
  unsigned char *buf = NULL;
  size_t len, tr_len;
  SshCryptoStatus cs;
  int i;

  cipher_name = ssh_cipher_name(cipher);
  block_len = ssh_cipher_get_block_length(cipher_name);
  buf_len = CIPHER_BUFFER_LEN;
  while (buf_len % block_len != 0)
    {
      SSH_DEBUG(5, ("Growing test data len to match with cipher block size."));
      buf_len++;
    }
  buf = ssh_xmalloc(buf_len);
  buf_used = 0;
  while (1)
    {
      len = fread(buf + buf_used, 1, buf_len - buf_used, fin);
      buf_used += len;
      if (buf_used >= (2 * block_len))
        {
          if (block_len == 1)
            tr_len = buf_used;
          else
            tr_len = buf_used - (buf_used % block_len) - block_len;
          cs = ssh_cipher_transform(cipher, buf, buf, tr_len);
          if (cs != SSH_CRYPTO_OK)
            {
              ssh_warning("%s: ssh_cipher_transform failed (%d).",
                          av0, (int)cs);
              goto decrypt_failed;
            }
          if (fwrite(buf, 1, tr_len, fout) != tr_len)
            {
              ssh_warning("%s: File write failed.", av0);
              goto decrypt_failed;
            }
          buf_used -= tr_len;
          if (buf_used > 0)
            memcpy(buf, buf + tr_len, buf_used);
        }
      if (feof(fin))
        {
          if (block_len < buf_used)
            {
              ssh_warning("%s: Invalid input file size.", av0);
              goto decrypt_failed;
            }
          if (block_len == 1)
            break;
          if (buf_used < block_len)
            {
              ssh_warning("%s: Truncated input file.", av0);
              goto decrypt_failed;
            }
          cs = ssh_cipher_transform(cipher,
                                    buf,
                                    buf,
                                    block_len);
          if (cs != SSH_CRYPTO_OK)
            {
              ssh_warning("%s: ssh_cipher_transform failed (%d).",
                          av0, (int)cs);
              goto decrypt_failed;
            }
          if (buf[block_len - 1] >= block_len)
            {
              ssh_warning("%s: Malformed input padding.", av0);
              goto decrypt_failed;
            }
          for (i = buf[block_len - 1]; i < block_len - 1; i++)
            {
              if (buf[i] != buf[block_len - 1])
                {
                  ssh_warning("%s: Malformed input padding.", av0);
                  goto decrypt_failed;
                }
            }
          if (buf[block_len - 1] > 0)
            {
              if (fwrite(buf, 1, buf[block_len - 1], fout) !=
                  buf[block_len - 1])
                {
                  ssh_warning("%s: File write failed.", av0);
                  goto decrypt_failed;
                }
            }
          break;
        }
    }

  ssh_xfree(buf);
  return TRUE;

 decrypt_failed:
  ssh_xfree(buf);
  return FALSE;
}
Esempio n. 29
0
int main(int argc, char **argv)
{
    SshStream stdio_stream;
    SshSigner signer;
    char config_filename[512];
    char *temp_name;

#ifdef SLEEP_AFTER_STARTUP
    sleep(30);
#endif /* SLEEP_AFTER_STARTUP */

    /* Get program name (without path). */
    if ((temp_name = strrchr(argv[0], '/')) != NULL)
        progname = ssh_xstrdup(temp_name + 1);
    else
        progname = ssh_xstrdup(argv[0]);

    /* XXX there should be a way to give command-line parameters to this
       program, but, they should only be used if the uid is the same as
       euid. */
    ssh_event_loop_initialize();

    signer = ssh_xcalloc(1, sizeof(*signer));

#ifdef SIGNER_QUIET
    signer->quiet = TRUE;
#else /* SIGNER_QUIET */
    signer->quiet = FALSE;
#endif /* SIGNER_QUIET */
    ssh_debug_register_callbacks(signer_ssh_fatal, signer_ssh_warning,
                                 signer_ssh_debug, (void *)signer);
#ifdef SIGNER_DEBUG
    ssh_debug_set_global_level(5);
#endif /* SIGNER_DEBUG */

    /* Act as server. */
    signer->config = ssh_server_create_config();

    SSH_TRACE(2, ("public key file: %s", signer->config->public_host_key_file));
    SSH_TRACE(2, ("private key file: %s", signer->config->host_key_file));
    SSH_TRACE(2, ("randomseed file: %s", signer->config->random_seed_file));

    /* Initialize user context with euid. This is used to dig up the
       hostkey and such. */
    signer->effective_user_data = ssh_user_initialize_with_uid(geteuid(), FALSE);

    signer->random_state = ssh_randseed_open(signer->effective_user_data,
                           signer->config);

    /* XXX what about alternative config files? This should be possible
       to configure somehow. An option for configure is probably a good
       idea. */
    snprintf(config_filename, sizeof(config_filename), "%s/%s",
             SSH_SERVER_DIR, SSH_SERVER_CONFIG_FILE);

    if (!ssh_config_read_file(signer->effective_user_data, signer->config,
                              NULL, config_filename, NULL))
        ssh_warning("%s: Failed to read config file %s", argv[0],
                    config_filename);

    stdio_stream = ssh_stream_fd_wrap2(fileno(stdin), fileno(stdout),
                                       TRUE);

    signer->wrapper = ssh_packet_wrap(stdio_stream,
                                      signer_received_packet,
                                      signer_received_eof,
                                      signer_can_send,
                                      signer);

    ssh_event_loop_run();

    return 0;
}
Esempio n. 30
0
void ssh_client_auth_hostbased(SshAuthClientOperation op,
                               const char *user,
                               unsigned int packet_type,
                               SshBuffer *packet_in,
                               const unsigned char *session_id,
                               size_t session_id_len,
                               void **state_placeholder,
                               SshAuthClientCompletionProc completion,
                               void *completion_context,
                               void *method_context)
{
  SshClientHostbasedAuth state;
  SshClient client;
  SshStream stdio_stream;
  char hostkeyfile[512];
  /*  char *keytype;
  SshPublicKey pubkey;*/
  char **signer_argv;
  char config_filename[512];
  size_t hostname_len;
  
  SSH_DEBUG(6, ("auth_hostbased op = %d  user = %s", op, user));

  client = (SshClient)method_context;
  state = *state_placeholder;

  switch (op)
    {
      /* This operation is always non-interactive, as hostkeys
         shouldn't have passphrases. Check for it, though. XXX */
    case SSH_AUTH_CLIENT_OP_START_NONINTERACTIVE:
      /* XXX There is a bug in sshauthc.c (or
         elsewhere). Authentication methods, that are not allowed,
         should not be tried. Now it calls
         SSH_AUTH_CLIENT_OP_START_NONINTERACTIVE for every
         authentication method before checking.*/
      (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context);
      break;
      
    case SSH_AUTH_CLIENT_OP_START:
      /* This is the first operation for doing hostbased authentication.
         We should not have any previous saved state when we come here. */
      SSH_ASSERT(*state_placeholder == NULL);

      /* Initialize a context. */
      state = ssh_xcalloc(1, sizeof(*state));

      state->session_id = session_id;
      state->session_id_len = session_id_len;
      state->user = ssh_xstrdup(user);

      /* We have to dig up the server configuration to get the place
         for the client host's publickey. This is a very kludgeish
         solution. XXX*/
      state->server_conf = ssh_server_create_config();
      
      /* Dig up hosts publickey. */
      
      snprintf(config_filename, sizeof(config_filename), "%s/%s",
               SSH_SERVER_DIR, SSH_SERVER_CONFIG_FILE);
      
      if (!ssh_config_read_file(client->user_data, state->server_conf,
                                NULL, config_filename, NULL))
        SSH_TRACE(2, ("Failed to read config file %s", \
                      config_filename));


      if(state->server_conf->public_host_key_file[0] != '/')
        {
          snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR,
                   state->server_conf->public_host_key_file);
        }
      else
        {
          snprintf(hostkeyfile, sizeof(hostkeyfile), "%s",
                   state->server_conf->public_host_key_file);  
        }

      /* This pubkey*-stuff is for the client _host's_ public
         hostkey. */
      SSH_DEBUG(4, ("Reading pubkey-blob from %s...", hostkeyfile));
      if (ssh2_key_blob_read(client->user_data, hostkeyfile, NULL,
                             &state->pubkeyblob,
                             &state->pubkeyblob_len, NULL) 
          != SSH_KEY_MAGIC_PUBLIC)
        {         
          goto error;
        }
      
      SSH_DEBUG(4, ("done."));
      if ((state->pubkey_algorithm =
           ssh_pubkeyblob_type(state->pubkeyblob,
                               state->pubkeyblob_len))
          == NULL)
        {
          goto error;
        }
      
      state->local_user_name = ssh_user_name(client->user_data);
      state->local_host_name = ssh_xmalloc(MAXHOSTNAMELEN + 1);
      ssh_tcp_get_host_name(state->local_host_name, MAXHOSTNAMELEN + 1);
      hostname_len = strlen(state->local_host_name);
      /* Sanity check */
      SSH_ASSERT(hostname_len + 2 < MAXHOSTNAMELEN);
      /* We want FQDN. */
      state->local_host_name[hostname_len] = '.';
      state->local_host_name[hostname_len + 1] = '\0';
      
      state->completion = completion;
      state->completion_context = completion_context;
      state->state_placeholder = state_placeholder;
      
      /* Assign the state to the placeholder that survives across
         calls.  (this is actually not needed, as hostbased
         authentication procedure is very simple. Just one packet from
         client to server, and server's response in one packet.) */
      *state_placeholder = state;

      /* Open a pipestream connection to ssh-signer. */
      switch (ssh_pipe_create_and_fork(&stdio_stream, NULL))
        {
        case SSH_PIPE_ERROR:
          /* Something went wrong. */
          ssh_warning("Couldn't create pipe to connect to %s.",
                      client->config->signer_path);
          goto error;
          break;
        case SSH_PIPE_CHILD_OK:
          /* Exec ssh-signer */
          SSH_TRACE(0, ("Child: Execing ssh-signer...(path: %s)", \
                        client->config->signer_path));

          signer_argv = ssh_xcalloc(2, sizeof(char *));
          signer_argv[0] = client->config->signer_path;
          signer_argv[1] = NULL;
          
          execvp(client->config->signer_path, signer_argv);
          fprintf(stderr, "Couldn't exec '%s' (System error message: %s)",
                  client->config->signer_path, strerror(errno));
          ssh_fatal("Executing ssh-signer failed.");
          break;
        case SSH_PIPE_PARENT_OK:
          state->wrapper = ssh_packet_wrap(stdio_stream,
                                           auth_hostbased_received_packet,
                                           auth_hostbased_received_eof,
                                           auth_hostbased_can_send,
                                           state);
          /* We don't check wrapper's validity, as ssh_packet_wrap
             should always succeed.*/
          break;
        }
      /* Here we continue as parent. */
      
      /* sign packet with ssh-signer (a suid-program). */
      if (ssh_packet_wrapper_can_send(state->wrapper))
        {
          ssh_client_auth_hostbased_send_to_signer(state);
        }
      /* If ssh_packet_wrapper_can_send returns FALSE,
         auth_hostbased_can_send will call the ...send_to_signer
         function above. */
      
      /* Rest is done in callbacks. */
      break;
      
    case SSH_AUTH_CLIENT_OP_CONTINUE:          
      SSH_TRACE(2, ("Invalid message. We didn't return " \
                    "SSH_AUTH_CLIENT_SEND_AND_CONTINUE at any stage!"));
      /* Send failure message.*/
      (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context);
      return;

    case SSH_AUTH_CLIENT_OP_ABORT:
      /* Abort the authentication operation immediately. */
      /* XXX Destroy 'state'-object. */
      *state_placeholder = NULL;
      break;

    default:
      /* something weird is going on.. */
      ssh_fatal("ssh_client_auth_hostbased: unknown op %d", (int)op);
    }
  return;

 error:
  /* XXX Destroy state. */
  /* Send failure message.*/
  (*completion)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context);
  return;
}