s4-gensec Don't upgrade all DIGEST-MD5 connections to seal
[kai/samba.git] / source4 / auth / gensec / cyrus_sasl.c
index da96d239af624bf7c928ab4798c8d71a0bc44fd7..c95bae91fe5d0032ff3337be875bdc6167cf476f 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/tsocket/tsocket.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
 #include "auth/gensec/gensec_proto.h"
-#include "lib/socket/socket.h"
 #include <sasl/sasl.h>
 
 struct gensec_sasl_state {
        sasl_conn_t *conn;
        int step;
+       bool wrap;
 };
 
 static NTSTATUS sasl_nt_status(int sasl_ret) 
@@ -117,15 +118,15 @@ static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security
        struct gensec_sasl_state *gensec_sasl_state;
        const char *service = gensec_get_target_service(gensec_security);
        const char *target_name = gensec_get_target_hostname(gensec_security);
-       struct socket_address *local_socket_addr = gensec_get_my_addr(gensec_security);
-       struct socket_address *remote_socket_addr = gensec_get_peer_addr(gensec_security);
+       const struct tsocket_address *tlocal_addr = gensec_get_local_address(gensec_security);
+       const struct tsocket_address *tremote_addr = gensec_get_remote_address(gensec_security);
        char *local_addr = NULL;
        char *remote_addr = NULL;
        int sasl_ret;
 
        sasl_callback_t *callbacks;
 
-       gensec_sasl_state = talloc(gensec_security, struct gensec_sasl_state);
+       gensec_sasl_state = talloc_zero(gensec_security, struct gensec_sasl_state);
        if (!gensec_sasl_state) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -153,18 +154,18 @@ static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security
 
        gensec_security->private_data = gensec_sasl_state;
 
-       if (local_socket_addr) {
-               local_addr = talloc_asprintf(gensec_sasl_state, 
-                                            "%s;%d",
-                                            local_socket_addr->addr, 
-                                            local_socket_addr->port);
+       if (tlocal_addr) {
+               local_addr = talloc_asprintf(gensec_sasl_state,
+                               "%s;%d",
+                               tsocket_address_inet_addr_string(tlocal_addr, gensec_sasl_state),
+                               tsocket_address_inet_port(tlocal_addr));
        }
 
-       if (remote_socket_addr) {
-               remote_addr = talloc_asprintf(gensec_sasl_state, 
-                                            "%s;%d",
-                                            remote_socket_addr->addr, 
-                                            remote_socket_addr->port);
+       if (tremote_addr) {
+               remote_addr = talloc_asprintf(gensec_sasl_state,
+                               "%s;%d",
+                               tsocket_address_inet_addr_string(tremote_addr, gensec_sasl_state),
+                               tsocket_address_inet_port(tremote_addr));
        }
        gensec_sasl_state->step = 0;
 
@@ -173,26 +174,27 @@ static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security
                                   local_addr, remote_addr, callbacks, 0,
                                   &gensec_sasl_state->conn);
        
-       if (sasl_ret == SASL_OK || sasl_ret == SASL_CONTINUE) {
+       if (sasl_ret == SASL_OK) {
                sasl_security_properties_t props;
                talloc_set_destructor(gensec_sasl_state, gensec_sasl_dispose);
-
+               
                ZERO_STRUCT(props);
                if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
                        props.min_ssf = 1;
+                       props.max_ssf = 1;
+                       props.maxbufsize = 65536;
+                       gensec_sasl_state->wrap = true;
                }
                if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
                        props.min_ssf = 40;
-               }
-               
-               props.max_ssf = UINT_MAX;
-               props.maxbufsize = 65536;
-               sasl_ret = sasl_setprop(gensec_sasl_state->conn, SASL_SEC_PROPS, &props);
-               if (sasl_ret != SASL_OK) {
-                       return sasl_nt_status(sasl_ret);
+                       props.max_ssf = UINT_MAX;
+                       props.maxbufsize = 65536;
+                       gensec_sasl_state->wrap = true;
                }
 
-       } else {
+               sasl_ret = sasl_setprop(gensec_sasl_state->conn, SASL_SEC_PROPS, &props);
+       }
+       if (sasl_ret != SASL_OK) {
                DEBUG(1, ("GENSEC SASL: client_new failed: %s\n", sasl_errdetail(gensec_sasl_state->conn)));
        }
        return sasl_nt_status(sasl_ret);
@@ -281,7 +283,14 @@ static bool gensec_sasl_have_feature(struct gensec_security *gensec_security,
        struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data,
                                                                      struct gensec_sasl_state);
        sasl_ssf_t ssf;
-       int sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF,
+       int sasl_ret;
+
+       /* If we did not elect to wrap, then we have neither sign nor seal, no matter what the SSF claims */
+       if (!gensec_sasl_state->wrap) {
+               return false;
+       }
+       
+       sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF,
                        (const void**)&ssf);
        if (sasl_ret != SASL_OK) {
                return false;