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); } } }
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); }
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); }
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; }