Ejemplo n.º 1
0
static void
do_service_request(struct packet_handler *c,
		   struct ssh_connection *connection,
		   struct lsh_string *packet)
{
  CAST(service_handler, closure, c);

  struct simple_buffer buffer;
  unsigned msg_number;
  int name;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_SERVICE_REQUEST)
      && parse_atom(&buffer, &name)
      && parse_eod(&buffer))
    {
      if (name)
	{
	  CAST_SUBTYPE(command, service, ALIST_GET(closure->services, name));
	  if (service)
	    {
	      /* Don't accept any further service requests */
	      connection->dispatch[SSH_MSG_SERVICE_REQUEST]
		= &connection_fail_handler;

	      /* Start service */
#if DATAFELLOWS_WORKAROUNDS
	      if (connection->peer_flags & PEER_SERVICE_ACCEPT_KLUDGE)
		C_WRITE(connection, format_service_accept_kludge());
	      else
#endif /* DATAFELLOWS_WORKAROUNDS */
		C_WRITE(connection, format_service_accept(name));
	      
	      COMMAND_CALL(service, connection,
			   closure->c, closure->e);
	      return;
	    }
	}
      EXCEPTION_RAISE(connection->e,
		      make_protocol_exception(SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, NULL));
      
    }
  else
      PROTOCOL_ERROR(connection->e, "Invalid SERVICE_REQUEST message");
}
Ejemplo n.º 2
0
Archivo: rsa.c Proyecto: macssh/macssh
/* Alternative constructor using a key of type ssh-rsa, when the atom
 * "ssh-rsa" is already read from the buffer. */
struct verifier *
parse_ssh_rsa_public(struct simple_buffer *buffer)
{
  NEW(rsa_verifier, res);
  init_rsa_verifier(res, &rsa_sha1_algorithm);

  if (parse_bignum(buffer, res->e, RSA_MAX_SIZE)
      && (mpz_sgn(res->e) == 1)
      && parse_bignum(buffer, res->n, RSA_MAX_SIZE)
      && (mpz_sgn(res->n) == 1)
      && (mpz_cmp(res->e, res->n) < 0)
      && parse_eod(buffer)
      && rsa_check_size(res))
    return &res->super;

  else
    {
      KILL(res);
      return NULL;
    }
}
Ejemplo n.º 3
0
static void
lshd_service_request_handler(struct transport_forward *self,
			     uint32_t length, const uint8_t *packet)
{
  struct simple_buffer buffer;
  unsigned msg_number;

  const uint8_t *name;
  uint32_t name_length;

  simple_buffer_init(&buffer, length, packet);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_SERVICE_REQUEST)
      && parse_string(&buffer, &name_length, &name)
      && parse_eod(&buffer))
    {
      CAST(lshd_context, ctx, self->super.ctx);
      const struct service_entry *service
	= service_config_lookup(ctx->service_config,
				name_length, name);
      
      if (service)
	{
	  int pipe[2];
	  pid_t child;

	  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe) < 0)
	    {
	      werror("lshd_service_request_handler: socketpair failed: %e.\n",
		     errno);
	      transport_disconnect(&self->super,
				   SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
				   "Service could not be started");
	      return;
	    }

	  child = fork();
	  if (child < 0)
	    {
	      werror("lshd_service_request_handler: fork failed: %e.\n",
		     errno);
	      close(pipe[0]);
	      close(pipe[1]);
	      transport_disconnect(&self->super,
				   SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
				   "Service could not be started");
	      return;
	    }
	  if (child)
	    {
	      /* Parent process */
	      close(pipe[1]);

	      transport_send_packet(&self->super, TRANSPORT_WRITE_FLAG_PUSH,
				    format_service_accept(name_length, name));

	      /* Setup forwarding. Replaces event_handler and packet_handler. */
	      transport_forward_setup(self, pipe[0], pipe[0]);
	    }
	  else
	    {
	      /* Child process */
	      struct arglist args;
	      const char *program;
	      unsigned i;

	      close(pipe[0]);
	      dup2(pipe[1], STDIN_FILENO);
	      dup2(pipe[1], STDOUT_FILENO);
	      close(pipe[1]);

	      /* FIXME: Pass sufficient information so that
		 $SSH_CLIENT can be set properly. */
	      arglist_init (&args);

	      program = service->args.argv[0];
	      arglist_push (&args, program);

	      /* If not absolute, interpret it relative to
		 libexecdir. */
	      if (program[0] != '/')
		program = lsh_get_cstring(ssh_format("%lz/%lz",
						     ctx->service_config->libexec_dir,
						     program));
	      
	      for (i = 1; i < service->args.argc; i++)
		{
		  const char *arg = service->args.argv[i];
		  if (arg[0] == '$')
		    {
		      if (!strcmp(arg+1, "(session_id)"))
			arg = lsh_get_cstring(ssh_format("%lxS",
							 self->super.session_id));
		    }
		  arglist_push (&args, arg);
		}
	      debug("exec of service %s, program %z. Argument list:\n",
		    name_length, name, program);
	      for (i = 0; i < args.argc; i++)
		debug("  %z\n", args.argv[i]);

	      execv(program, (char **) args.argv);

	      werror("lshd_service_request_handler: exec of %z failed: %e.\n",
		     args.argv[0], errno);
	      _exit(EXIT_FAILURE);
	    }
	}
      else
	transport_disconnect(&self->super,
			     SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
			      "Service not available");
    }
  else
    transport_protocol_error(&self->super, "Invalid SERVICE_REQUEST");
}
Ejemplo n.º 4
0
Archivo: rsa.c Proyecto: macssh/macssh
static int
do_rsa_verify(struct verifier *v,
	      int algorithm,
	      UINT32 length,
	      const UINT8 *msg,
	      UINT32 signature_length,
	      const UINT8 *signature_data)
{
  CAST(rsa_verifier, self, v);
  mpz_t s;
  int res = 0;

  trace("do_rsa_verify: Verifying %a signature\n", algorithm);
  
  mpz_init(s);
  
  switch(algorithm)
    {
#if 0
    case ATOM_RSA_PKCS1_SHA1:
    case ATOM_RSA_PKCS1_SHA1_LOCAL:

      if (signature_length > self->size)
	goto fail;
  
      bignum_parse_u(s, signature_length, signature_data);
      break;

    case ATOM_SPKI:
#endif
    case ATOM_SSH_RSA:
      {
	struct simple_buffer buffer;
	UINT32 length;
	const UINT8 *digits;
	int atom;
	
	simple_buffer_init(&buffer, signature_length, signature_data);

	if (!(parse_atom(&buffer, &atom)
	      && (atom == ATOM_SSH_RSA)
	      && parse_string(&buffer, &length, &digits)
	      && (length <= self->size)
	      && parse_eod(&buffer) ))
	  goto fail;

	bignum_parse_u(s, length, digits);

	break;
      }
      
      /* It doesn't matter here which flavour of SPKI is used. */
    case ATOM_SPKI_SIGN_RSA:
    case ATOM_SPKI_SIGN_DSS:
      {
	struct simple_buffer buffer;
	struct sexp *e;
	
	simple_buffer_init(&buffer, signature_length, signature_data);

	if (! ( (e = sexp_parse_canonical(&buffer))
		&& parse_eod(&buffer)
		&& decode_rsa_sig_val(e, s, self->size)) )
	  goto fail;

	break;
      }
      
    default:
      fatal("do_rsa_verify: Internal error!\n");
    }
  
  res = rsa_pkcs1_verify(self, length, msg, s);

 fail:
  mpz_clear(s);
  
  return res;
}