Support for SASL PLAIN authentication
authorThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sun, 2 Nov 2008 11:58:02 +0000 (09:58 -0200)
committerThadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Sun, 2 Nov 2008 11:58:02 +0000 (09:58 -0200)
Makefile
sasl.c [new file with mode: 0644]
sasl.h [new file with mode: 0644]
tictactoe.c
xmpp.c
xmpp.h
xmpp_internal.h

index 15fe746..275426f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 OBJECTS = sort_udns.o tcp_connect.o iksemel_extra.o tictactoe.o \
-       xmpp.o features.o
+       xmpp.o features.o sasl.o
 CC = gcc
-CFLAGS = -g -Wall `pkg-config --cflags iksemel`
-LIBS = -ludns `pkg-config --libs iksemel`
+CFLAGS = -g -Wall `pkg-config --cflags iksemel libgsasl`
+LIBS = -ludns `pkg-config --libs iksemel libgsasl`
 
 all: tictactoe
 
diff --git a/sasl.c b/sasl.c
new file mode 100644 (file)
index 0000000..dd93367
--- /dev/null
+++ b/sasl.c
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include "xmpp_internal.h"
+#include "sasl.h"
+
+void
+hc_xmpp_sasl_authenticate (hc_xmpp_t *xmpp)
+{
+  const char *mech = "PLAIN";
+  char *p = "";
+  iks *auth;
+  gsasl_client_start (xmpp->sasl_ctx, mech, &xmpp->sasl_session);
+  gsasl_property_set (xmpp->sasl_session, GSASL_AUTHID, xmpp->user);
+  gsasl_property_set (xmpp->sasl_session, GSASL_PASSWORD, xmpp->password);
+  gsasl_step64 (xmpp->sasl_session, p, &p);
+  auth = iks_new ("auth");
+  iks_insert_attrib (auth, "xmlns", HC_XMPP_NS_SASL);
+  iks_insert_attrib (auth, "mechanism", mech);
+  iks_insert_cdata (auth, p, 0);
+  hc_xmpp_send_iks (xmpp, auth);
+  free (p);
+}
+
+void
+hc_xmpp_sasl_iterate (hc_xmpp_t *xmpp, iks *stanza)
+{
+  if (!iks_strcmp (iks_name (stanza), "success"))
+    {
+      xmpp->status = HC_XMPP_AUTHENTICATED;
+    }
+}
diff --git a/sasl.h b/sasl.h
new file mode 100644 (file)
index 0000000..a5bafb7
--- /dev/null
+++ b/sasl.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (C) 2008  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef HC_XMPP_SASL_H
+#define HC_XMPP_SASL_H
+
+#include "xmpp.h"
+
+void hc_xmpp_sasl_authenticate (hc_xmpp_t *);
+void hc_xmpp_sasl_iterate (hc_xmpp_t *, iks *);
+
+#endif
index cc1dab5..700a269 100644 (file)
@@ -26,6 +26,7 @@
 #include "tcp_connect.h"
 #include "iksemel_extra.h"
 #include "xmpp.h"
+#include "sasl.h"
 
 int
 myhook (void *data, int type, iks *stanza)
@@ -33,10 +34,16 @@ myhook (void *data, int type, iks *stanza)
   if (!iks_strcmp (iks_name (stanza), "stream:features"))
     {
       hc_xmpp_features (data, stanza);
-      if (hc_xmpp_is_tls_supported (data))
-        fprintf (stderr, "TLS is supported\n");
       if (hc_xmpp_is_sasl_supported (data))
-        fprintf (stderr, "SASL is supported\n");
+        {
+          hc_xmpp_sasl_authenticate (data);
+        }
+    }
+  else if (!iks_strcmp (iks_find_attrib (stanza, "xmlns"), HC_XMPP_NS_SASL))
+    {
+      hc_xmpp_sasl_iterate (data, stanza);
+      if (hc_xmpp_status (data) == HC_XMPP_AUTHENTICATED)
+        fprintf (stdout, "Authenticated\n");
     }
   else
     {
@@ -46,32 +53,32 @@ myhook (void *data, int type, iks *stanza)
 }
 
 void
-write_stream (hc_xmpp_t *xmpp);
+write_stream (hc_xmpp_t *xmpp)
 {
   char *buffer = NULL;
   asprintf (&buffer, "<stream:stream xmlns='jabber:client' "
                      "xmlns:stream='http://etherx.jabber.org/streams' "
-                     "version='1.0' to='%s'>", xmpp->server);
-  write (xmpp->fd, buffer, strlen (buffer));
+                     "version='1.0' to='%s'>", hc_xmpp_server (xmpp));
+  hc_xmpp_send_buffer (xmpp, buffer, 0);
   free (buffer);
 }
 
 void
-loop (hc_xmpp_t *xmpp);
+loop (hc_xmpp_t *xmpp)
 {
-  char buffer[4096];
-  int r;
-  while ((r = read (xmpp->fd, buffer, sizeof (buffer))) > 0)
-    iks_parse (xmpp->parser, buffer, r, 0);
+  while (1)
+    hc_xmpp_read_and_parse (xmpp);
 }
 
 int
 main (int argc, char **argv)
 {
   char *server = "jabber-br.org";
+  char *user = "pubsub";
+  char *password = "pubsub";
   hc_xmpp_t *xmpp;
   dns_init (NULL, 1);
-  xmpp = hc_xmpp_new (myhook, server);
+  xmpp = hc_xmpp_new (myhook, server, user, password);
   write_stream (xmpp);
   loop (xmpp);
   return 0;
diff --git a/xmpp.c b/xmpp.c
index a6a0a09..ca9501e 100644 (file)
--- a/xmpp.c
+++ b/xmpp.c
 
 
 #include <stdlib.h>
+#include <string.h>
+#include <gsasl.h>
 #include "xmpp.h"
 #include "xmpp_internal.h"
 #include "iksemel_extra.h"
+#include "tcp_connect.h"
 
 hc_xmpp_t *
-hc_xmpp_new (iksStreamHook *hook, char *server)
+hc_xmpp_new (iksStreamHook *hook, char *server, char *user, char *pass)
 {
   hc_xmpp_t *xmpp = malloc (sizeof (hc_xmpp_t));
   xmpp->server = strdup (server);
+  xmpp->user = strdup (user);
+  xmpp->password = strdup (pass);
   xmpp->parser = iks_extra_stream_new (xmpp, hook);
+  gsasl_init (&xmpp->sasl_ctx);
   xmpp->fd = hc_tcp_connect (server, "xmpp-client");
   xmpp->tls = NONE;
   xmpp->sasl = NONE;
+  xmpp->status = HC_XMPP_NONE;
   return xmpp;
 }
 
@@ -82,3 +89,39 @@ hc_xmpp_is_sasl_enabled (hc_xmpp_t *xmpp)
   return xmpp->sasl & ENABLED;
 }
 
+char *
+hc_xmpp_server (hc_xmpp_t *xmpp)
+{
+  return xmpp->server;
+}
+
+void
+hc_xmpp_send_buffer (hc_xmpp_t *xmpp, char *buffer, size_t len)
+{
+  if (len == 0)
+    len = strlen (buffer);
+  write (xmpp->fd, buffer, len);
+}
+
+void
+hc_xmpp_send_iks (hc_xmpp_t *xmpp, iks *x)
+{
+  char *str;
+  str = iks_string (iks_stack (x), x);
+  write (xmpp->fd, str, strlen (str));
+}
+
+void
+hc_xmpp_read_and_parse (hc_xmpp_t *xmpp)
+{
+  char buffer[4096];
+  int r;
+  r = read (xmpp->fd, buffer, sizeof (buffer));
+  iks_parse (xmpp->parser, buffer, r, 0);
+}
+
+int
+hc_xmpp_status (hc_xmpp_t *xmpp)
+{
+  return xmpp->status;
+}
diff --git a/xmpp.h b/xmpp.h
index 74cee4a..7a0e0d0 100644 (file)
--- a/xmpp.h
+++ b/xmpp.h
 
 #include <iksemel.h>
 
+enum
+{
+  HC_XMPP_NONE,
+  HC_XMPP_AUTHENTICATED,
+  HC_XMPP_BOUND
+};
+
 typedef struct _hc_xmpp_t hc_xmpp_t;
 
 #define HC_XMPP_NS_TLS "urn:ietf:params:xml:ns:xmpp-tls"
 #define HC_XMPP_NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
 
-hc_xmpp_t * hc_xmpp_new (void);
+hc_xmpp_t * hc_xmpp_new (iksStreamHook *, char *, char *, char *);
 int hc_xmpp_is_tls_supported (hc_xmpp_t *);
 int hc_xmpp_is_tls_required (hc_xmpp_t *);
 int hc_xmpp_is_tls_optional (hc_xmpp_t *);
@@ -36,6 +43,11 @@ int hc_xmpp_is_sasl_supported (hc_xmpp_t *);
 int hc_xmpp_is_sasl_required (hc_xmpp_t *);
 int hc_xmpp_is_sasl_optional (hc_xmpp_t *);
 int hc_xmpp_is_sasl_enabled (hc_xmpp_t *);
+char *hc_xmpp_server (hc_xmpp_t *);
+void hc_xmpp_send_buffer (hc_xmpp_t *, char *, size_t);
+void hc_xmpp_send_iks (hc_xmpp_t *, iks *);
+void hc_xmpp_read_and_parse (hc_xmpp_t *);
 void hc_xmpp_features (hc_xmpp_t *, iks *);
+int hc_xmpp_status (hc_xmpp_t *);
 
 #endif
index f57c688..df8790c 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef HC_XMPP_INTERNAL_H
 #define HC_XMPP_INTERNAL_H
 
+#include <gsasl.h>
 #include <iksemel.h>
 #include "xmpp.h"
 
@@ -35,10 +36,15 @@ enum
 struct _hc_xmpp_t
 {
   char *server;
+  char *user;
+  char *password;
   iksparser *parser;
+  Gsasl *sasl_ctx;
+  Gsasl_session *sasl_session;
   int fd;
   int tls;
   int sasl;
+  int status;
 };
 
 #endif