You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2012/04/05 21:03:43 UTC

svn commit: r1310014 - in /qpid/proton/trunk/proton-c: ./ include/proton/ src/ src/codec/ src/engine/ src/sasl/ src/types/

Author: rhs
Date: Thu Apr  5 19:03:42 2012
New Revision: 1310014

URL: http://svn.apache.org/viewvc?rev=1310014&view=rev
Log:
updated sasl interface to permit full challenge/response sequence

Added:
    qpid/proton/trunk/proton-c/include/proton/errors.h
Removed:
    qpid/proton/trunk/proton-c/src/sasl/sasl-internal.h
Modified:
    qpid/proton/trunk/proton-c/cproton.i
    qpid/proton/trunk/proton-c/include/proton/codec.h
    qpid/proton/trunk/proton-c/include/proton/driver.h
    qpid/proton/trunk/proton-c/include/proton/engine.h
    qpid/proton/trunk/proton-c/include/proton/sasl.h
    qpid/proton/trunk/proton-c/include/proton/value.h
    qpid/proton/trunk/proton-c/src/codec/codec.c
    qpid/proton/trunk/proton-c/src/driver.c
    qpid/proton/trunk/proton-c/src/engine/engine.c
    qpid/proton/trunk/proton-c/src/proton.c
    qpid/proton/trunk/proton-c/src/sasl/sasl.c
    qpid/proton/trunk/proton-c/src/types/array.c
    qpid/proton/trunk/proton-c/src/types/binary.c
    qpid/proton/trunk/proton-c/src/types/value.c
    qpid/proton/trunk/proton-c/src/util.c

Modified: qpid/proton/trunk/proton-c/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/cproton.i?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/cproton.i (original)
+++ qpid/proton/trunk/proton-c/cproton.i Thu Apr  5 19:03:42 2012
@@ -160,6 +160,7 @@ ssize_t pn_send(pn_link_t *transport, ch
 %ignore pn_connector_destroy;
 
 /* Parse the header file to generate wrappers */
+%include "proton/errors.h"
 %include "proton/engine.h"
 %include "proton/message.h"
 %include "proton/sasl.h"

Modified: qpid/proton/trunk/proton-c/include/proton/codec.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/codec.h?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/codec.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/codec.h Thu Apr  5 19:03:42 2012
@@ -26,6 +26,7 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <wchar.h>
+#include <proton/errors.h>
 
 int pn_write_descriptor(char **pos, char *limit);
 int pn_write_null(char **pos, char *limit);

Modified: qpid/proton/trunk/proton-c/include/proton/driver.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/driver.h?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/driver.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/driver.h Thu Apr  5 19:03:42 2012
@@ -22,6 +22,7 @@
  *
  */
 
+#include <proton/errors.h>
 #include <proton/engine.h>
 #include <proton/sasl.h>
 
@@ -54,6 +55,7 @@ pn_sasl_t *pn_connector_sasl(pn_connecto
 pn_connection_t *pn_connector_connection(pn_connector_t *ctor);
 void *pn_connector_context(pn_connector_t *ctor);
 void pn_connector_set_context(pn_connector_t *ctor, void *context);
+void pn_connector_eos(pn_connector_t *ctor);
 void pn_connector_close(pn_connector_t *ctor);
 bool pn_connector_closed(pn_connector_t *ctor);
 void pn_connector_destroy(pn_connector_t *ctor);

Modified: qpid/proton/trunk/proton-c/include/proton/engine.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/engine.h?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/engine.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/engine.h Thu Apr  5 19:03:42 2012
@@ -25,6 +25,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <sys/types.h>
+#include <proton/errors.h>
 
 typedef struct pn_error_t pn_error_t;
 typedef struct pn_transport_t pn_transport_t;
@@ -88,8 +89,6 @@ void pn_connection_close(pn_connection_t
 void pn_connection_destroy(pn_connection_t *connection);
 
 // transport
-#define PN_EOS (-1)
-#define PN_ERR (-2)
 pn_state_t pn_transport_state(pn_transport_t *transport);
 pn_error_t *pn_transport_error(pn_transport_t *transport);
 ssize_t pn_input(pn_transport_t *transport, char *bytes, size_t available);
@@ -136,7 +135,6 @@ ssize_t pn_send(pn_link_t *sender, const
 //void pn_abort(pn_sender_t *sender);
 
 // receiver
-#define PN_EOM (-1)
 void pn_flow(pn_link_t *receiver, int credits);
 ssize_t pn_recv(pn_link_t *receiver, char *bytes, size_t n);
 

Added: qpid/proton/trunk/proton-c/include/proton/errors.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/errors.h?rev=1310014&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/errors.h (added)
+++ qpid/proton/trunk/proton-c/include/proton/errors.h Thu Apr  5 19:03:42 2012
@@ -0,0 +1,31 @@
+#ifndef _PROTON_ERRORS_H
+#define _PROTON_ERRORS_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#define PN_EOS (-1)
+#define PN_ERR (-2)
+#define PN_OVERFLOW (-3)
+#define PN_STATE_ERR (-4)
+#define PN_ARG_ERR (-5)
+
+#endif /* errors.h */

Modified: qpid/proton/trunk/proton-c/include/proton/sasl.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/sasl.h?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/sasl.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/sasl.h Thu Apr  5 19:03:42 2012
@@ -28,21 +28,39 @@
 
 typedef struct pn_sasl_t pn_sasl_t;
 
-typedef enum {SASL_NONE=-1, SASL_OK=0, SASL_AUTH=1, SASL_SYS=2, SASL_PERM=3,
-              SASL_TEMP=4} pn_sasl_outcome_t;
+typedef enum {
+  PN_SASL_NONE=-1,
+  PN_SASL_OK=0,
+  PN_SASL_AUTH=1,
+  PN_SASL_SYS=2,
+  PN_SASL_PERM=3,
+  PN_SASL_TEMP=4
+} pn_sasl_outcome_t;
+
+typedef enum {
+  PN_SASL_CONF,
+  PN_SASL_IDLE,
+  PN_SASL_STEP,
+  PN_SASL_PASS,
+  PN_SASL_FAIL
+} pn_sasl_state_t;
 
 pn_sasl_t *pn_sasl();
-void pn_sasl_client(pn_sasl_t *sasl, const char *mechanism, const char *username, const char *password);
+pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl);
+void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms);
+const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl);
+void pn_sasl_client(pn_sasl_t *sasl);
 void pn_sasl_server(pn_sasl_t *sasl);
-void pn_sasl_auth(pn_sasl_t *sasl, pn_sasl_outcome_t outcome);
-bool pn_sasl_init(pn_sasl_t *sasl);
-const char *pn_sasl_mechanism(pn_sasl_t *sasl);
-pn_binary_t *pn_sasl_challenge(pn_sasl_t *sasl);
-pn_binary_t *pn_sasl_response(pn_sasl_t *sasl);
+void pn_sasl_plain(pn_sasl_t *sasl, const char *username, const char *password);
+size_t pn_sasl_pending(pn_sasl_t *sasl);
+ssize_t pn_sasl_recv(pn_sasl_t *sasl, char *bytes, size_t size);
+ssize_t pn_sasl_send(pn_sasl_t *sasl, const char *bytes, size_t size);
+void pn_sasl_done(pn_sasl_t *sasl, pn_sasl_outcome_t outcome);
 pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl);
 ssize_t pn_sasl_input(pn_sasl_t *sasl, char *bytes, size_t available);
 ssize_t pn_sasl_output(pn_sasl_t *sasl, char *bytes, size_t size);
 void pn_sasl_trace(pn_sasl_t *sasl, pn_trace_t trace);
 void pn_sasl_destroy(pn_sasl_t *sasl);
 
+
 #endif /* sasl.h */

Modified: qpid/proton/trunk/proton-c/include/proton/value.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/value.h?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/value.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/value.h Thu Apr  5 19:03:42 2012
@@ -104,6 +104,7 @@ pn_map_t *pn_to_map(pn_value_t v);
 pn_tag_t *pn_to_tag(pn_value_t v);
 void *pn_to_ref(pn_value_t v);
 
+pn_value_t pn_from_array(pn_array_t *a);
 pn_value_t pn_from_list(pn_list_t *l);
 pn_value_t pn_from_map(pn_map_t *m);
 pn_value_t pn_from_tag(pn_tag_t *t);
@@ -193,10 +194,12 @@ pn_binary_t *pn_binary(const char *bytes
 size_t pn_binary_size(pn_binary_t *b);
 const char *pn_binary_bytes(pn_binary_t *b);
 pn_binary_t *pn_binary_dup(pn_binary_t *b);
+ssize_t pn_binary_get(pn_binary_t *b, char *bytes, size_t size);
 
 /* arrays */
 
 pn_array_t *pn_array(enum TYPE type, int capacity);
+int pn_array_add(pn_array_t *a, pn_value_t v);
 pn_value_t pn_array_get(pn_array_t *a, int index);
 size_t pn_encode_sizeof_array(pn_array_t *a);
 size_t pn_encode_array(pn_array_t *array, char *out);

Modified: qpid/proton/trunk/proton-c/src/codec/codec.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/codec/codec.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/codec.c (original)
+++ qpid/proton/trunk/proton-c/src/codec/codec.c Thu Apr  5 19:03:42 2012
@@ -41,7 +41,7 @@ typedef union {
 static int pn_write_code(char **pos, char *limit, uint8_t code) {
   char *dst = *pos;
   if (limit - dst < 1) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     dst[0] = code;
     *pos += 1;
@@ -58,7 +58,7 @@ int pn_write_null(char **pos, char *limi
 static int pn_write_fixed8(char **pos, char *limit, uint8_t v, uint8_t code) {
   char *dst = *pos;
   if (limit - dst < 2) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     dst[0] = code;
     dst[1] = v;
@@ -81,7 +81,7 @@ static int pn_write_fixed16(char **pos, 
                             uint8_t code) {
   char *dst = *pos;
   if (limit - dst < 3) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     dst[0] = code;
     *((uint16_t *) (dst + 1)) = htons(v);
@@ -99,7 +99,7 @@ int pn_write_short(char **pos, char *lim
 static int pn_write_fixed32(char **pos, char *limit, uint32_t v, uint8_t code) {
   char *dst = *pos;
   if (limit - dst < 5) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     dst[0] = code;
     *((uint32_t *) (dst + 1)) = htonl(v);
@@ -125,7 +125,7 @@ int pn_write_float(char **pos, char *lim
 static int pn_write_fixed64(char **pos, char *limit, uint64_t v, uint8_t code) {
   char *dst = *pos;
   if (limit - dst < 9) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     dst[0] = code;
     uint32_t hi = v >> 32;
@@ -162,7 +162,7 @@ static int pn_write_variable(char **pos,
       return n;
   }
 
-  if (limit - *pos < size) return -1;
+  if (limit - *pos < size) return PN_OVERFLOW;
 
   memmove(*pos, src, size);
   *pos += size;
@@ -181,7 +181,7 @@ int pn_write_symbol(char **pos, char *li
 int pn_write_start(char **pos, char *limit, char **start) {
   char *dst = *pos;
   if (limit - dst < 9) {
-    return -1;
+    return PN_OVERFLOW;
   } else {
     *start = dst;
     *pos += 9;
@@ -238,7 +238,7 @@ ssize_t pn_read_encoding(const char *byt
   switch (code)
   {
   case PNE_DESCRIPTOR:
-    return -8;
+    return PN_ARG_ERR;
   case PNE_NULL:
     cb->on_null(ctx);
     return offset;
@@ -313,7 +313,7 @@ ssize_t pn_read_encoding(const char *byt
       cb->on_double(ctx, conv.d);
       break;
     default:
-      return -1;
+      return PN_ARG_ERR;
     }
 
     return offset;
@@ -341,7 +341,7 @@ ssize_t pn_read_encoding(const char *byt
       offset += 4;
       break;
     default:
-      return -2;
+      return PN_ARG_ERR;
     }
 
     {
@@ -358,7 +358,7 @@ ssize_t pn_read_encoding(const char *byt
         cb->on_symbol(ctx, size, start);
         break;
       default:
-        return -3;
+        return PN_ARG_ERR;
       }
     }
 
@@ -394,7 +394,7 @@ ssize_t pn_read_encoding(const char *byt
       offset += 4;
       break;
     default:
-      return -4;
+      return PN_ARG_ERR;
     }
 
     switch (code)
@@ -425,7 +425,7 @@ ssize_t pn_read_encoding(const char *byt
       cb->start_map(ctx, count);
       break;
     default:
-      return -5;
+      return PN_ARG_ERR;
     }
 
     for (int i = 0; i < count; i++)
@@ -446,13 +446,13 @@ ssize_t pn_read_encoding(const char *byt
       cb->stop_map(ctx, count);
       break;
     default:
-      return -6;
+      return PN_ARG_ERR;
     }
 
     return offset;
   default:
     printf("Unrecognised typecode: %u\n", code);
-    return -7;
+    return PN_ARG_ERR;
   }
 }
 

Modified: qpid/proton/trunk/proton-c/src/driver.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/driver.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/driver.c (original)
+++ qpid/proton/trunk/proton-c/src/driver.c Thu Apr  5 19:03:42 2012
@@ -197,7 +197,6 @@ static pn_connector_t *pn_listener_accep
   }
 }
 
-
 void pn_listener_close(pn_listener_t *l)
 {
   if (!l) return;
@@ -272,6 +271,7 @@ static ssize_t pn_connector_write_sasl_h
 static ssize_t pn_connector_write_sasl(pn_connector_t *ctor);
 static ssize_t pn_connector_write_amqp_header(pn_connector_t *ctor);
 static ssize_t pn_connector_write_amqp(pn_connector_t *ctor);
+static ssize_t pn_connector_write_eos(pn_connector_t *ctor);
 
 pn_connector_t *pn_connector_fd(pn_driver_t *driver, int fd, void *context)
 {
@@ -336,6 +336,13 @@ pn_listener_t *pn_connector_listener(pn_
   return ctor ? ctor->listener : NULL;
 }
 
+void pn_connector_eos(pn_connector_t *ctor)
+{
+  if (!ctor) return;
+
+  ctor->process_input = pn_connector_write_eos;
+}
+
 void pn_connector_close(pn_connector_t *ctor)
 {
   // XXX: should probably signal engine and callback here
@@ -465,7 +472,7 @@ static void pn_connector_write(pn_connec
     } else if (n == 0) {
       break;
     } else {
-      if (n != PN_EOS) fprintf(stderr, "error in process_output: %zi", n);
+      if (n != PN_EOS) fprintf(stderr, "error in process_output: %zi\n", n);
       pn_connector_close(ctor);
       return;
     }
@@ -525,6 +532,11 @@ static ssize_t pn_connector_write_amqp(p
   return pn_output(transport, pn_connector_output(ctor), pn_connector_available(ctor));
 }
 
+static ssize_t pn_connector_write_eos(pn_connector_t *ctor)
+{
+  return PN_EOS;
+}
+
 static time_t pn_connector_tick(pn_connector_t *ctor, time_t now)
 {
   // XXX: should probably have a function pointer for this and switch it with different layers

Modified: qpid/proton/trunk/proton-c/src/engine/engine.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/engine/engine.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/engine/engine.c (original)
+++ qpid/proton/trunk/proton-c/src/engine/engine.c Thu Apr  5 19:03:42 2012
@@ -1553,11 +1553,11 @@ ssize_t pn_recv(pn_link_t *receiver, cha
       delivery->size -= size;
       return size;
     } else {
-      return PN_EOM;
+      return PN_EOS;
     }
   } else {
     // XXX: ?
-    return PN_EOM;
+    return PN_EOS;
   }
 }
 

Modified: qpid/proton/trunk/proton-c/src/proton.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/proton.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/proton.c (original)
+++ qpid/proton/trunk/proton-c/src/proton.c Thu Apr  5 19:03:42 2012
@@ -85,29 +85,31 @@ void server_callback(pn_connector_t *cto
 {
   pn_sasl_t *sasl = pn_connector_sasl(ctor);
 
-  if (!pn_sasl_init(sasl)) {
-    pn_sasl_server(sasl);
-  }
-
-  switch (pn_sasl_outcome(sasl)) {
-  case SASL_NONE:
-    {
-      const char *mech = pn_sasl_mechanism(sasl);
-      if (mech && (!strcmp(mech, "PLAIN") || !strcmp(mech, "ANONYMOUS"))) {
-        pn_binary_t *response = pn_sasl_response(sasl);
-        char buf[1024];
-        pn_format(buf, 1024, pn_from_binary(response));
-        printf("response = %s\n", buf);
-        pn_sasl_auth(sasl, SASL_OK);
-        break;
-      } else {
-        return;
+  while (pn_sasl_state(sasl) != PN_SASL_PASS) {
+    switch (pn_sasl_state(sasl)) {
+    case PN_SASL_IDLE:
+      return;
+    case PN_SASL_CONF:
+      pn_sasl_mechanisms(sasl, "PLAIN ANONYMOUS");
+      pn_sasl_server(sasl);
+      break;
+    case PN_SASL_STEP:
+      {
+        size_t n = pn_sasl_pending(sasl);
+        char iresp[n];
+        pn_sasl_recv(sasl, iresp, n);
+        printf(pn_sasl_remote_mechanisms(sasl));
+        printf(" response = ");
+        pn_print_data(iresp, n);
+        printf("\n");
+        pn_sasl_done(sasl, PN_SASL_OK);
       }
+      break;
+    case PN_SASL_PASS:
+      break;
+    case PN_SASL_FAIL:
+      return;
     }
-  case SASL_OK:
-    break;
-  default:
-    return;
   }
 
   pn_connection_t *conn = pn_connector_connection(ctor);
@@ -152,7 +154,7 @@ void server_callback(pn_connector_t *cto
       printf("  payload = \"");
       while (true) {
         ssize_t n = pn_recv(link, msg, 1024);
-        if (n == PN_EOM) {
+        if (n == PN_EOS) {
           pn_advance(link);
           pn_disposition(delivery, PN_ACCEPTED);
           break;
@@ -214,21 +216,38 @@ struct client_context {
 void client_callback(pn_connector_t *ctor)
 {
   struct client_context *ctx = pn_connector_context(ctor);
+  if (pn_connector_closed(ctor)) {
+    ctx->done = true;
+  }
 
   pn_sasl_t *sasl = pn_connector_sasl(ctor);
-  if (!pn_sasl_init(sasl)) {
-    pn_sasl_client(sasl, ctx->mechanism, ctx->username, ctx->password);
-  }
 
-  switch (pn_sasl_outcome(sasl)) {
-  case SASL_NONE:
-    return;
-  case SASL_OK:
-    break;
-  default:
-    fprintf(stderr, "auth failed\n");
-    ctx->done = true;
-    return;
+  while (pn_sasl_state(sasl) != PN_SASL_PASS) {
+    pn_sasl_state_t st = pn_sasl_state(sasl);
+    switch (st) {
+    case PN_SASL_IDLE:
+      return;
+    case PN_SASL_CONF:
+      if (ctx->mechanism && !strcmp(ctx->mechanism, "PLAIN")) {
+        pn_sasl_plain(sasl, ctx->username, ctx->password);
+      } else {
+        pn_sasl_mechanisms(sasl, ctx->mechanism);
+        pn_sasl_client(sasl);
+      }
+      break;
+    case PN_SASL_STEP:
+      if (pn_sasl_pending(sasl)) {
+        fprintf(stderr, "challenge failed\n");
+        ctx->done = true;
+      }
+      return;
+    case PN_SASL_FAIL:
+      fprintf(stderr, "authentication failed\n");
+      ctx->done = true;
+      return;
+    case PN_SASL_PASS:
+      break;
+    }
   }
 
   pn_connection_t *connection = pn_connector_connection(ctor);
@@ -287,7 +306,7 @@ void client_callback(pn_connector_t *cto
       printf("  payload = \"");
       while (true) {
         size_t n = pn_recv(link, msg, 1024);
-        if (n == PN_EOM) {
+        if (n == PN_EOS) {
           pn_advance(link);
           pn_disposition(delivery, PN_ACCEPTED);
           pn_settle(delivery);

Modified: qpid/proton/trunk/proton-c/src/sasl/sasl.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/sasl/sasl.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/sasl/sasl.c (original)
+++ qpid/proton/trunk/proton-c/src/sasl/sasl.c Thu Apr  5 19:03:42 2012
@@ -25,16 +25,47 @@
 #include <proton/framing.h>
 #include <proton/value.h>
 #include <proton/engine.h> // XXX: just needed for PN_EOS
-#include "sasl-internal.h"
+#include <proton/sasl.h>
 #include "protocol.h"
+#include "../dispatcher/dispatcher.h"
 #include "../util.h"
 
+#define SCRATCH (1024)
+
+struct pn_sasl_t {
+  pn_dispatcher_t *disp;
+  bool client;
+  bool configured;
+  char *mechanisms;
+  char *remote_mechanisms;
+  pn_binary_t *send_data;
+  pn_binary_t *recv_data;
+  pn_sasl_outcome_t outcome;
+  bool sent_init;
+  bool rcvd_init;
+  bool sent_done;
+  bool rcvd_done;
+  char scratch[SCRATCH];
+};
+
 void pn_do_init(pn_dispatcher_t *disp);
 void pn_do_mechanisms(pn_dispatcher_t *disp);
 void pn_do_challenge(pn_dispatcher_t *disp);
 void pn_do_response(pn_dispatcher_t *disp);
 void pn_do_outcome(pn_dispatcher_t *disp);
 
+#define strdup my_strdup
+
+char *my_strdup(const char *s)
+{
+  if (!s) return NULL;
+  size_t size = strlen(s);
+  char *r = malloc(size + 1);
+  memcpy(r, s, size);
+  r[size] = '\0';
+  return r;
+}
+
 pn_sasl_t *pn_sasl()
 {
   pn_sasl_t *sasl = malloc(sizeof(pn_sasl_t));
@@ -46,53 +77,108 @@ pn_sasl_t *pn_sasl()
   pn_dispatcher_action(sasl->disp, SASL_RESPONSE, "SASL-RESPONSE", pn_do_response);
   pn_dispatcher_action(sasl->disp, SASL_OUTCOME, "SASL-OUTCOME", pn_do_outcome);
 
-  sasl->init = false;
-  sasl->outcome = SASL_NONE;
-  sasl->mechanism = NULL;
-  sasl->challenge = NULL;
-  sasl->response = NULL;
+  sasl->client = false;
+  sasl->configured = false;
+  sasl->mechanisms = NULL;
+  sasl->remote_mechanisms = NULL;
+  sasl->send_data = NULL;
+  sasl->recv_data = NULL;
+  sasl->outcome = PN_SASL_NONE;
+  sasl->sent_init = false;
+  sasl->rcvd_init = false;
+  sasl->sent_done = false;
+  sasl->rcvd_done = false;
 
   return sasl;
 }
 
-void pn_sasl_mechanism_set(pn_sasl_t *sasl, const char *mechanism)
+pn_sasl_state_t pn_sasl_state(pn_sasl_t *sasl)
 {
-  if (sasl->mechanism) pn_free_symbol(sasl->mechanism);
-  sasl->mechanism = pn_symbol(mechanism);
+  if (sasl) {
+    if (!sasl->configured) return PN_SASL_CONF;
+    if (sasl->outcome == PN_SASL_NONE) {
+      return sasl->rcvd_init ? PN_SASL_STEP : PN_SASL_IDLE;
+    } else {
+      return sasl->outcome == PN_SASL_OK ? PN_SASL_PASS : PN_SASL_FAIL;
+    }
+    //    if (sasl->rcvd_init && sasl->outcome == PN_SASL_NONE) return PN_SASL_STEP;
+    //if (sasl->outcome == PN_SASL_OK) return PN_SASL_PASS;
+    //else return PN_SASL_FAIL;
+  } else {
+    return PN_SASL_FAIL;
+  }
 }
 
-const char *pn_sasl_mechanism(pn_sasl_t *sasl)
+void pn_sasl_mechanisms(pn_sasl_t *sasl, const char *mechanisms)
 {
-  if (sasl->mechanism)
-    return pn_symbol_name(sasl->mechanism);
-  else
-    return NULL;
+  if (!sasl) return;
+  sasl->mechanisms = strdup(mechanisms);
 }
 
-void pn_sasl_challenge_set(pn_sasl_t *sasl, pn_binary_t *challenge)
+const char *pn_sasl_remote_mechanisms(pn_sasl_t *sasl)
 {
-  if (sasl->challenge) pn_free_binary(sasl->challenge);
-  sasl->challenge = pn_binary_dup(challenge);
+  return sasl ? sasl->remote_mechanisms : NULL;
 }
 
-pn_binary_t *pn_sasl_challenge(pn_sasl_t *sasl)
+ssize_t pn_sasl_send(pn_sasl_t *sasl, const char *bytes, size_t size)
 {
-  return sasl->challenge;
+  if (sasl) {
+    if (sasl->send_data) {
+      // XXX: need better error
+      return PN_STATE_ERR;
+    }
+    sasl->send_data = pn_binary(bytes, size);
+    return size;
+  } else {
+    return PN_ARG_ERR;
+  }
 }
 
-void pn_sasl_response_set(pn_sasl_t *sasl, pn_binary_t *response)
+size_t pn_sasl_pending(pn_sasl_t *sasl)
 {
-  if (sasl->response) pn_free_binary(sasl->response);
-  sasl->response = pn_binary_dup(response);
+  if (sasl && sasl->recv_data) {
+    return pn_binary_size(sasl->recv_data);
+  } else {
+    return 0;
+  }
 }
 
-pn_binary_t *pn_sasl_response(pn_sasl_t *sasl)
+ssize_t pn_sasl_recv(pn_sasl_t *sasl, char *bytes, size_t size)
 {
-  return sasl->response;
+  if (!sasl) return PN_ARG_ERR;
+
+  if (sasl->recv_data) {
+    ssize_t result = pn_binary_get(sasl->recv_data, bytes, size);
+    if (result >= 0) {
+      pn_free_binary(sasl->recv_data);
+      sasl->recv_data = NULL;
+    }
+    return result;
+  } else {
+    return PN_EOS;
+  }
 }
 
-void pn_sasl_client(pn_sasl_t *sasl, const char *mechanism, const char *username, const char *password)
+void pn_sasl_client(pn_sasl_t *sasl)
 {
+  if (sasl) {
+    sasl->client = true;
+    sasl->configured = true;
+  }
+}
+
+void pn_sasl_server(pn_sasl_t *sasl)
+{
+  if (sasl) {
+    sasl->client = false;
+    sasl->configured = true;
+  }
+}
+
+void pn_sasl_plain(pn_sasl_t *sasl, const char *username, const char *password)
+{
+  if (!sasl) return;
+
   const char *user = username ? username : "";
   const char *pass = password ? password : "";
   size_t usize = strlen(user);
@@ -105,34 +191,21 @@ void pn_sasl_client(pn_sasl_t *sasl, con
   iresp[usize + 1] = 0;
   memmove(iresp + usize + 2, pass, psize);
 
-  pn_init_frame(sasl->disp);
-  pn_field(sasl->disp, SASL_INIT_MECHANISM, pn_from_symbol(pn_symbol(mechanism)));
-  pn_field(sasl->disp, SASL_INIT_INITIAL_RESPONSE, pn_from_binary(pn_binary(iresp, size)));
-  pn_post_frame(sasl->disp, 0, SASL_INIT);
-  sasl->init = true;
-}
-
-void pn_sasl_server(pn_sasl_t *sasl)
-{
-  pn_init_frame(sasl->disp);
-  pn_field(sasl->disp, SASL_MECHANISMS_SASL_SERVER_MECHANISMS,
-           pn_value("@s[ss]", "PLAIN", "ANONYMOUS"));
-  pn_post_frame(sasl->disp, 0, SASL_MECHANISMS);
-  sasl->init = true;
+  pn_sasl_mechanisms(sasl, "PLAIN");
+  pn_sasl_send(sasl, iresp, size);
+  pn_sasl_client(sasl);
 }
 
-void pn_sasl_auth(pn_sasl_t *sasl, pn_sasl_outcome_t outcome)
+void pn_sasl_done(pn_sasl_t *sasl, pn_sasl_outcome_t outcome)
 {
-  sasl->outcome = outcome;
-
-  pn_init_frame(sasl->disp);
-  pn_field(sasl->disp, SASL_OUTCOME_CODE, pn_value("B", outcome));
-  pn_post_frame(sasl->disp, 0, SASL_OUTCOME);
+  if (sasl) {
+    sasl->outcome = outcome;
+  }
 }
 
-bool pn_sasl_init(pn_sasl_t *sasl)
+pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl)
 {
-  return sasl->init;
+  return sasl ? sasl->outcome : PN_SASL_NONE;
 }
 
 void pn_sasl_trace(pn_sasl_t *sasl, pn_trace_t trace)
@@ -142,17 +215,92 @@ void pn_sasl_trace(pn_sasl_t *sasl, pn_t
 
 void pn_sasl_destroy(pn_sasl_t *sasl)
 {
-  pn_sasl_mechanism_set(sasl, NULL);
-  pn_sasl_challenge_set(sasl, NULL);
-  pn_sasl_response_set(sasl, NULL);
+  free(sasl->mechanisms);
+  free(sasl->remote_mechanisms);
+  pn_free_binary(sasl->send_data);
+  pn_free_binary(sasl->recv_data);
   pn_dispatcher_destroy(sasl->disp);
   free(sasl);
 }
 
+void pn_client_init(pn_sasl_t *sasl)
+{
+  pn_init_frame(sasl->disp);
+  pn_field(sasl->disp, SASL_INIT_MECHANISM, pn_from_symbol(pn_symbol(sasl->mechanisms)));
+  if (sasl->send_data) {
+    pn_field(sasl->disp, SASL_INIT_INITIAL_RESPONSE, pn_from_binary(sasl->send_data));
+    sasl->send_data = NULL;
+  }
+  pn_post_frame(sasl->disp, 0, SASL_INIT);
+}
+
+void pn_server_init(pn_sasl_t *sasl)
+{
+  // XXX
+  pn_array_t *mechs = pn_array(SYMBOL, 16);
+  if (sasl->mechanisms) {
+    char *start = sasl->mechanisms;
+    char *end = start;
+
+    while (*end) {
+      if (*end == ' ') {
+        if (start != end) {
+          *end = '\0';
+          pn_array_add(mechs, pn_value("s", start));
+        }
+        end++;
+        start = end;
+      } else {
+        end++;
+      }
+    }
+
+    if (start != end) {
+      pn_array_add(mechs, pn_value("s", start));
+    }
+  }
+
+  pn_init_frame(sasl->disp);
+  pn_field(sasl->disp, SASL_MECHANISMS_SASL_SERVER_MECHANISMS, pn_from_array(mechs));
+  pn_post_frame(sasl->disp, 0, SASL_MECHANISMS);
+}
+
+void pn_server_done(pn_sasl_t *sasl)
+{
+  pn_init_frame(sasl->disp);
+  pn_field(sasl->disp, SASL_OUTCOME_CODE, pn_value("B", sasl->outcome));
+  pn_post_frame(sasl->disp, 0, SASL_OUTCOME);
+}
+
+void pn_sasl_process(pn_sasl_t *sasl)
+{
+  if (!sasl->configured) return;
+
+  if (!sasl->sent_init) {
+    if (sasl->client) {
+      pn_client_init(sasl);
+    } else {
+      pn_server_init(sasl);
+    }
+    sasl->sent_init = true;
+  }
+
+  if (!sasl->client && sasl->outcome != PN_SASL_NONE && !sasl->sent_done) {
+    pn_server_done(sasl);
+    sasl->sent_done = true;
+    sasl->rcvd_done = true;
+  }
+}
+
 ssize_t pn_sasl_input(pn_sasl_t *sasl, char *bytes, size_t available)
 {
-  if (sasl->outcome != SASL_NONE) {
-    return PN_EOS;
+  if (sasl->rcvd_done) {
+    if (pn_sasl_state(sasl) == PN_SASL_PASS) {
+      return PN_EOS;
+    } else {
+      // XXX: should probably do something better here
+      return PN_ERR;
+    }
   } else {
     return pn_dispatcher_input(sasl->disp, bytes, available);
   }
@@ -160,30 +308,33 @@ ssize_t pn_sasl_input(pn_sasl_t *sasl, c
 
 ssize_t pn_sasl_output(pn_sasl_t *sasl, char *bytes, size_t size)
 {
-  if (sasl->disp->available == 0 && sasl->outcome != SASL_NONE) {
-    return PN_EOS;
+  pn_sasl_process(sasl);
+
+  if (sasl->disp->available == 0 && sasl->sent_done) {
+    if (pn_sasl_state(sasl) == PN_SASL_PASS) {
+      return PN_EOS;
+    } else {
+      // XXX: should probably do something better here
+      return PN_ERR;
+    }
   } else {
     return pn_dispatcher_output(sasl->disp, bytes, size);
   }
 }
 
-pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl)
-{
-  return sasl->outcome;
-}
-
 void pn_do_init(pn_dispatcher_t *disp)
 {
   pn_sasl_t *sasl = disp->context;
   pn_symbol_t *mech = pn_to_symbol(pn_list_get(disp->args, SASL_INIT_MECHANISM));
-  pn_sasl_mechanism_set(sasl, pn_symbol_name(mech));
-  pn_sasl_response_set(sasl, pn_to_binary(pn_list_get(disp->args, SASL_INIT_INITIAL_RESPONSE)));
+  sasl->remote_mechanisms = strdup(pn_symbol_name(mech));
+  sasl->recv_data = pn_binary_dup(pn_to_binary(pn_list_get(disp->args, SASL_INIT_INITIAL_RESPONSE)));
+  sasl->rcvd_init = true;
 }
 
 void pn_do_mechanisms(pn_dispatcher_t *disp)
 {
-  //pn_sasl_t *sasl = disp->context;
-  
+  pn_sasl_t *sasl = disp->context;
+  sasl->rcvd_init = true;
 }
 
 void pn_do_challenge(pn_dispatcher_t *disp)
@@ -200,4 +351,6 @@ void pn_do_outcome(pn_dispatcher_t *disp
 {
   pn_sasl_t *sasl = disp->context;
   sasl->outcome = pn_to_uint8(pn_list_get(disp->args, SASL_OUTCOME_CODE));
+  sasl->rcvd_done = true;
+  sasl->sent_done = true;
 }

Modified: qpid/proton/trunk/proton-c/src/types/array.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/types/array.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/types/array.c (original)
+++ qpid/proton/trunk/proton-c/src/types/array.c Thu Apr  5 19:03:42 2012
@@ -21,6 +21,7 @@
 
 #include <proton/util.h>
 #include <arpa/inet.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include "encodings.h"
 #include "value-internal.h"
@@ -90,6 +91,17 @@ pn_array_t *pn_array(enum TYPE type, int
   return l;
 }
 
+int pn_array_add(pn_array_t *a, pn_value_t v)
+{
+  if (a->capacity <= a->size) {
+    fprintf(stderr, "wah!\n");
+    return -1;
+  }
+
+  a->values[a->size++] = v;
+  return 0;
+}
+
 void pn_free_array(pn_array_t *a)
 {
   free(a);

Modified: qpid/proton/trunk/proton-c/src/types/binary.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/types/binary.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/types/binary.c (original)
+++ qpid/proton/trunk/proton-c/src/types/binary.c Thu Apr  5 19:03:42 2012
@@ -19,6 +19,7 @@
  *
  */
 
+#include <proton/errors.h>
 #include <proton/codec.h>
 #include <string.h>
 #include <stdlib.h>
@@ -49,6 +50,16 @@ const char *pn_binary_bytes(pn_binary_t 
   return b->bytes;
 }
 
+ssize_t pn_binary_get(pn_binary_t *b, char *bytes, size_t size)
+{
+  if (size < b->size) {
+    return PN_OVERFLOW;
+  } else {
+    memmove(bytes, b->bytes, b->size);
+    return b->size;
+  }
+}
+
 uintptr_t pn_hash_binary(pn_binary_t *b)
 {
   uintptr_t hash = 0;

Modified: qpid/proton/trunk/proton-c/src/types/value.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/types/value.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/types/value.c (original)
+++ qpid/proton/trunk/proton-c/src/types/value.c Thu Apr  5 19:03:42 2012
@@ -358,6 +358,11 @@ void *pn_to_ref(pn_value_t v)
   return v.u.as_ref;
 }
 
+pn_value_t pn_from_array(pn_array_t *a)
+{
+  return (pn_value_t) {.type = ARRAY, .u.as_array = a};
+}
+
 pn_value_t pn_from_list(pn_list_t *l)
 {
   return (pn_value_t) {.type = LIST, .u.as_list = l};
@@ -572,6 +577,7 @@ size_t pn_format_sizeof(pn_value_t v)
   }
 }
 
+// XXX: this should delegate to stuff in codec
 size_t pn_encode_sizeof(pn_value_t v)
 {
   switch (v.type)

Modified: qpid/proton/trunk/proton-c/src/util.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/util.c?rev=1310014&r1=1310013&r2=1310014&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/util.c (original)
+++ qpid/proton/trunk/proton-c/src/util.c Thu Apr  5 19:03:42 2012
@@ -28,9 +28,7 @@
 #include <stdint.h>
 #include <ctype.h>
 #include <string.h>
-
-// XXX: should centralize error codes
-#define PN_OVERFLOW (-1)
+#include <proton/errors.h>
 
 ssize_t pn_quote_data(char *dst, size_t capacity, const char *src, size_t size)
 {



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org