Author: ArcRiley
Date: 2009-02-26 17:03:31 -0500 (Thu, 26 Feb 2009)
New Revision: 1526

Modified:
   trunk/concordance/include/concordance.sockets.h
   trunk/concordance/src/sockets/Client.c
Log:
SASL authentication working (if a bit hackish for now)

Modified: trunk/concordance/include/concordance.sockets.h
===================================================================
--- trunk/concordance/include/concordance.sockets.h     2009-02-26 22:03:27 UTC 
(rev 1525)
+++ trunk/concordance/include/concordance.sockets.h     2009-02-26 22:03:31 UTC 
(rev 1526)
@@ -71,6 +71,7 @@
   gchar                 skey[16];      /* session key (stream id="") */
   concordVersion        vers;          /* XMPP major.minor version */
   gboolean              tls;           /* flag for whether tls is enabled */
+  gchar*                user;          /* NULL or authenticated username */
   gint                  state;         /* current session state */
   gint                  depth;         /* parser element depth */
   GString*              wbuff;         /* write buffer */
@@ -93,6 +94,7 @@
   CONCORD_E_OPEN,                   /* inside <stream>           */
   CONCORD_E_CLIENT,                 /* <iq> <message> <presence> */
   CONCORD_E_SASL,                   /* <auth> <response>         */
+  CONCORD_E_RESET,                  /* pending stream reset      */
 };
 
 #endif

Modified: trunk/concordance/src/sockets/Client.c
===================================================================
--- trunk/concordance/src/sockets/Client.c      2009-02-26 22:03:27 UTC (rev 
1525)
+++ trunk/concordance/src/sockets/Client.c      2009-02-26 22:03:31 UTC (rev 
1526)
@@ -66,6 +66,7 @@
     session->self = self;
     session->node = NULL;
     session->lock = g_mutex_new();
+    session->user = NULL;
 
     /* create a new channel using an OS-dependent function
 
@@ -179,9 +180,25 @@
            the session->state will be reset to CONCORD_E_CLOSE (== FALSE)
            to indicate that the session needs to get wrapped up.
         */
-        if (XML_Parse(session->pars, buff, buff_len, FALSE) && session->state)
+        if (XML_Parse(session->pars, buff, buff_len, FALSE) &&
+            session->state) {
+          if (session->state == CONCORD_E_RESET) {
+            /* reset XML parser and stream state
+        
+               XML_Bool XML_ParserReset          (XML_Parser p,
+                                                  const XML_Char *encoding);
+            */
+            XML_Parse(session->pars, NULL, 0, TRUE);
+            XML_ParserReset(session->pars, NULL);
+            XML_SetUserData(session->pars, session);
+            XML_SetElementHandler(session->pars, _xmlStart, _xmlEnd);
+            XML_SetCharacterDataHandler(session->pars, _xmlCharData);
+            session->depth = 0;
+            session->state = CONCORD_E_OPEN;
+          }
           /* return true so GMainLoop will continue watching this channel */
           return TRUE;
+        }
       }
     }
 
@@ -302,6 +319,39 @@
   #
   ###########################################################################
   #
+  # GNU SASL Callback
+  #                                                                        */
+  static int
+  _saslCallback(Gsasl* ctx, Gsasl_session* sctx, Gsasl_property prop) {   /*\
+    cdef :                                                                \*/
+      socketsClient_Data* session;
+      gint                ret;
+
+    /* get session data
+
+       void*            gsasl_session_hook_get   (Gsasl_session * sctx);
+    */
+    session = (socketsClient_Data*) gsasl_session_hook_get(sctx);
+
+    switch (prop) {
+      case GSASL_PASSWORD : {
+        gsasl_property_set(sctx, GSASL_PASSWORD, "tester");
+        ret = GSASL_OK;
+        break;
+      }
+      default : {
+        ret = GSASL_NO_CALLBACK;
+        break;
+      }
+    }
+
+    return ret;
+  }
+  
+  /*
+  #
+  ###########################################################################
+  #
   # Element responses
   #                                                                        */
   static void
@@ -444,24 +494,30 @@
       return;
     }
 
-    /* open stream:features and mechanisms element */
-    buff = g_string_append(buff, "<stream:features><mechanisms"
-                                 " xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>");
+    if (session->user) {
+      /* don't provide features to authenticated users */
+      buff = g_string_append(buff, "<stream:features/>");
+    }
+    else {
+      /* open stream:features and mechanisms element */
+      buff = g_string_append(buff, "<stream:features><mechanisms"
+                                   " 
xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>");
 
-    /* add a <mechanism> element for each supported SASL mechanism
+      /* add a <mechanism> element for each supported SASL mechanism
 
-       int              gsasl_server_support_p   (Gsasl* ctx,
+         int            gsasl_server_support_p   (Gsasl* ctx,
                                                   const char* name);
-       GString*         g_string_append          (GString *string,
+         GString*       g_string_append          (GString *string,
                                                   const gchar *val);
-    */
-    if (gsasl_server_support_p(self->saslCntx, "DIGEST-MD5"))
-      buff = g_string_append(buff, "<mechanism>DIGEST-MD5</mechanism>");
-    if (gsasl_server_support_p(self->saslCntx, "PLAIN"))
-      buff = g_string_append(buff, "<mechanism>PLAIN</mechanism>");
+      */
+      if (gsasl_server_support_p(self->saslCntx, "DIGEST-MD5"))
+        buff = g_string_append(buff, "<mechanism>DIGEST-MD5</mechanism>");
+      if (gsasl_server_support_p(self->saslCntx, "PLAIN"))
+        buff = g_string_append(buff, "<mechanism>PLAIN</mechanism>");
 
-    /* close <mechanisms> and <stream:features>, then send buffer */
-    buff = g_string_append(buff, "</mechanisms></stream:features>");
+      /* close <mechanisms> and <stream:features>, then send buffer */
+      buff = g_string_append(buff, "</mechanisms></stream:features>");
+    }
     _gioSend(session, buff->str, buff->len);
 
     /* free response buffer before returning
@@ -474,44 +530,75 @@
 
 
   static void
-  _reply_saslChallenge(socketsClient_Data* session) {                     /*\
+  _reply_sasl(socketsClient_Data* session) {                              /*\
     cdef :                                                                \*/
+      GString* buff;
+      gchar*   element;
+      gchar*   output = "";
+      gint     status;
 
-
-    return;
-    /*
-       gchar*           g_base64_encode          (const guchar *data,
-                                                  gsize len);
+    /* process gsasl step with base64 conversion
+    
+       int              gsasl_step64             (Gsasl_session *sctx,
+                                                  const char *b64input,
+                                                  char **b64output);
     */
+    status = gsasl_step64(session->sctx, session->ebuff->str, &output);
 
+    buff = g_string_new("");
 
+    switch (status) {
+      case GSASL_OK : {
+        element = "success";
+        session->state = CONCORD_E_RESET;
+        break;
+      }
+      case GSASL_NEEDS_MORE : {
+        element = "challenge";
+        break;
+      }
+      case GSASL_UNKNOWN_MECHANISM : {
+        element = "failure";
+        output = "<invalid-mechanism/>";
+        break;
+      }
+      case GSASL_BASE64_ERROR : {
+        element = "failure";
+        output = "<incorrect-encoding/>";
+        break;
+      }
+      case GSASL_AUTHENTICATION_ERROR : {
+        element = "failure";
+        output = "<not-authorized/>";
+        break;
+      }
+      default : {
+        element = "failure";
+        output = "<temporary-auth-failure/>";
+        break;
+      }
+    }
 
-    /*g_string_printf(buff,
-                    "<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
-                    "%s</challenge>", ""); */
-  }
+    /* switch how output is generated based on whether element is populated */
+    if (output[0] == 0) {
+      g_string_printf(buff,
+                      "<%s xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>",
+                      element);
+    }
+    else {
+      g_string_printf(buff,
+                      "<%s xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>%s</%s>",
+                      element, output, element);
+    }
+    _gioSend(session, buff->str, buff->len);
 
-  static void
-  _reply_saslFailure(socketsClient_Data* session, gchar* failure) {       /*\
-    cdef :                                                                \*/
-      GString* buff;
-
-    /* printf failure to a GString, then send it
-
-       GString*         g_string_new             (const gchar *init);
-       void             g_string_printf          (GString *string,
-                                                  const gchar *format,
-                                                  ...);
-       gchar*           g_string_free            (GString *string,
-                                                  gboolean free_segment);
-    */
-    buff = g_string_new("");
-    g_string_printf(buff, "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
-                          "%s</failure>", failure);
-    _gioSend(session, buff->str, buff->len);
+    /* free buffer and sasl output before returning */
     g_string_free(buff, TRUE);
+    if (status == GSASL_OK || status == GSASL_NEEDS_MORE) {
+      g_free(output);
+    }
   }
-
+  
   /*
   #
   ###########################################################################
@@ -535,15 +622,6 @@
     */
     element = g_strsplit(name, " ", 2);
 
-    /* this from http://www.xml.com/pub/a/1999/09/expat/index.html?page=2 */
-    for (i = 0; i < session->depth; i++)
-      printf("  ");
-
-    printf("<%s xmlns='%s'", element[1], element[0]);
-    for (i = 0; atts[i]; i += 2)
-      printf(" %s='%s'", atts[i], atts[i + 1]);
-    printf(">\n");
-
     switch (session->depth) {
       /* match element by depth, namespace, and finally element name
 
@@ -591,8 +669,6 @@
             if (!(attr = concordFindAttr(atts, "from")))
               attr = "";
             session->efrom = g_string_assign(session->efrom, attr);
-            printf("--------- from: %s to: %s\n",
-                   session->efrom->str, session->eto->str);
 
             /* copy element and attributes to ebuff
 
@@ -618,21 +694,27 @@
                                "urn:ietf:params:xml:ns:xmpp-sasl") == 0) {
           if (g_ascii_strcasecmp(element[1], "auth") == 0) {
             gchar* mec = concordFindAttr(atts, "mechanism");
-            if (mec && gsasl_server_support_p(self->saslCntx, mec)) {
-              /* initiate server session
+            if (!mec) {
+              mec = "";              
+            }
+            /* initiate server session
 
-                 int    gsasl_server_start       (Gsasl* ctx,
+               int      gsasl_server_start       (Gsasl* ctx,
                                                   const char* mech,
                                                   Gsasl_session** sctx);
-              */
-              printf("------ init %s mechanism\n", mec);
-              gsasl_server_start(self->saslCntx, mec, &session->sctx);
-              session->state = CONCORD_E_SASL;
-            }
-            else {
-              _reply_saslFailure(session, "<invalid-mechanism/>");
-              session->state = CONCORD_E_CLOSE;
-            }
+               void     gsasl_session_hook_set   (Gsasl_session * sctx,
+                                                  void * hook);
+               void     gsasl_callback_set       (Gsasl * ctx,
+                                                  Gsasl_callback_function cb);
+               void     gsasl_property_set       (Gsasl_session *sctx,
+                                                  Gsasl_property prop,
+                                                  const char *data);
+            */
+            gsasl_server_start(self->saslCntx, mec, &session->sctx);
+            gsasl_session_hook_set(session->sctx, (gpointer) session);
+            gsasl_callback_set(self->saslCntx, _saslCallback);
+            gsasl_property_set(session->sctx, GSASL_REALM, 
"selket.apogean.org");
+            session->state = CONCORD_E_SASL;
           }
 
           /* remaining: response, abort */
@@ -692,10 +774,6 @@
     */
     element = g_strsplit(name, " ", 2);
 
-    for (i = 0; i < session->depth; i++)
-      printf("  ");
-    printf("</%s>\n", element[1]);
-
     switch (session->depth) {
       case 0 : {
         /* close session when </stream:stream> is sent */
@@ -716,7 +794,7 @@
             break;
           }
           case CONCORD_E_SASL : {
-            _reply_saslChallenge(session);
+            _reply_sasl(session);
             break;
           }
         }
@@ -729,7 +807,6 @@
         session->ebuff = g_string_assign(session->ebuff, "");
         session->efrom = g_string_assign(session->efrom, "");
         session->eto   = g_string_assign(session->eto,   "");
-
         break;
       }
       default : {
@@ -759,15 +836,7 @@
     cdef :                                                                \*/
       socketsClient_Data*   session = (socketsClient_Data*) data;
       gint                  i;
-      gchar*                strn;
 
-    /* output to stdout for debugging */
-    strn = g_strndup(str, str_len);
-    for (i = 0; i < session->depth; i++)
-      printf("  ");
-    printf("\"%s\"\n", strn);
-    g_free(strn);
-
     if (session->state == CONCORD_E_OPEN)
       /* character data should be ignored at the stream level */
       return;

_______________________________________________
PySoy-SVN mailing list
PySoy-SVN@pysoy.org
http://www.pysoy.org/mailman/listinfo/pysoy-svn

Reply via email to