static void
infinoted_plugin_manager_socket_accept_func(InfNativeSocket* socket,
                                            InfIoEvent event,
                                            gpointer user_data)
{
  InfinotedPluginDocumentStream* plugin;
  int val;
  int errval;
  socklen_t len;
  InfNativeSocket new_socket;
  GError* error;

  plugin = (InfinotedPluginDocumentStream*)user_data;

  if(event & INF_IO_ERROR)
  {
    len = sizeof(errval);
    val = getsockopt(*socket, SOL_SOCKET, SO_ERROR, &errval, &len);
    if(val == -1)
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(plugin->manager),
        "Failed to obtain error from socket: %s",
        strerror(errno)
      );
    }
    else
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(plugin->manager),
        "Document streaming server error: %s",
        strerror(errval)
      );
    }
  }
  else if(event & INF_IO_INCOMING)
  {
    error = NULL;

    new_socket = infinoted_plugin_document_stream_accept_socket(
      *socket,
      &error
    );

    if(error != NULL)
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(plugin->manager),
        "Failed to accept new stream: %s",
        error->message
      );

      g_error_free(error);
    }
    else
    {
      infinoted_plugin_document_stream_add_stream(plugin, new_socket);
    }
  }
}
static void
infinoted_plugin_linekeeper_user_join_cb(InfRequest* request,
                                         const InfRequestResult* result,
                                         const GError* error,
                                         gpointer user_data)
{
  InfinotedPluginLinekeeperSessionInfo* info;
  InfUser* user;

  info = (InfinotedPluginLinekeeperSessionInfo*)user_data;

  info->request = NULL;

  if(error != NULL)
  {
    infinoted_log_warning(
      infinoted_plugin_manager_get_log(info->plugin->manager),
      _("Could not join LineKeeper user for document: %s\n"),
      error->message
    );
  }
  else
  {
    inf_request_result_get_join_user(result, NULL, &user);

    info->user = user;
    g_object_ref(info->user);

    /* Initial run */
    infinoted_plugin_linekeeper_run(info);

    g_signal_connect(
      G_OBJECT(info->buffer),
      "text-inserted",
      G_CALLBACK(infinoted_plugin_linekeeper_text_inserted_cb),
      info
    );

    g_signal_connect(
      G_OBJECT(info->buffer),
      "text-erased",
      G_CALLBACK(infinoted_plugin_linekeeper_text_erased_cb),
      info
    );

    /* It can happen that while the request is being processed, the situation
     * changes again. */
    if(infinoted_plugin_linekeeper_has_available_users(info) == FALSE)
    {
      infinoted_plugin_linekeeper_remove_user(info);
    }
  }
}
static void
infinoted_plugin_dbus_name_lost_func(GDBusConnection* connection,
                                     const gchar* name,
                                     gpointer user_data)
{
  InfinotedPluginDbus* plugin;
  plugin = (InfinotedPluginDbus*)user_data;

  infinoted_log_warning(
    infinoted_plugin_manager_get_log(plugin->manager),
    "The name \"%s\" could not be acquired on the bus: "
    "d-bus functionality is not available",
    name
  );
}
static void
infinoted_plugin_certificate_auth_set_acl_cb(InfRequest* request,
                                             const InfRequestResult* result,
                                             const GError* error,
                                             gpointer user_data)
{
  InfinotedPluginCertificateAuth* plugin;
  plugin = (InfinotedPluginCertificateAuth*)user_data;

  if(error != NULL)
  {
    infinoted_log_warning(
      infinoted_plugin_manager_get_log(plugin->manager),
      _("Failed to set permissions for super user: %s"),
      error->message
    );
  }
}
static void
infinoted_plugin_certificate_auth_remove_acl_account_cb(
  InfRequest* request,
  const InfRequestResult* result,
  const GError* error,
  gpointer user_data)
{
  InfinotedPluginCertificateAuth* plugin;
  plugin = (InfinotedPluginCertificateAuth*)user_data;

  if(error != NULL)
  {
    infinoted_log_warning(
      infinoted_plugin_manager_get_log(plugin->manager),
      _("Failed to remove super user on server shutdown. This should not be "
        "a problem since the account is not made persistent, however might "
        "point to an inconsistency in the server setup. The error message "
        "was: %s"),
      error->message
    );
  }
}
static gboolean
infinoted_plugin_document_stream_send(
  InfinotedPluginDocumentStreamStream* stream,
  const void* data,
  gsize len)
{
  GError* error;
  gsize sent;

  if(stream->send_queue.len > 0)
  {
    infinoted_plugin_document_stream_queue_append(
      &stream->send_queue,
      data,
      len
    );

    return TRUE;
  }
  else
  {
    error = NULL;
    sent = infinoted_plugin_document_stream_send_direct(
      stream,
      data,
      len,
      &error
    );

    if(error != NULL)
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(stream->plugin->manager),
        "Document stream error: %s",
        error->message
      );

      g_error_free(error);
      return FALSE;
    }
    else
    {
      if(sent < len)
      {
        infinoted_plugin_document_stream_queue_append(
          &stream->send_queue,
          (const gchar*)data + sent,
          len - sent
        );

        inf_io_update_watch(
          infinoted_plugin_manager_get_io(stream->plugin->manager),
          stream->watch,
          INF_IO_INCOMING | INF_IO_OUTGOING
        );
      }

      return TRUE;
    }
  }
}
static void
infinoted_plugin_document_stream_io_func(InfNativeSocket* socket,
                                         InfIoEvent event,
                                         gpointer user_data)
{
  InfinotedPluginDocumentStreamStream* stream;
  InfinotedPluginManager* manager;
  int val;
  int errval;
  socklen_t len;
  GError* error;

  stream = (InfinotedPluginDocumentStreamStream*)user_data;
  manager = stream->plugin->manager;

  if(event & INF_IO_ERROR)
  {
    len = sizeof(errval);
    val = getsockopt(*socket, SOL_SOCKET, SO_ERROR, &errval, &len);
    if(val == -1)
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(manager),
        "Failed to obtain error from socket: %s",
        strerror(errno)
      );
    }
    else
    {
      if(errval == 0)
      {
        /* Connection closed */
        infinoted_plugin_document_stream_close_stream(stream);
      }
      else
      {
        infinoted_log_warning(
          infinoted_plugin_manager_get_log(manager),
          "Document stream error: %s",
          strerror(errval)
        );
      }
    }
  }
  else if(event & INF_IO_INCOMING)
  {
    error = NULL;
    if(!infinoted_plugin_document_stream_io_in(stream, &error))
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(manager),
        "Document stream error: %s",
        error->message
      );

      g_error_free(error);
    }
  }
  else if(event & INF_IO_OUTGOING)
  {
    error = NULL;
    if(!infinoted_plugin_document_stream_io_out(stream, &error))
    {
      infinoted_log_warning(
        infinoted_plugin_manager_get_log(manager),
        "Document stream error: %s",
        error->message
      );

      g_error_free(error);
    }
  }
}
Пример #8
0
static void
infinoted_plugin_autosave_save(InfinotedPluginAutosaveSessionInfo* info)
{
  InfdDirectory* directory;
  InfBrowserIter* iter;
  GError* error;
  gchar* path;
  InfSession* session;
  InfBuffer* buffer;
  gchar* root_directory;
  gchar* argv[4];

  directory = infinoted_plugin_manager_get_directory(info->plugin->manager);
  iter = &info->iter;
  error = NULL;

  if(info->timeout != NULL)
  {
    inf_io_remove_timeout(infd_directory_get_io(directory), info->timeout);
    info->timeout = NULL;
  }

  g_object_get(G_OBJECT(info->proxy), "session", &session, NULL);
  buffer = inf_session_get_buffer(session);

  inf_signal_handlers_block_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  if(infd_directory_iter_save_session(directory, iter, &error) == FALSE)
  {
    path = inf_browser_get_path(INF_BROWSER(directory), iter);

    infinoted_log_warning(
      infinoted_plugin_manager_get_log(info->plugin->manager),
      _("Failed to auto-save session \"%s\": %s\n\n"
        "Will retry in %u seconds."),
      path,
      error->message,
      info->plugin->interval
    );

    g_free(path);
    g_error_free(error);
    error = NULL;

    infinoted_plugin_autosave_start(info);
  }
  else
  {
    /* TODO: Remove this as soon as directory itself unsets modified flag
     * on session_write */
    inf_buffer_set_modified(INF_BUFFER(buffer), FALSE);

    if(info->plugin->hook != NULL)
    {
      path = inf_browser_get_path(INF_BROWSER(directory), iter);

      g_object_get(
        G_OBJECT(infd_directory_get_storage(directory)),
        "root-directory",
        &root_directory,
        NULL
      );

      argv[0] = info->plugin->hook;
      argv[1] = root_directory;
      argv[2] = path;
      argv[3] = NULL;

      if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
                        NULL, NULL, NULL, &error))
      {
        infinoted_log_warning(
          infinoted_plugin_manager_get_log(info->plugin->manager),
          _("Could not execute autosave hook: \"%s\""),
          error->message
        );

        g_error_free(error);
        error = NULL;
      }

      g_free(path);
      g_free(root_directory);
    }
  }
  
  inf_signal_handlers_unblock_by_func(
    G_OBJECT(buffer),
    G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb),
    info
  );

  g_object_unref(session);
}
Пример #9
0
static void
infinoted_startup_sasl_callback(InfSaslContextSession* session,
                                Gsasl_property prop,
                                gpointer session_data,
                                gpointer user_data)
{
  InfinotedStartup* startup;
  const char* username;
  const char* password;
  InfXmppConnection* xmpp;
  gchar cmp;
  gsize password_len;
  gsize i;

#ifdef LIBINFINITY_HAVE_PAM
  const gchar* pam_service;
  GError* error;
#endif
  gchar* remote_id;

  xmpp = INF_XMPP_CONNECTION(session_data);
  g_object_get(xmpp, "remote-id", &remote_id, NULL);

  switch(prop)
  {
  case GSASL_VALIDATE_SIMPLE:
    startup = (InfinotedStartup*)user_data;
    username = inf_sasl_context_session_get_property(session, GSASL_AUTHID);
    password = inf_sasl_context_session_get_property(session, GSASL_PASSWORD);
#ifdef LIBINFINITY_HAVE_PAM
    pam_service = startup->options->pam_service;
    if(pam_service != NULL)
    {
      error = NULL;
      if(!infinoted_pam_authenticate(pam_service, username, password))
      {
        infinoted_log_warning(
          startup->log,
          _("User %s failed to log in from %s: PAM authentication failed"),
          username,
          remote_id
        );

        infinoted_startup_sasl_callback_set_error(
          xmpp,
          INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED,
          NULL
        );

        inf_sasl_context_session_continue(
          session,
          GSASL_AUTHENTICATION_ERROR
        );
      }
      else if(!infinoted_pam_user_is_allowed(startup, username, &error))
      {
        infinoted_log_warning(
          startup->log,
          _("User %s failed to log in from %s: PAM user not allowed"),
          username,
          remote_id
        );

        infinoted_startup_sasl_callback_set_error(
          xmpp,
          INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED,
          error
        );

        inf_sasl_context_session_continue(
          session,
          GSASL_AUTHENTICATION_ERROR
        );
      }
      else
      {
        infinoted_log_info(
          startup->log,
          _("User %s logged in from %s via PAM"),
          username,
          remote_id
        );

        inf_sasl_context_session_continue(session, GSASL_OK);
      }
    }
    else
#endif /* LIBINFINITY_HAVE_PAM */
    {
      g_assert(startup->options->password != NULL);

      /* length-independent string compare */
      cmp = 0;
      password_len = strlen(password);
      for(i = 0; i < startup->options->password_len; ++i)
      {
        if(i < password_len)
          cmp |= (startup->options->password[i] ^ password[i]);
        else
          cmp |= (startup->options->password[i] ^ 0x00);
      }

      if(startup->options->password_len != password_len)
        cmp |= 0xFF;

      if(cmp == 0)
      {
        infinoted_log_info(
          startup->log,
          _("User %s logged in from %s via password"),
          username,
          remote_id
        );

        inf_sasl_context_session_continue(session, GSASL_OK);
      }
      else
      {
        infinoted_log_warning(
          startup->log,
          _("User %s failed to log in from %s: wrong password"),
          username,
          remote_id
        );

        infinoted_startup_sasl_callback_set_error(
          xmpp,
          INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED,
          NULL
        );

        inf_sasl_context_session_continue(
          session,
          GSASL_AUTHENTICATION_ERROR
        );
      }
    }

    break;
  default:
    inf_sasl_context_session_continue(session, GSASL_AUTHENTICATION_ERROR);
    break;
  }

  g_free(remote_id);
}
Пример #10
0
static InfAdoptedSessionRecord*
infinoted_plugin_record_start(InfinotedPluginRecord* plugin,
                              InfAdoptedSession* session,
                              const gchar* title)
{
  gchar* dirname;
  gchar* basename;
  gchar* filename;
  guint i;
  gsize pos;
  InfAdoptedSessionRecord* record;
  GError* error;

  basename = g_build_filename(g_get_home_dir(), ".infinoted-records", title, NULL);
  pos = strlen(basename) + 8;
  filename = g_strdup_printf("%s.record-00000.xml", basename);
  g_free(basename);

  i = 0;
  while(g_file_test(filename, G_FILE_TEST_EXISTS) && ++i < 100000)
    g_snprintf(filename + pos, 10, "%05u.xml", i);

  record = NULL;
  if(i >= 100000)
  {
    dirname = g_path_get_dirname(filename);

    infinoted_log_warning(
      infinoted_plugin_manager_get_log(plugin->manager),
      _("Could not create record file for session \"%s\": Could not generate "
        "unused record file in directory \"%s\""),
      title,
      dirname
    );

    g_free(dirname);
  }
  else
  {
    error = NULL;
    if(!infinoted_util_create_dirname(filename, &error))
    {
      dirname = g_path_get_dirname(filename);

      infinoted_log_warning(
        infinoted_plugin_manager_get_log(plugin->manager),
        _("Could not create directory \"%s\": %s"),
        filename,
        error->message
      );

      g_error_free(error);
      g_free(dirname);
    }
    else
    {
      record = inf_adopted_session_record_new(session);
      inf_adopted_session_record_start_recording(record, filename, &error);
      if(error != NULL)
      {
        infinoted_log_warning(
          infinoted_plugin_manager_get_log(plugin->manager),
          _("Error while writing record for session \"%s\" into \"%s\": %s"),
          title,
          filename,
          error->message
        );

        g_error_free(error);
        g_object_unref(record);
        record = NULL;
      }
    }
  }

  g_free(filename);
  return record;
}
static gboolean
infinoted_plugin_transformation_protection_check_request_cb(InfAdoptedSession* session,
                                                            InfAdoptedRequest* request,
                                                            InfAdoptedUser* user,
                                                            gpointer user_data)
{
  InfinotedPluginTransformationProtectionSessionInfo* info;
  guint vdiff;
  InfXmlConnection* connection;
  gchar* request_str;
  gchar* current_str;
  gchar* remote_id;
  gchar* path;

  info = (InfinotedPluginTransformationProtectionSessionInfo*)user_data;

  vdiff = inf_adopted_state_vector_vdiff(
    inf_adopted_request_get_vector(request),
    inf_adopted_algorithm_get_current(
      inf_adopted_session_get_algorithm(session)
    )
  );

  if(vdiff > info->plugin->max_vdiff)
  {
    connection = inf_user_get_connection(INF_USER(user));

    /* Local requests do not need to be transformed, so always have a
     * zero vdiff. */
    g_assert(connection != NULL);

    /* Kill the connection */
    infd_session_proxy_unsubscribe(
      INFD_SESSION_PROXY(info->proxy),
      connection
    );

    /* Write a log message */
    path = inf_browser_get_path(
      INF_BROWSER(
        infinoted_plugin_manager_get_directory(info->plugin->manager)
      ),
      &info->iter
    );

    request_str = inf_adopted_state_vector_to_string(
      inf_adopted_request_get_vector(request)
    );

    current_str = inf_adopted_state_vector_to_string(
      inf_adopted_algorithm_get_current(
        inf_adopted_session_get_algorithm(session)
      )
    );

    g_object_get(G_OBJECT(connection), "remote-id", &remote_id, NULL);

    infinoted_log_warning(
      infinoted_plugin_manager_get_log(info->plugin->manager),
      _("In document \"%s\": Attempt to transform request \"%s\" to current state \"%s\" "
        "(vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the "
        "connection has been unsubscribed."),
      path,
      request_str,
      current_str,
      vdiff,
      inf_user_get_name(INF_USER(user)),
      inf_user_get_id(INF_USER(user)),
      remote_id,
      info->plugin->max_vdiff
    );

    g_free(path);
    g_free(request_str);
    g_free(current_str);
    g_free(remote_id);

    /* Prevent the request from being transformed */
    return TRUE;
  }

  return FALSE;
}