예제 #1
0
static void
inf_test_mass_join_browser_notify_status_cb(GObject* object,
        const GParamSpec* pspec,
        gpointer user_data)
{
    InfBrowser* browser;
    InfBrowserStatus status;
    InfBrowserIter iter;

    InfTestMassJoin* massjoin;
    InfTestMassJoiner* joiner;
    GSList* item;

    browser = INF_BROWSER(object);
    massjoin = (InfTestMassJoin*)user_data;
    joiner = NULL;
    for(item = massjoin->joiners; item != NULL; item = item->next)
    {
        joiner = (InfTestMassJoiner*)item->data;
        if(INF_BROWSER(joiner->browser) == browser)
            break;
    }

    g_assert(joiner != NULL);

    g_object_get(G_OBJECT(browser), "status", &status, NULL);
    switch(status)
    {
    case INF_BROWSER_OPENING:
        /* nothing to do */
        break;
    case INF_BROWSER_OPEN:
        fprintf(stdout, "Joiner %s: Connected\n", joiner->username);

        inf_browser_get_root(browser, &iter);

        inf_browser_explore(
            browser,
            &iter,
            inf_test_mass_join_explore_finished_cb,
            joiner
        );

        break;
    case INF_BROWSER_CLOSED:
        fprintf(stdout, "Joiner %s: Disconnected\n", joiner->username);
        massjoin->joiners = g_slist_remove(massjoin->joiners, joiner);
        if(massjoin->joiners == NULL)
            inf_standalone_io_loop_quit(INF_STANDALONE_IO(massjoin->io));
        break;
    default:
        g_assert_not_reached();
        break;
    }
}
static void
infinoted_plugin_manager_walk_directory(
  InfinotedPluginManager* manager,
  const InfBrowserIter* iter,
  InfinotedPluginInstance* instance,
  InfinotedPluginManagerWalkDirectoryFunc func)
{
  /* This function walks the whole directory tree recursively and
   * registers running sessions with the given plugin instance. */
  InfBrowser* browser;
  InfBrowserIter child;
  InfSessionProxy* proxy;

  browser = INF_BROWSER(manager->directory);
  if(inf_browser_is_subdirectory(browser, iter) == TRUE)
  {
    if(inf_browser_get_explored(browser, iter) == TRUE)
    {
      child = *iter;
      inf_browser_get_child(browser, &child);
      do
      {
        infinoted_plugin_manager_walk_directory(manager, &child, instance, func);
      } while(inf_browser_get_next(browser, &child));
    }
  }
  else
  {
    proxy = inf_browser_get_session(browser, iter);
    if(proxy != NULL)
    {
      func(manager, instance, iter, proxy);
    }
  }
}
예제 #3
0
static void
inf_test_mass_join_explore_finished_cb(InfRequest* request,
                                       const InfRequestResult* result,
                                       const GError* error,
                                       gpointer user_data)
{
    InfTestMassJoiner* joiner;
    InfBrowser* browser;
    InfBrowserIter iter;
    const char* name;
    gboolean document_exists;

    joiner = (InfTestMassJoiner*)user_data;
    browser = INF_BROWSER(joiner->browser);
    inf_browser_get_root(browser, &iter);
    if(inf_browser_get_child(browser, &iter) == FALSE)
    {
        fprintf(
            stderr,
            "Joiner %s: Document %s does not exist\n",
            joiner->username,
            joiner->document
        );

        inf_xml_connection_close(infc_browser_get_connection(joiner->browser));
    }

    document_exists = FALSE;

    do
    {
        name = inf_browser_get_node_name(browser, &iter);
        if(strcmp(name, joiner->document) == 0)
        {
            document_exists = TRUE;

            inf_browser_subscribe(
                browser,
                &iter,
                inf_test_mass_join_subscribe_finished_cb,
                joiner
            );

            break;
        }
    } while(inf_browser_get_next(browser, &iter) == TRUE);

    if(!document_exists)
    {
        fprintf(
            stderr,
            "Joiner %s: Document %s does not exist\n",
            joiner->username,
            joiner->document
        );

        inf_xml_connection_close(infc_browser_get_connection(joiner->browser));
    }
}
예제 #4
0
static void
inf_test_mass_join_subscribe_finished_cb(InfRequest* request,
        const InfRequestResult* result,
        const GError* error,
        gpointer user_data)
{
    InfTestMassJoiner* joiner;
    const InfBrowserIter* iter;
    InfSession* session;

    joiner = (InfTestMassJoiner*)user_data;
    inf_request_result_get_subscribe_session(result, NULL, &iter, NULL);

    joiner->session = INFC_SESSION_PROXY(
                          inf_browser_get_session(
                              INF_BROWSER(joiner->browser),
                              iter
                          )
                      );

    g_assert(joiner->session != NULL);

    g_object_get(G_OBJECT(joiner->session), "session", &session, NULL);
    switch(inf_session_get_status(session))
    {
    case INF_SESSION_PRESYNC:
    case INF_SESSION_SYNCHRONIZING:
        g_signal_connect_after(
            G_OBJECT(session),
            "synchronization-failed",
            G_CALLBACK(inf_test_mass_join_session_synchronization_failed_cb),
            joiner
        );

        g_signal_connect_after(
            G_OBJECT(session),
            "synchronization-complete",
            G_CALLBACK(inf_test_mass_join_session_synchronization_complete_cb),
            joiner
        );

        break;
    case INF_SESSION_RUNNING:
        inf_test_mass_join_join_user(joiner);
        break;
    case INF_SESSION_CLOSED:
        fprintf(
            stderr,
            "Joiner %s: Session closed after subscription\n",
            joiner->username
        );

        inf_xml_connection_close(infc_browser_get_connection(joiner->browser));
        break;
    }

    g_object_unref(session);
}
static gboolean
infinoted_plugin_document_stream_process_get_document(
  InfinotedPluginDocumentStreamStream* stream,
  const gchar** data,
  gsize* len)
{
  guint16 user_len;
  const gchar* user_name;
  guint16 doc_len;
  const gchar* doc_name;

  /* get size of user name string */
  if(*len < 2) return FALSE;
  user_len = *(guint16*)(*data);
  *data += 2; *len -= 2;

  /* get user name string */
  if(*len < user_len) return FALSE;
  user_name = *data;
  *data += user_len; *len -= user_len;

  /* get size of document string */
  if(*len < 2) return FALSE;
  doc_len = *(guint16*)(*data);
  *data += 2; *len -= 2;

  /* get document string */
  if(*len < doc_len) return FALSE;
  doc_name = *data;
  *data += doc_len; *len -= doc_len;

  /* quit connection if we already have a buffer */
  if(stream->buffer != NULL)
  {
    infinoted_plugin_document_stream_send_error(
      stream,
      "Stream is already open"
    );
  }
  else
  {
    stream->username = g_strndup(user_name, user_len);

    stream->navigate_handle = infinoted_plugin_util_navigate_to(
      INF_BROWSER(
        infinoted_plugin_manager_get_directory(stream->plugin->manager)
      ),
      doc_name,
      doc_len,
      FALSE,
      infinoted_plugin_document_stream_navigate_func,
      stream
    );
  }

  return TRUE;
}
예제 #6
0
ExploreRequest* BrowserIter::explore()
{
    if( m_infBrowser ) {
        InfRequest* req = inf_browser_get_pending_request(
                              INF_BROWSER(m_infBrowser),
                              &m_infBrowserIter,
                              "explore-node"
                          );
        if ( req ) {
            return ExploreRequest::wrap(req, 0, false);
        }
        else {
            return ExploreRequest::wrap( inf_browser_explore(
                                             INF_BROWSER(m_infBrowser), &m_infBrowserIter, 0, 0
                                         ) );
        }
    }
    return 0;
}
예제 #7
0
ExploreRequest* BrowserIter::exploreRequest() const
{
    if( m_infBrowser ) {
        InfRequest* req = inf_browser_get_pending_request(
                              INF_BROWSER(m_infBrowser),
                              &m_infBrowserIter,
                              "explore-node"
                          );
        return ExploreRequest::wrap(req, 0, false);
    }
    return 0;
}
static void
infinoted_plugin_manager_unload_plugin(InfinotedPluginManager* manager,
                                       InfinotedPluginInstance* instance)
{
  InfinotedPluginManagerPrivate* priv;
  InfinotedPluginManagerForeachConnectionData data;
  InfBrowserIter root;

  priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager);
  priv->plugins = g_slist_remove(priv->plugins, instance);

  /* Unregister all sessions with the plugin */
  inf_browser_get_root(INF_BROWSER(priv->directory), &root);
  infinoted_plugin_manager_walk_directory(
    manager,
    &root,
    instance,
    infinoted_plugin_manager_remove_session
  );

  /* Unregister all connections with the plugin */
  data.manager = manager;
  data.instance = instance;
  infd_directory_foreach_connection(
    priv->directory,
    infinoted_plugin_manager_unload_plugin_foreach_connection_func,
    &data
  );

  if(instance->plugin->on_deinitialize != NULL)
    instance->plugin->on_deinitialize(instance+1);

  infinoted_log_info(
    priv->log,
    _("Unloaded plugin \"%s\" from \"%s\""),
    instance->plugin->name,
    g_module_name(instance->module)
  );

  g_module_close(instance->module);
  g_free(instance);
}
예제 #9
0
static void
infinoted_plugin_record_session_added(const InfBrowserIter* iter,
                                      InfSessionProxy* proxy,
                                      gpointer plugin_info,
                                      gpointer session_info)
{
  InfinotedPluginRecord* plugin;
  InfinotedPluginRecordSessionInfo* info;
  InfSession* session;
  gchar* title;
  gchar* pos;
  InfAdoptedSessionRecord* record;

  plugin = (InfinotedPluginRecord*)plugin_info;
  info = (InfinotedPluginRecordSessionInfo*)session_info;

  g_object_get(G_OBJECT(proxy), "session", &session, NULL);
  g_assert(INF_ADOPTED_IS_SESSION(session));

  title = inf_browser_get_path(
    INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)),
    iter
  );

  for(pos = title + 1; *pos != '\0'; ++pos)
    if(*pos == '/')
      *pos = '_';

  info->plugin = plugin;
  info->record = infinoted_plugin_record_start(
    plugin,
    INF_ADOPTED_SESSION(session),
    title + 1
  );

  g_object_set_data(G_OBJECT(session), "infinoted-record", info->record);

  g_object_unref(session);
  g_free(title);
}
예제 #10
0
bool BrowserIter::parent()
{
    if( m_infBrowser )
        return inf_browser_get_parent( INF_BROWSER(m_infBrowser), &m_infBrowserIter ) != 0;
    return 0;
}
예제 #11
0
bool BrowserIter::child()
{
    if( m_infBrowser )
        return inf_browser_get_child( INF_BROWSER(m_infBrowser), &m_infBrowserIter ) != 0;
    return 0;
}
예제 #12
0
BrowserIter::BrowserIter( const Browser &browser )
    : m_infBrowser( INFC_BROWSER(browser.gobject()) )
{
    Q_ASSERT(browser.connectionStatus() == INF_BROWSER_OPEN);
    inf_browser_get_root(INF_BROWSER(m_infBrowser), &m_infBrowserIter);
}
예제 #13
0
QString BrowserIter::noteType()
{
    if( m_infBrowser )
        return inf_browser_get_node_type( INF_BROWSER(m_infBrowser), &m_infBrowserIter );
    return "";
}
예제 #14
0
QString BrowserIter::path() const
{
    if( m_infBrowser )
        return inf_browser_get_path( INF_BROWSER(m_infBrowser), &m_infBrowserIter );
    return "";
}
예제 #15
0
QString BrowserIter::name() const
{
    if( m_infBrowser )
        return inf_browser_get_node_name( INF_BROWSER(m_infBrowser), &m_infBrowserIter );
    return "";
}
static void
infinoted_plugin_certificate_auth_deinitialize(gpointer plugin_info)
{
  InfinotedPluginCertificateAuth* plugin;
  InfRequest* remove_acl_account_request;
  InfCertificateCredentials* creds;
  guint i;

  plugin = (InfinotedPluginCertificateAuth*)plugin_info;

  /* Remove super user account. Note that this is not strictly necessary,
   * since the acocunt is transient and therefore is not written to disk,
   * so will not be re-created at the next server start. However, to be sure,
   * we explicitly remove the account at this point. */
  if(plugin->super_id != 0)
  {
    remove_acl_account_request = inf_browser_remove_acl_account(
      INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)),
      plugin->super_id,
      infinoted_plugin_certificate_auth_remove_acl_account_cb,
      plugin
    );

    /* This should be instantaneous: if we are not called back within the call
     * to inf_browser_remove_acl_account(), then we don't care about the
     * result, since we are being deinitialized. */
    if(remove_acl_account_request != NULL)
    {
      inf_signal_handlers_disconnect_by_func(
        plugin->set_acl_request,
        G_CALLBACK(infinoted_plugin_certificate_auth_remove_acl_account_cb),
        plugin
      );
    }
  }

  if(plugin->set_acl_request != NULL)
  {
    inf_signal_handlers_disconnect_by_func(
      plugin->set_acl_request,
      G_CALLBACK(infinoted_plugin_certificate_auth_set_acl_cb),
      plugin
    );

    g_object_unref(plugin->set_acl_request);
  }

  creds = infinoted_plugin_manager_get_credentials(plugin->manager);
  if(creds != NULL)
    gnutls_certificate_free_cas(inf_certificate_credentials_get(creds));

  infd_directory_set_certificate(
    infinoted_plugin_manager_get_directory(plugin->manager),
    NULL,
    NULL
  );

  /* If we have a ca_key set, the certificate that belongs to the key had
   * its ownership transferred to the directory, so make sure not to free
   * it twice here. */
  for(i = 0; i < plugin->n_cas; ++i)
    if(plugin->ca_key == NULL || i != plugin->ca_key_index)
      gnutls_x509_crt_deinit(plugin->cas[i]);
  g_free(plugin->cas);

  if(plugin->ca_key != NULL)
    gnutls_x509_privkey_deinit(plugin->ca_key);

  g_free(plugin->ca_list_file);
  g_free(plugin->ca_key_file);
  g_free(plugin->super_user);
}
static void
infinoted_plugin_dbus_main_invocation(gpointer user_data)
{
  /* Main thread invocation handler */
  InfinotedPluginDbusInvocation* invocation;
  const gchar* path;
  gsize len;
  InfinotedPluginUtilNavigateData* navigate;

  invocation = (InfinotedPluginDbusInvocation*)user_data;
  invocation->plugin->invocations =
    g_slist_prepend(invocation->plugin->invocations, invocation);
  g_atomic_int_inc(&invocation->ref_count);

  /* These commands take a path as the first parameter and do not
   * require that path to be explored. */
  if(strcmp(invocation->method_name, "remove_node") == 0 ||
     strcmp(invocation->method_name, "query_acl") == 0 ||
     strcmp(invocation->method_name, "set_acl") == 0 ||
     strcmp(invocation->method_name, "check_acl") == 0)
  {
    path = g_variant_get_string(
      g_variant_get_child_value(invocation->parameters, 0),
      &len
    );

    navigate = infinoted_plugin_util_navigate_to(
      INF_BROWSER(infinoted_plugin_manager_get_directory(invocation->plugin->manager)),
      path,
      len,
      FALSE,
      infinoted_plugin_dbus_navigate_done,
      invocation
    );
    
    if(navigate != NULL)
      invocation->navigate = navigate;
  }
  /* These commands take a path as the first parameter and DO require that
   * path to be explored. */
  else if(strcmp(invocation->method_name, "explore_node") == 0 ||
          strcmp(invocation->method_name, "add_node") == 0)
  {
    path = g_variant_get_string(
      g_variant_get_child_value(invocation->parameters, 0),
      &len
    );

    navigate = infinoted_plugin_util_navigate_to(
      INF_BROWSER(infinoted_plugin_manager_get_directory(invocation->plugin->manager)),
      path,
      len,
      TRUE,
      infinoted_plugin_dbus_navigate_done,
      invocation
    );
    
    if(navigate != NULL)
      invocation->navigate = navigate;
  }
  else
  {
    g_dbus_method_invocation_return_error_literal(
      invocation->invocation,
      G_DBUS_ERROR,
      G_DBUS_ERROR_UNKNOWN_METHOD,
      "Not implemented"
    );

    infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation);
  }
}
static void
inf_test_certificate_request_notify_status_cb(GObject* object,
                                              GParamSpec* pspec,
                                              gpointer user_data)
{
  InfTestCertificateRequest* test;
  InfBrowserStatus status;
  gnutls_x509_crq_t crq;
  InfRequest* request;
  GError* error;
  int res;

  test = (InfTestCertificateRequest*)user_data;
  g_object_get(G_OBJECT(test->browser), "status", &status, NULL);

  if(status == INF_BROWSER_OPEN)
  {
    fprintf(stderr, "Connection established, creating key... (4096 bit)\n");

    /* TODO: Some error checking here */
    gnutls_x509_privkey_init(&test->key);
    gnutls_x509_privkey_generate(test->key, GNUTLS_PK_RSA, 4096, 0);

    fprintf(stderr, "Done, sending the certificate request\n");

    gnutls_x509_crq_init(&crq);

    gnutls_x509_crq_set_key(crq, test->key);
    gnutls_x509_crq_set_key_usage(crq, GNUTLS_KEY_DIGITAL_SIGNATURE);
    gnutls_x509_crq_set_version(crq, 3);

    gnutls_x509_crq_set_dn_by_oid(
      crq,
      GNUTLS_OID_X520_COMMON_NAME,
      0,
      "Armin Burgmeier",
      strlen("Armin Burgmeier")
    );

    /* TODO: gnutls_x509_crq_sign2 is deprecated in favour of
     * gnutls_x509_crq_privkey_sign, but the latter returns the error code
     * GNUTLS_E_UNIMPLEMENTED_FEATURE, so we keep using the deprecated
     * version here. */
    /*gnutls_x509_crq_privkey_sign(crq, key, GNUTLS_DIG_SHA1, 0);*/
    gnutls_x509_crq_sign2(crq, test->key, GNUTLS_DIG_SHA1, 0);

    error = NULL;
    request = inf_browser_create_acl_account(
      INF_BROWSER(object),
      crq,
      inf_test_certificate_request_finished_cb,
      test
    );

    gnutls_x509_crq_deinit(crq);
  }

  if(status == INF_BROWSER_CLOSED)
  {
    if(inf_standalone_io_loop_running(test->io))
      inf_standalone_io_loop_quit(test->io);
  }
}
예제 #19
0
int
main(int argc, char* argv[])
{
  InfTestBrowser test;
  InfIpAddress* address;
  InfCommunicationManager* manager;
  InfTcpConnection* tcp_conn;
  GError* error;

  gnutls_global_init();
  g_type_init();

  test.io = inf_standalone_io_new();
#ifndef G_OS_WIN32
  test.input_fd = STDIN_FILENO;
#endif
  address = inf_ip_address_new_loopback4();

  error = NULL;
  tcp_conn =
    inf_tcp_connection_new_and_open(INF_IO(test.io), address, inf_protocol_get_default_port(), &error);

  inf_ip_address_free(address);

  if(tcp_conn == NULL)
  {
    fprintf(stderr, "Could not open TCP connection: %s\n", error->message);
    g_error_free(error);
  }
  else
  {
    test.conn = inf_xmpp_connection_new(
      tcp_conn,
      INF_XMPP_CONNECTION_CLIENT,
      NULL,
      "localhost",
      INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS,
      NULL,
      NULL,
      NULL
    );

    g_object_unref(G_OBJECT(tcp_conn));

    manager = inf_communication_manager_new();
    test.browser = INF_BROWSER(
      infc_browser_new(
        INF_IO(test.io),
        manager,
        INF_XML_CONNECTION(test.conn)
      )
    );

    g_signal_connect_after(
      G_OBJECT(test.browser),
      "notify::status",
      G_CALLBACK(inf_test_browser_notify_status_cb),
      &test
    );

    g_signal_connect(
      G_OBJECT(test.browser),
      "error",
      G_CALLBACK(inf_test_browser_error_cb),
      &test
    );

    inf_standalone_io_loop(test.io);
    g_object_unref(G_OBJECT(manager));
    g_object_unref(G_OBJECT(test.browser));

    /* TODO: Wait until the XMPP connection is in status closed */
    g_object_unref(G_OBJECT(test.conn));
  }

  g_object_unref(G_OBJECT(test.io));
  return 0;
}
static gboolean
infinoted_plugin_certificate_auth_initialize(InfinotedPluginManager* manager,
                                             gpointer plugin_info,
                                             GError** error)
{
  InfinotedPluginCertificateAuth* plugin;
  InfCertificateCredentials* creds;
  GPtrArray* read_certs;
  int res;
  guint i;

  gnutls_x509_crt_t* sign_certs;
  InfCertificateChain* sign_chain;

  gnutls_x509_privkey_t super_key;
  InfCertUtilDescription desc;
  gnutls_x509_crt_t super_cert;
  InfAclAccountId super_id;
  gnutls_x509_crt_t chain[2];
  gboolean written;

  InfdDirectory* directory;
  InfBrowserIter iter;
  InfAclSheetSet sheet_set;
  InfAclSheet sheet;
  InfRequest* request;

  plugin = (InfinotedPluginCertificateAuth*)plugin_info;
  plugin->manager = manager;

  creds = infinoted_plugin_manager_get_credentials(manager);
  if(creds == NULL)
  {
    g_set_error(
      error,
      infinoted_plugin_certificate_auth_error_quark(),
      INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CREDENTIALS,
      "%s",
      _("The certificate-auth plugin can only be used when TLS is enabled "
        "and a server certificate has been set.")
    );

    return FALSE;
  }

  read_certs =
    inf_cert_util_read_certificate(plugin->ca_list_file, NULL, error);
  if(read_certs == NULL) return FALSE;

  if(read_certs->len == 0)
  {
    g_set_error(
      error,
      infinoted_plugin_certificate_auth_error_quark(),
      INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CAS,
      _("File \"%s\" does not contain any CA certificates"),
      plugin->ca_list_file
    );

    g_ptr_array_free(read_certs, TRUE);
    return FALSE;
  }

  plugin->n_cas = read_certs->len;
  plugin->cas = (gnutls_x509_crt_t*)g_ptr_array_free(read_certs, FALSE);

  res = gnutls_certificate_set_x509_trust(
    inf_certificate_credentials_get(creds),
    plugin->cas,
    plugin->n_cas
  );

  if(res < 0)
  {
    inf_gnutls_set_error(error, res);
    return FALSE;
  }

  if(plugin->ca_key_file != NULL)
  {
    plugin->ca_key =
      inf_cert_util_read_private_key(plugin->ca_key_file, error);
    if(plugin->ca_key == NULL)
      return FALSE;

    /* Walk through certificates and find the certificate that the key
     * belongs to. */
    for(i = 0; i < plugin->n_cas; ++i)
      if(inf_cert_util_check_certificate_key(plugin->cas[i], plugin->ca_key))
        break;

    if(i == plugin->n_cas)
    {
      gnutls_x509_privkey_deinit(plugin->ca_key);
      plugin->ca_key = NULL;

      g_set_error(
        error,
        infinoted_plugin_certificate_auth_error_quark(),
        INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_FOR_KEY,
        "%s",
        _("The given CA key does not match with any of the CA certificates")
      );

      return FALSE;
    }

    plugin->ca_key_index = i;

    /* Set the signing certificate of the directory, so that it can handle
     * account creation requests. Note that this takes ownership of the
     * certificate, so we take special care in the cleanup code in
     * infinoted_plugin_certificate_auth_deinitialize(). */
    sign_certs = g_malloc(sizeof(gnutls_x509_crt_t));
    sign_certs[0] = plugin->cas[plugin->ca_key_index];
    sign_chain = inf_certificate_chain_new(sign_certs, 1);

    infd_directory_set_certificate(
      infinoted_plugin_manager_get_directory(plugin->manager),
      plugin->ca_key,
      sign_chain
    );

    inf_certificate_chain_unref(sign_chain);
  }

  if(plugin->super_user != NULL)
  {
    if(plugin->ca_key == NULL)
    {
      g_set_error(
        error,
        infinoted_plugin_certificate_auth_error_quark(),
        INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_KEY,
        "%s",
        _("Cannot generate a superuser certificate without CA key")
      );

      return FALSE;
    }

    /* Create a private key and certificate for the super user. */
    infinoted_log_info(
      infinoted_plugin_manager_get_log(plugin->manager),
      _("Creating 4096-bit RSA private key for the super user account...")
    );

    super_key =
      inf_cert_util_create_private_key(GNUTLS_PK_RSA, 4096, error);
    if(super_key == NULL)
      return FALSE;

    desc.validity = 12 * 3600; /* 12 hours */
    desc.dn_common_name = "Super User";
    desc.san_dnsname = NULL;

    super_cert = inf_cert_util_create_signed_certificate(
      super_key,
      &desc,
      plugin->cas[plugin->ca_key_index],
      plugin->ca_key,
      error
    );

    if(super_cert == NULL)
    {
      gnutls_x509_privkey_deinit(super_key);
      return FALSE;
    }

    super_id = infd_directory_create_acl_account(
      infinoted_plugin_manager_get_directory(plugin->manager),
      _("Super User"),
      TRUE, /* transient */
      &super_cert,
      1,
      error
    );

    if(super_id == 0)
    {
      gnutls_x509_crt_deinit(super_cert);
      gnutls_x509_privkey_deinit(super_key);
      return FALSE;
    }

    plugin->super_id = super_id;

    chain[0] = super_cert;
    chain[1] = plugin->cas[plugin->ca_key_index];

    written = inf_cert_util_write_certificate_with_key(
      super_key,
      chain,
      2,
      plugin->super_user,
      error
    );

    gnutls_x509_crt_deinit(super_cert);
    gnutls_x509_privkey_deinit(super_key);

    if(written == FALSE)
      return FALSE;

    inf_browser_get_root(
      INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)),
      &iter
    );

    directory = infinoted_plugin_manager_get_directory(plugin->manager);

    sheet.account = super_id;
    sheet.mask = INF_ACL_MASK_ALL;
    infd_directory_get_support_mask(directory, &sheet.perms);
    sheet_set.n_sheets = 1;
    sheet_set.own_sheets = NULL;
    sheet_set.sheets = &sheet;

    request = inf_browser_set_acl(
      INF_BROWSER(directory),
      &iter,
      &sheet_set,
      infinoted_plugin_certificate_auth_set_acl_cb,
      plugin
    );

    if(request != NULL)
    {
      plugin->set_acl_request = request;
      g_object_ref(plugin->set_acl_request);
    }
  }

  return TRUE;
}
예제 #21
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);
}
예제 #22
0
bool BrowserIter::isDirectory()
{
    if( m_infBrowser )
        return inf_browser_is_subdirectory( INF_BROWSER(m_infBrowser), &m_infBrowserIter ) != 0;
    return 0;
}
예제 #23
0
bool BrowserIter::isExplored()
{
    if( m_infBrowser )
        return inf_browser_get_explored( INF_BROWSER(m_infBrowser), &m_infBrowserIter ) != 0;
    return 0;
}
static gboolean
infinoted_plugin_manager_load_plugin(InfinotedPluginManager* manager,
                                     const gchar* plugin_path,
                                     const gchar* plugin_name,
                                     GKeyFile* key_file,
                                     GError** error)
{
  gchar* plugin_basename;
  gchar* plugin_filename;

  GModule* module;
  const InfinotedPlugin* plugin;
  InfinotedPluginInstance* instance;

  gboolean result;
  GError* local_error;

  InfBrowserIter root;
  InfinotedPluginManagerForeachConnectionData data;

  plugin_basename = g_strdup_printf(
    "libinfinoted-plugin-%s.%s",
    plugin_name,
    G_MODULE_SUFFIX
  );

  plugin_filename = g_build_filename(plugin_path, plugin_basename, NULL);
  g_free(plugin_basename);

  module = g_module_open(plugin_filename, G_MODULE_BIND_LOCAL);
  g_free(plugin_filename);

  if(module == NULL)
  {
    g_set_error(
      error,
      infinoted_plugin_manager_error_quark(),
      INFINOTED_PLUGIN_MANAGER_ERROR_OPEN_FAILED,
      "%s",
      g_module_error()
    );

    
    return FALSE;
  }

  if(g_module_symbol(module, "INFINOTED_PLUGIN", (gpointer*)&plugin) == FALSE)
  {
    g_set_error(
      error,
      infinoted_plugin_manager_error_quark(),
      INFINOTED_PLUGIN_MANAGER_ERROR_NO_ENTRY_POINT,
      "%s",
      g_module_error()
    );
    
    g_module_close(module);
    return FALSE;
  }

  instance = g_malloc(sizeof(InfinotedPluginInstance) + plugin->info_size);
  instance->module = module;
  instance->plugin = plugin;

  /* Call on_info_initialize, allowing the plugin to set default values */
  if(plugin->on_info_initialize != NULL)
    plugin->on_info_initialize(instance+1);

  /* Next, parse options from keyfile */
  if(plugin->options != NULL)
  {
    local_error = NULL;

    result = infinoted_parameter_load_from_key_file(
      plugin->options,
      key_file,
      plugin->name,
      instance+1,
      &local_error
    );
    
    if(result == FALSE)
    {
      g_free(instance);
      g_module_close(module);

      g_propagate_prefixed_error(
        error,
        local_error,
        "Failed to initialize plugin \"%s\": ",
        plugin_name
      );

      return FALSE;
    }
  }

  /* Finally, call on_initialize, which allows the plugin to initialize
   * itself with the plugin options. */
  if(plugin->on_initialize != NULL)
  {
    local_error = NULL;

    result = plugin->on_initialize(manager, instance+1, &local_error);

    if(local_error != NULL)
    {
      if(instance->plugin->on_deinitialize != NULL)
        instance->plugin->on_deinitialize(instance+1);

      g_free(instance);
      g_module_close(module);

      g_propagate_prefixed_error(
        error,
        local_error,
        "Failed to initialize plugin \"%s\": ",
        plugin_name
      );

      return FALSE;
    }
  }

  /* Register initial connections with plugin */
  data.manager = manager;
  data.instance = instance;
  infd_directory_foreach_connection(
    manager->directory,
    infinoted_plugin_manager_load_plugin_foreach_connection_func,
    &data
  );

  /* Register initial sessions with plugin */
  inf_browser_get_root(INF_BROWSER(manager->directory), &root);
  infinoted_plugin_manager_walk_directory(
    manager,
    &root,
    instance,
    infinoted_plugin_manager_add_session
  );

  infinoted_log_info(
    manager->log,
    _("Loaded plugin \"%s\" from \"%s\""),
    plugin_name,
    g_module_name(module)
  );

  manager->plugins = g_slist_prepend(manager->plugins, instance);

  return TRUE;
}
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;
}