r4547: - added talloc_new(ctx) macro that is a neater form of the common talloc(ctx...
[kamenim/samba.git] / source4 / ldap_server / ldap_server.c
index dcce32874d471addf655ad5b5b5ff8d60ee18c5b..a301c14084ea019044af0a28fd95f62c9cd852d5 100644 (file)
 */
 
 #include "includes.h"
+#include "events.h"
+#include "auth/auth.h"
+#include "dlinklist.h"
+#include "asn_1.h"
+#include "ldap_server/ldap_server.h"
 
 /*
   close the socket and shutdown a server_context
@@ -34,11 +39,11 @@ static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, c
 */
 static void add_socket(struct server_service *service, 
                       const struct model_ops *model_ops, 
-                      struct in_addr *ifip)
+                      struct ipv4_addr *ifip)
 {
        struct server_socket *srv_sock;
        uint16_t port = 389;
-       char *ip_str = talloc_strdup(service, inet_ntoa(*ifip));
+       char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip));
 
        srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
 
@@ -99,7 +104,7 @@ static void ldapsrv_init(struct server_service *service,
                   socket per interface and bind to only these.
                */
                for(i = 0; i < num_interfaces; i++) {
-                       struct in_addr *ifip = iface_n_ip(i);
+                       struct ipv4_addr *ifip = iface_n_ip(i);
 
                        if (ifip == NULL) {
                                DEBUG(0,("ldapsrv_init: interface %d has NULL "
@@ -110,13 +115,11 @@ static void ldapsrv_init(struct server_service *service,
                        add_socket(service, model_ops, ifip);
                }
        } else {
-               struct in_addr *ifip;
+               struct ipv4_addr ifip;
 
                /* Just bind to lp_socket_address() (usually 0.0.0.0) */
-               ifip = interpret_addr2(service, lp_socket_address());
-               add_socket(service, model_ops, ifip);
-
-               talloc_destroy(ifip);
+               ifip = interpret_addr2(lp_socket_address());
+               add_socket(service, model_ops, &ifip);
        }
 }
 
@@ -128,7 +131,7 @@ static void ldapsrv_init(struct server_service *service,
 void ldapsrv_consumed_from_buf(struct rw_buffer *buf,
                                   size_t length)
 {
-       memcpy(buf->data, buf->data+length, buf->length-length);
+       memmove(buf->data, buf->data+length, buf->length-length);
        buf->length -= length;
 }
 
@@ -157,12 +160,20 @@ static BOOL read_into_buf(struct socket_context *sock, struct rw_buffer *buf)
        NTSTATUS status;
        DATA_BLOB tmp_blob;
        BOOL ret;
+       size_t nread;
 
-       status = socket_recv(sock, sock, &tmp_blob, 1024, 0);
-       if (!NT_STATUS_IS_OK(status)) {
+       tmp_blob = data_blob_talloc(sock, NULL, 1024);
+       if (tmp_blob.data == NULL) {
+               return False;
+       }
+
+       status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
+       if (NT_STATUS_IS_ERR(status)) {
                DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
+               talloc_free(tmp_blob.data);
                return False;
        }
+       tmp_blob.length = nread;
 
        ret = ldapsrv_append_to_buf(buf, tmp_blob.data, tmp_blob.length);
 
@@ -175,31 +186,45 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
 {
        NTSTATUS status;
        DATA_BLOB tmp_blob;
-       DATA_BLOB creds;
+       DATA_BLOB wrapped;
+       DATA_BLOB unwrapped;
        BOOL ret;
        uint8_t *buf;
-       int buf_length, sasl_length;
+       size_t buf_length, sasl_length;
        struct socket_context *sock = conn->connection->socket;
        TALLOC_CTX *mem_ctx;
+       size_t nread;
 
-       if (!conn->gensec || !conn->session_info ||
-          !(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
-            gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
+       if (!conn->gensec) {
+               return read_into_buf(sock, &conn->in_buffer);
+       }
+       if (!conn->session_info) {
+               return read_into_buf(sock, &conn->in_buffer);
+       }
+       if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
                return read_into_buf(sock, &conn->in_buffer);
        }
 
-       mem_ctx = talloc(conn, 0);
+       mem_ctx = talloc_new(conn);
        if (!mem_ctx) {
                DEBUG(0,("no memory\n"));
                return False;
        }
 
-       status = socket_recv(sock, mem_ctx, &tmp_blob, 1024, 0);
-       if (!NT_STATUS_IS_OK(status)) {
+       tmp_blob = data_blob_talloc(mem_ctx, NULL, 1024);
+       if (tmp_blob.data == NULL) {
+               talloc_free(mem_ctx);
+               return False;
+       }
+
+       status = socket_recv(sock, tmp_blob.data, tmp_blob.length, &nread, 0);
+       if (NT_STATUS_IS_ERR(status)) {
                DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
                return False;
        }
+       tmp_blob.length = nread;
 
        ret = ldapsrv_append_to_buf(&conn->sasl_in_buffer, tmp_blob.data, tmp_blob.length);
        if (!ret) {
@@ -217,47 +242,25 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
 
        sasl_length = RIVAL(buf, 0);
 
-       if (buf_length < (4 + sasl_length)) {
+       if ((buf_length - 4) < sasl_length) {
                /* not enough yet */
                talloc_free(mem_ctx);
                return True;
        }
 
-       creds.data = buf + 4;
-       creds.length = gensec_sig_size(conn->gensec);
+       wrapped.data = buf + 4;
+       wrapped.length = sasl_length;
 
-       if (creds.length > sasl_length) {
-               /* invalid packet? */
+       status = gensec_unwrap(conn->gensec, mem_ctx,
+                              &wrapped, 
+                              &unwrapped);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
                return False;
        }
 
-       tmp_blob.data = buf + (4 + creds.length);
-       tmp_blob.length = (4 + sasl_length) - (4 + creds.length);
-
-       if (gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL)) {
-               status = gensec_unseal_packet(conn->gensec, mem_ctx,
-                                             tmp_blob.data, tmp_blob.length,
-                                             tmp_blob.data, tmp_blob.length,
-                                             &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       } else {
-               status = gensec_check_packet(conn->gensec, mem_ctx,
-                                             tmp_blob.data, tmp_blob.length,
-                                             tmp_blob.data, tmp_blob.length,
-                                             &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_check_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       }
-
-       ret = ldapsrv_append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length);
+       ret = ldapsrv_append_to_buf(&conn->in_buffer, unwrapped.data, unwrapped.length);
        if (!ret) {
                talloc_free(mem_ctx);
                return False;
@@ -278,7 +281,7 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
        tmp_blob.data = buf->data;
        tmp_blob.length = buf->length;
 
-       status = socket_send(sock, sock, &tmp_blob, &sendlen, 0);
+       status = socket_send(sock, &tmp_blob, &sendlen, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
                return False;
@@ -292,77 +295,68 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
 static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
 {
        NTSTATUS status;
+       DATA_BLOB wrapped;
        DATA_BLOB tmp_blob;
-       DATA_BLOB creds;
        DATA_BLOB sasl;
        size_t sendlen;
        BOOL ret;
        struct socket_context *sock = conn->connection->socket;
        TALLOC_CTX *mem_ctx;
 
-       if (!conn->gensec || !conn->session_info ||
-          !(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
-            gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
+
+       if (!conn->gensec) {
+               return write_from_buf(sock, &conn->out_buffer);
+       }
+       if (!conn->session_info) {
+               return write_from_buf(sock, &conn->out_buffer);
+       }
+       if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
                return write_from_buf(sock, &conn->out_buffer);
        }
 
-       mem_ctx = talloc(conn, 0);
+       mem_ctx = talloc_new(conn);
        if (!mem_ctx) {
                DEBUG(0,("no memory\n"));
                return False;
        }
 
-       tmp_blob.data = conn->out_buffer.data;
-       tmp_blob.length = conn->out_buffer.length;
-
-       if (tmp_blob.length == 0) {
+       if (conn->out_buffer.length == 0) {
                goto nodata;
        }
 
-       if (gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL)) {
-               status = gensec_seal_packet(conn->gensec, mem_ctx,
-                                           tmp_blob.data, tmp_blob.length,
-                                           tmp_blob.data, tmp_blob.length,
-                                           &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       } else {
-               status = gensec_sign_packet(conn->gensec, mem_ctx,
-                                           tmp_blob.data, tmp_blob.length,
-                                           tmp_blob.data, tmp_blob.length,
-                                           &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_sign_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }               
+       tmp_blob.data = conn->out_buffer.data;
+       tmp_blob.length = conn->out_buffer.length;
+       status = gensec_wrap(conn->gensec, mem_ctx,
+                            &tmp_blob,
+                            &wrapped);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status)));
+               talloc_free(mem_ctx);
+               return False;
        }
 
-       sasl = data_blob_talloc(mem_ctx, NULL, 4 + creds.length + tmp_blob.length);
+       sasl = data_blob_talloc(mem_ctx, NULL, 4 + wrapped.length);
        if (!sasl.data) {
                DEBUG(0,("no memory\n"));
                talloc_free(mem_ctx);
                return False;
        }
 
-       RSIVAL(sasl.data, 0, creds.length + tmp_blob.length);
-       memcpy(sasl.data + 4, creds.data, creds.length);
-       memcpy(sasl.data + 4 + creds.length, tmp_blob.data, tmp_blob.length);
+       RSIVAL(sasl.data, 0, wrapped.length);
+       memcpy(sasl.data + 4, wrapped.data, wrapped.length);
 
        ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length);
        if (!ret) {
                talloc_free(mem_ctx);
                return False;
        }
-       ldapsrv_consumed_from_buf(&conn->out_buffer, tmp_blob.length);
+       ldapsrv_consumed_from_buf(&conn->out_buffer, conn->out_buffer.length);
 nodata:
        tmp_blob.data = conn->sasl_out_buffer.data;
        tmp_blob.length = conn->sasl_out_buffer.length;
 
-       status = socket_send(sock, mem_ctx, &tmp_blob, &sendlen, 0);
+       status = socket_send(sock, &tmp_blob, &sendlen, 0);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
@@ -422,14 +416,14 @@ NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn)
 /*
   called when a LDAP socket becomes readable
 */
-static void ldapsrv_recv(struct server_connection *conn, time_t t,
+static void ldapsrv_recv(struct server_connection *conn, struct timeval t,
                         uint16_t flags)
 {
        struct ldapsrv_connection *ldap_conn = conn->private_data;
        uint8_t *buf;
-       int buf_length, msg_length;
+       size_t buf_length, msg_length;
        DATA_BLOB blob;
-       ASN1_DATA data;
+       struct asn1_data data;
        struct ldapsrv_call *call;
        NTSTATUS status;
 
@@ -518,7 +512,7 @@ static void ldapsrv_recv(struct server_connection *conn, time_t t,
 /*
   called when a LDAP socket becomes writable
 */
-static void ldapsrv_send(struct server_connection *conn, time_t t,
+static void ldapsrv_send(struct server_connection *conn, struct timeval t,
                         uint16_t flags)
 {
        struct ldapsrv_connection *ldap_conn = conn->private_data;
@@ -540,7 +534,7 @@ static void ldapsrv_send(struct server_connection *conn, time_t t,
 /*
   called when connection is idle
 */
-static void ldapsrv_idle(struct server_connection *conn, time_t t)
+static void ldapsrv_idle(struct server_connection *conn, struct timeval t)
 {
        DEBUG(10,("ldapsrv_idle: not implemented!\n"));
        return;