Commit c4dd3189 authored by Alexander Kanavin's avatar Alexander Kanavin Committed by Alexander Kanavin

Added plugin documentation and examples

parent b83a12bd
......@@ -4,7 +4,7 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src test
SUBDIRS = src examples docs test
valgrind:
cd test; make valgrind
......@@ -3,6 +3,7 @@
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
gtkdocize || exit 1
aclocal #-I m4
autoheader
libtoolize --copy --force
......
......@@ -18,6 +18,9 @@ AM_PROG_AR
LT_PREREQ([2.2])
LT_INIT([disable-static])
#gtk-doc
GTK_DOC_CHECK([1.18],[--flavour no-tmpl])
# Checks for libraries.
PKG_CHECK_MODULES([GSIGNON],
[glib-2.0 >= 2.30
......@@ -51,6 +54,8 @@ AC_SUBST(EXTENSIONSDIR)
AC_OUTPUT([
Makefile
docs/Makefile
src/Makefile
test/Makefile
examples/Makefile
])
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=gsignond-plugin-sasl
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code.
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk
DOC_SOURCE_DIR=$(top_srcdir)/src
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=
CFILE_GLOB=
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES=
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=\
$(GSIGNON_CFLAGS) \
$(LIBSOUP_CFLAGS)
GTKDOC_LIBS=\
$(top_builddir)/src/libsasl.la \
$(GSIGNON_LIBS) \
$(LIBSOUP_LIBS)
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
#DISTCLEANFILES +=
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
TESTS = $(GTKDOC_CHECK)
endif
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>gsignond-plugin-sasl Reference Manual</title>
<releaseinfo>
for gsignond-plugin-sasl.
The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/gsignond-plugin-sasl/index.html">http://[SERVER]/gsignond-plugin-sasl/</ulink>.
</releaseinfo>
</bookinfo>
<chapter>
<title>Plugin reference</title>
<xi:include href="xml/gsignond-sasl-plugin.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>
bin_PROGRAMS = gsignond-sasl-example
gsignond_sasl_example_SOURCES = gsignond-sasl-example.c
gsignond_sasl_example_CFLAGS = \
$(GSIGNON_CFLAGS)
gsignond_sasl_example_LDADD = \
$(top_builddir)/src/libsasl.la \
$(GSIGNON_LIBS)
all-local: $(top_builddir)/docs/gsignond-sasl-example.listing
mostlyclean-local:
rm -rf $(top_builddir)/docs/gsignond-sasl-example.listing
$(top_builddir)/docs/gsignond-sasl-example.listing:
cp $(top_srcdir)/examples/gsignond-sasl-example.c $(top_builddir)/docs/gsignond-sasl-example.listing
/*
* Copyright (C) 2012 Intel Corporation.
*
* Contact: Alexander Kanavin <alex.kanavin@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <gsignond/gsignond-session-data.h>
#include <gsignond/gsignond-plugin-interface.h>
#include <gsignond/gsignond-error.h>
//this callback prints the received final response
//the final response should also be sent to the server
static void final_response_callback(GSignondPlugin* plugin, GSignondSessionData* result,
gpointer user_data)
{
const gchar* response = gsignond_dictionary_get_string(result,
"ResponseBase64");
g_printf("Authenticated successfully, got final response:\n%s\n",
response);
}
static void response_callback(GSignondPlugin* plugin, GSignondSessionData* result,
gpointer user_data)
{
//print the received intermediate response
const gchar* response = gsignond_dictionary_get_string(result,
"ResponseBase64");
g_printf("Authenticated successfully, got intermediate response:\n%s\n",
response);
//here the response should be sent to the server, and the server should
//respond with a challenge
//to make the example simpler (and non-functional) we hardcode a challenge
const gchar* server_challenge = "some challenge";
//submit the challenge to the plugin
GSignondSessionData* data = gsignond_dictionary_new();
gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge);
gsignond_plugin_request(plugin, data);
gsignond_dictionary_unref(data);
}
//this callback differs from the previous one in that we also set a password
//when returning a server response to the plugin - this is mandated by scram-sha1
//mechanism
static void scram_sha1_response_callback(GSignondPlugin* plugin, GSignondSessionData* result,
gpointer user_data)
{
//print the received intermediate response
const gchar* response = gsignond_dictionary_get_string(result,
"ResponseBase64");
g_printf("Authenticated successfully, got intermediate response:\n%s\n",
response);
//here the response should be sent to the server, and the server should
//respond with a challenge
//to make the example simpler (and non-functional) we hardcode a challenge
const gchar* server_challenge = "some challenge";
//submit the challenge and a password to the plugin
GSignondSessionData* data = gsignond_dictionary_new();
gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge);
gsignond_session_data_set_secret(data, "megapassword");
gsignond_plugin_request(plugin, data);
gsignond_dictionary_unref(data);
}
// print an error and exit the mainloop
static void error_callback(GSignondPlugin* plugin, GError* error,
gpointer user_data)
{
g_printf("Got an error: %s\n", error->message);
}
static void anonymous_authorization(gpointer plugin)
{
GSignondSessionData* data = gsignond_dictionary_new();
//fill in necessary data
gsignond_dictionary_set_string(data, "AnonymousToken",
"megauser@example.com");
//start the authorization
//any further processing happens in signal callbacks
gsignond_plugin_request_initial(plugin, data, "ANONYMOUS");
gsignond_dictionary_unref(data);
}
static void plain_authorization(gpointer plugin)
{
GSignondSessionData* data = gsignond_dictionary_new();
//fill in necessary data
gsignond_session_data_set_username(data, "megauser@example.com");
gsignond_session_data_set_secret(data, "megapassword");
//start the authorization
//any further processing happens in signal callbacks
gsignond_plugin_request_initial(plugin, data, "PLAIN");
gsignond_dictionary_unref(data);
}
static void cram_md5_authorization(gpointer plugin)
{
GSignondSessionData* data = gsignond_dictionary_new();
//fill in necessary data
gsignond_session_data_set_username(data, "megauser@example.com");
gsignond_session_data_set_secret(data, "megapassword");
//initial server challenge, for simplicty it's hardcoded
gsignond_dictionary_set_string(data, "ChallengeBase64", "some challenge");
//start the authorization
//any further processing happens in signal callbacks
gsignond_plugin_request_initial(plugin, data, "CRAM-MD5");
gsignond_dictionary_unref(data);
}
static void digest_md5_authorization(gpointer plugin)
{
GSignondSessionData* data = gsignond_dictionary_new();
//fill in necessary data
gsignond_dictionary_set_string(data, "Service", "megaservice");
gsignond_dictionary_set_string(data, "Hostname", "megahostname");
gsignond_session_data_set_username(data, "megauser@example.com");
gsignond_session_data_set_secret(data, "megapassword");
//initial server challenge, for simplicty it's hardcoded
gsignond_dictionary_set_string(data, "ChallengeBase64", "some challenge");
//start the authorization
//any further processing happens in signal callbacks
gsignond_plugin_request_initial(plugin, data, "DIGEST-MD5");
gsignond_dictionary_unref(data);
}
static void scram_sha1_authorization(gpointer plugin)
{
GSignondSessionData* data = gsignond_dictionary_new();
//fill in necessary data
gsignond_session_data_set_username(data, "megauser@example.com");
//initial server challenge, for simplicty it's hardcoded
gsignond_dictionary_set_string(data, "ChallengeBase64", "some challenge");
//start the authorization
//any further processing happens in signal callbacks
gsignond_plugin_request_initial(plugin, data, "SCRAM-SHA-1");
gsignond_dictionary_unref(data);
}
int main (void)
{
#if !GLIB_CHECK_VERSION (2, 36, 0)
g_type_init ();
#endif
gpointer plugin = g_object_new(gsignond_sasl_plugin_get_type(), NULL);
//connect to various signals of the plugin object
g_signal_connect(plugin, "response-final", G_CALLBACK(final_response_callback), NULL);
gulong response_id = g_signal_connect(plugin, "response", G_CALLBACK(response_callback), NULL);
g_signal_connect(plugin, "error", G_CALLBACK(error_callback), NULL);
//how to use various authorization mechanisms
anonymous_authorization(plugin);
plain_authorization(plugin);
cram_md5_authorization(plugin);
digest_md5_authorization(plugin);
//how to use SCRAM-SHA-1 authorization
//SCRAM-SHA-1 mechanism requires a custom response callback where in addition
//to the server response also a password is provided
g_signal_handler_disconnect(plugin, response_id);
g_signal_connect(plugin, "response", G_CALLBACK(scram_sha1_response_callback), NULL);
scram_sha1_authorization(plugin);
g_object_unref(plugin);
return 0;
}
This diff is collapsed.
......@@ -36,8 +36,17 @@
#define GSIGNOND_IS_SASL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSIGNOND_TYPE_SASL_PLUGIN))
#define GSIGNOND_SASL_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSIGNOND_TYPE_SASL_PLUGIN, GSignondSaslPluginClass))
/**
* GSignondSaslPlugin:
*
* Opaque structure for the SASL plugin object
*/
typedef struct _GSignondSaslPlugin GSignondSaslPlugin;
/**
* GSignondSaslPluginClass:
*
* Opaque structure for the SASL plugin class
*/
typedef struct _GSignondSaslPluginClass GSignondSaslPluginClass;
struct _GSignondSaslPlugin
......@@ -50,6 +59,7 @@ struct _GSignondSaslPlugin
struct _GSignondSaslPluginClass
{
/*< private >*/
GObjectClass parent_class;
};
......
......@@ -50,6 +50,7 @@ static void check_plugin(GSignondPlugin* plugin)
START_TEST (test_saslplugin_create)
{
g_printf("Starting test_saslplugin_create\n");
gpointer plugin;
plugin = g_object_new(GSIGNOND_TYPE_SASL_PLUGIN, NULL);
......@@ -75,6 +76,8 @@ static void error_callback(GSignondPlugin* plugin, GError* error,
START_TEST (test_saslplugin_request_anonymous)
{
g_printf("Starting test_saslplugin_request_anonymous\n");
gpointer plugin;
plugin = g_object_new(GSIGNOND_TYPE_SASL_PLUGIN, NULL);
......@@ -127,6 +130,7 @@ END_TEST
START_TEST (test_saslplugin_request_plain)
{
g_printf("Starting test_saslplugin_request_plain\n");
gpointer plugin;
plugin = g_object_new(GSIGNOND_TYPE_SASL_PLUGIN, NULL);
......@@ -172,6 +176,7 @@ END_TEST
START_TEST (test_saslplugin_request_digest_md5)
{
g_printf("Starting test_saslplugin_request_digest_md5\n");
gpointer plugin;
Gsasl *gsasl_context;
Gsasl_session *gsasl_session;
......@@ -222,7 +227,6 @@ START_TEST (test_saslplugin_request_digest_md5)
gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge);
free(server_challenge);
gsignond_plugin_request(plugin, data);
fail_if(result != NULL);
......@@ -243,6 +247,7 @@ END_TEST
START_TEST (test_saslplugin_request_cram_md5)
{
g_printf("Starting test_saslplugin_request_cram_md5\n");
gpointer plugin;
Gsasl *gsasl_context;
Gsasl_session *gsasl_session;
......@@ -301,6 +306,7 @@ END_TEST
START_TEST (test_saslplugin_request_scram_sha_1)
{
g_printf("Starting test_saslplugin_request_scram_sha_1\n");
gpointer plugin;
Gsasl *gsasl_context;
Gsasl_session *gsasl_session;
......@@ -336,7 +342,6 @@ START_TEST (test_saslplugin_request_scram_sha_1)
fail_if(result == NULL);
fail_if(result_final != NULL);
fail_if(error != NULL);
gsasl_property_set(gsasl_session, GSASL_PASSWORD, "megapassword");
fail_if (gsasl_step64(gsasl_session,
gsignond_dictionary_get_string(result,
......@@ -348,7 +353,6 @@ START_TEST (test_saslplugin_request_scram_sha_1)
gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge);
free(server_challenge);
gsignond_session_data_set_secret(data, "megapassword");
gsignond_plugin_request(plugin, data);
fail_if(result == NULL);
......@@ -364,7 +368,6 @@ START_TEST (test_saslplugin_request_scram_sha_1)
gsignond_dictionary_set_string(data, "ChallengeBase64", server_challenge);
free(server_challenge);
gsignond_plugin_request(plugin, data);
fail_if(result != NULL);
......@@ -403,7 +406,9 @@ int main (void)
{
int number_failed;
g_type_init();
#if !GLIB_CHECK_VERSION (2, 36, 0)
g_type_init ();
#endif
Suite *s = saslplugin_suite();
SRunner *sr = srunner_create(s);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment