s3:smbd: setup a shared memory area for the signing state
authorStefan Metzmacher <metze@samba.org>
Mon, 22 Mar 2010 08:45:43 +0000 (09:45 +0100)
committerMichael Adam <obnox@samba.org>
Fri, 26 Mar 2010 11:43:05 +0000 (12:43 +0100)
metze
(cherry picked from commit 79e5e3dda7178c4d3c5952a48474d6dcafba91ec)

source3/smbd/signing.c

index 5bee361a3453c8dafd08e9b9a37e7f635fe1b8fa..9817013a8c7d7895b973f06d30750251fed2a3ba 100644 (file)
@@ -87,6 +87,62 @@ void srv_cancel_sign_response(struct smbd_server_connection *conn)
        smb_signing_cancel_reply(conn->signing_state, true);
 }
 
+struct smbd_shm_signing {
+       size_t shm_size;
+       uint8_t *shm_ptr;
+
+       /* we know the signing engine will only allocate 2 chunks */
+       uint8_t *ptr1;
+       size_t len1;
+       uint8_t *ptr2;
+       size_t len2;
+};
+
+static void *smbd_shm_signing_alloc(TALLOC_CTX *mem_ctx, size_t len)
+{
+       struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
+                                    struct smbd_shm_signing);
+
+       if (s->ptr1 == NULL) {
+               s->len1 = len;
+               if (len % 8) {
+                       s->len1 += (8 - (len % 8));
+               }
+               if (s->len1 > s->shm_size) {
+                       s->len1 = 0;
+                       errno = ENOMEM;
+                       return NULL;
+               }
+               s->ptr1 = s->shm_ptr;
+               return s->ptr1;
+       }
+
+       if (s->ptr2 == NULL) {
+               s->len2 = len;
+               if (s->len2 > (s->shm_size - s->len1)) {
+                       s->len2 = 0;
+                       errno = ENOMEM;
+                       return NULL;
+               }
+               s->ptr2 = s->shm_ptr + s->len1;
+               return s->ptr2;
+       }
+
+       errno = ENOMEM;
+       return NULL;
+}
+
+static void smbd_shm_signing_free(TALLOC_CTX *mem_ctx, void *ptr)
+{
+       struct smbd_shm_signing *s = talloc_get_type_abort(mem_ctx,
+                                    struct smbd_shm_signing);
+
+       if (s->ptr2 == ptr) {
+               s->ptr2 = NULL;
+               s->len2 = 0;
+       }
+}
+
 /***********************************************************
  Called by server negprot when signing has been negotiated.
 ************************************************************/
@@ -109,6 +165,30 @@ bool srv_init_signing(struct smbd_server_connection *conn)
                break;
        }
 
+       if (lp_async_smb_echo_handler()) {
+               struct smbd_shm_signing *s;
+
+               /* setup the signing state in shared memory */
+               s = talloc_zero(smbd_event_context(), struct smbd_shm_signing);
+               if (s == NULL) {
+                       return false;
+               }
+               s->shm_size = 4096;
+               s->shm_ptr = (uint8_t *)allocate_anonymous_shared(s->shm_size);
+               if (s->shm_ptr == NULL) {
+                       talloc_free(s);
+                       return false;
+               }
+               conn->signing_state = smb_signing_init_ex(s,
+                                                       allowed, mandatory,
+                                                       smbd_shm_signing_alloc,
+                                                       smbd_shm_signing_free);
+               if (!conn->signing_state) {
+                       return false;
+               }
+               return true;
+       }
+
        conn->signing_state = smb_signing_init(smbd_event_context(),
                                               allowed, mandatory);
        if (!conn->signing_state) {