r18740: Some more work around srvsvc
authorSimo Sorce <idra@samba.org>
Wed, 20 Sep 2006 20:32:36 +0000 (20:32 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:19:06 +0000 (14:19 -0500)
(This used to be commit be2f4a2c44ed2b4d586f0d6e9976158f33fb29d8)

source4/rpc_server/srvsvc/dcesrv_srvsvc.c
source4/torture/rpc/srvsvc.c

index b8da68e920e7e0033cb82fa14cccd2577bb8403f..983c51f137b233c3781cdf2c0f165a6f115f21b6 100644 (file)
@@ -1101,88 +1101,45 @@ static WERROR srvsvc_NetShareGetInfo(struct dcesrv_call_state *dce_call, TALLOC_
        return WERR_UNKNOWN_LEVEL;
 }
 
-
-/* 
-  srvsvc_NetShareSetInfo 
-*/
-static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct srvsvc_NetShareSetInfo *r)
+static WERROR srvsvc_fill_share_info(struct share_info *info, int *count,
+                                       const char *share_name, int level,
+                                       const char *name,
+                                       const char *path,
+                                       const char *comment,
+                                       const char *password,
+                                       enum srvsvc_ShareType type,
+                                       int32_t max_users,
+                                       uint32_t csc_policy,
+                                       struct security_descriptor *sd)
 {
-       NTSTATUS nterr;
-       struct share_context *sctx = NULL;
-       struct share_config *scfg = NULL;
-
-       ZERO_STRUCT(r->out);
+       int i = 0;
 
-       /* TODO: - access check
-        */
-
-       if (strcmp("", r->in.share_name) == 0) {
-               return WERR_INVALID_PARAM;
-       }
-
-       nterr = share_get_context(mem_ctx, &sctx);
-       if (!NT_STATUS_IS_OK(nterr)) {
-               return ntstatus_to_werror(nterr);
-       }
-
-       switch (r->in.level) {
-       case 0:
-       {
-               return WERR_NOT_SUPPORTED;
-       }
-       case 1:
-       {
-               return WERR_NOT_SUPPORTED;
+       if (level == 501) {
+               info[i].name = SHARE_CSC_POLICY;
+               info[i].type = SHARE_INFO_INT;
+               info[i].value = talloc(info, int);
+               *((int *)info[i].value) = csc_policy;
+               i++;
        }
-       case 2:
-       {
-               struct share_info *info;
-               int count = 8;
-               int i;
+       
+       switch(level) {
 
-               /* there are no more than 8 options in struct srvsvc_NetShareInfo2 */
-               info = talloc_array(mem_ctx, struct share_info, count);
-               W_ERROR_HAVE_NO_MEMORY(info);
-
-               i = 0;
-
-               if (strcasecmp(r->in.share_name, r->in.info.info2->name) != 0) {
-                       info[i].name = SHARE_NAME;
-                       info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info2->name);
-                       W_ERROR_HAVE_NO_MEMORY(info[i].value);
-                       i++;
-               }
+       case 502:
+               /* TODO: check if unknown is csc_policy */
 
-               info[i].name = SHARE_TYPE;
-               info[i].type = SHARE_INFO_STRING;
-               switch (r->in.info.info2->type) {
-               case 0x00:
-                       info[i].value = talloc_strdup(info, "DISK");
-                       break;
-               case 0x01:
-                       info[i].value = talloc_strdup(info, "PRINTER");
-                       break;
-               case 0x03:
-                       info[i].value = talloc_strdup(info, "IPC");
-                       break;
-               default:
-                       return WERR_INVALID_PARAM;
-               }
-               W_ERROR_HAVE_NO_MEMORY(info[i].value);
-               i++;
+               /* TODO: security descriptor */
 
-               if (r->in.info.info2->path && r->in.info.info2->path[0]) {
+       case 2:
+               if (path && path[0]) {
                        info[i].name = SHARE_PATH;
                        info[i].type = SHARE_INFO_STRING;
 
                        /* Windows will send a path in a form of C:\example\path */
-                       if (r->in.info.info2->path[1] == ':') {
-                               info[i].value = talloc_strdup(info, &r->in.info.info2->path[2]);
+                       if (path[1] == ':') {
+                               info[i].value = talloc_strdup(info, &path[2]);
                        } else {
                                /* very strange let's try to set as is */
-                               info[i].value = talloc_strdup(info, r->in.info.info2->path);
+                               info[i].value = talloc_strdup(info, path);
                        }
                        W_ERROR_HAVE_NO_MEMORY(info[i].value);
                        all_string_sub((char *)info[i].value, "\\", "/", 0);
@@ -1190,19 +1147,10 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_
                        i++;
                }
 
-               if (r->in.info.info2->comment && r->in.info.info2->comment[0]) {
-                       info[i].name = SHARE_COMMENT;
-                       info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info2->comment);
-                       W_ERROR_HAVE_NO_MEMORY(info[i].value);
-
-                       i++;
-               }
-
-               if (r->in.info.info2->password && r->in.info.info2->password[0]) {
+               if (password && password[0]) {
                        info[i].name = SHARE_PASSWORD;
                        info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info502->password);
+                       info[i].value = talloc_strdup(info, password);
                        W_ERROR_HAVE_NO_MEMORY(info[i].value);
 
                        i++;
@@ -1211,49 +1159,14 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_
                info[i].name = SHARE_MAX_CONNECTIONS;
                info[i].type = SHARE_INFO_INT;
                info[i].value = talloc(info, int);
-               *((int *)info[i].value) = r->in.info.info2->max_users;
+               *((int *)info[i].value) = max_users;
                i++;
 
-               /* TODO: security descriptor */
-
-               nterr = share_set(sctx, r->in.share_name, info, i);
-               if (!NT_STATUS_IS_OK(nterr)) {
-                       return ntstatus_to_werror(nterr);
-               }
-
-               if (r->in.parm_error) {
-                       r->out.parm_error = r->in.parm_error;
-               }
-               
-               return WERR_OK;
-       }
        case 501:
-       {
-               return WERR_NOT_SUPPORTED;
-       }
-       case 502:
-       {
-               struct share_info *info;
-               int count = 8;
-               int i;
-
-               /* there are no more than 8 options in struct srvsvc_NetShareInfo502 */
-               info = talloc_array(mem_ctx, struct share_info, count);
-               W_ERROR_HAVE_NO_MEMORY(info);
-
-               i = 0;
-
-               if (strcasecmp(r->in.share_name, r->in.info.info502->name) != 0) {
-                       info[i].name = SHARE_NAME;
-                       info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info502->name);
-                       W_ERROR_HAVE_NO_MEMORY(info[i].value);
-                       i++;
-               }
-
+       case 1:
                info[i].name = SHARE_TYPE;
                info[i].type = SHARE_INFO_STRING;
-               switch (r->in.info.info502->type) {
+               switch (type) {
                case 0x00:
                        info[i].value = talloc_strdup(info, "DISK");
                        break;
@@ -1269,74 +1182,171 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_
                W_ERROR_HAVE_NO_MEMORY(info[i].value);
                i++;
 
-               if (r->in.info.info502->path && r->in.info.info502->path[0]) {
-                       info[i].name = SHARE_PATH;
+       case 1004:
+               if (comment) {
+                       info[i].name = SHARE_COMMENT;
                        info[i].type = SHARE_INFO_STRING;
-
-                       /* Windows will send a path in a form of C:\example\path */
-                       if (r->in.info.info2->path[1] == ':') {
-                               info[i].value = talloc_strdup(info, &r->in.info.info502->path[2]);
-                       } else {
-                               /* very strange let's try to set as is */
-                               info[i].value = talloc_strdup(info, r->in.info.info502->path);
-                       }
+                       info[i].value = talloc_strdup(info, comment);
                        W_ERROR_HAVE_NO_MEMORY(info[i].value);
-                       all_string_sub((char *)info[i].value, "\\", "/", 0);
 
                        i++;
                }
-
-               if (r->in.info.info502->comment && r->in.info.info502->comment[0]) {
-                       info[i].name = SHARE_COMMENT;
+       case 0:
+               if (name &&
+                   strcasecmp(share_name, name) != 0) {
+                       info[i].name = SHARE_NAME;
                        info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info502->comment);
+                       info[i].value = talloc_strdup(info, name);
                        W_ERROR_HAVE_NO_MEMORY(info[i].value);
-
                        i++;
                }
 
-               if (r->in.info.info502->password && r->in.info.info502->password[0]) {
-                       info[i].name = SHARE_PASSWORD;
-                       info[i].type = SHARE_INFO_STRING;
-                       info[i].value = talloc_strdup(info, r->in.info.info502->password);
-                       W_ERROR_HAVE_NO_MEMORY(info[i].value);
+               break;
 
-                       i++;
-               }
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
 
-               info[i].name = SHARE_MAX_CONNECTIONS;
-               info[i].type = SHARE_INFO_INT;
-               info[i].value = talloc(info, int);
-               *((int *)info[i].value) = r->in.info.info502->max_users;
-               i++;
+       *count = i;
 
-               /* TODO: security descriptor */
+       return WERR_OK;
+}
 
-               nterr = share_set(sctx, r->in.share_name, info, i);
-               if (!NT_STATUS_IS_OK(nterr)) {
-                       return ntstatus_to_werror(nterr);
-               }
+/* 
+  srvsvc_NetShareSetInfo 
+*/
+static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+                      struct srvsvc_NetShareSetInfo *r)
+{
+       NTSTATUS nterr;
+       WERROR status;
+       struct share_context *sctx = NULL;
+       struct share_info *info;
+       int count;
 
-               if (r->in.parm_error) {
-                       r->out.parm_error = r->in.parm_error;
+       /* TODO: - access check
+        */
+
+       /* there are no more than 10 options in all struct srvsvc_NetShareInfoXXX */
+       info = talloc_array(mem_ctx, struct share_info, 10);
+       W_ERROR_HAVE_NO_MEMORY(info);
+
+       ZERO_STRUCT(r->out);
+
+       if (strcmp("", r->in.share_name) == 0) {
+               return WERR_INVALID_PARAM;
+       }
+
+       nterr = share_get_context(mem_ctx, &sctx);
+       if (!NT_STATUS_IS_OK(nterr)) {
+               return ntstatus_to_werror(nterr);
+       }
+
+       switch (r->in.level) {
+       case 0:
+       {
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       r->in.info.info0->name,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       0,
+                                       0,
+                                       0,
+                                       NULL);
+               if (status != WERR_OK) {
+                       return status;
                }
-               
-               return WERR_OK;
+               break;
+       }
+       case 1:
+       {
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       r->in.info.info1->name,
+                                       NULL,
+                                       r->in.info.info1->comment,
+                                       NULL,
+                                       r->in.info.info1->type,
+                                       0,
+                                       0,
+                                       NULL);
+               if (status != WERR_OK) {
+                       return status;
+               }
+               break;
+       }
+       case 2:
+       {
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       r->in.info.info2->name,
+                                       r->in.info.info2->path,
+                                       r->in.info.info2->comment,
+                                       r->in.info.info2->password,
+                                       r->in.info.info2->type,
+                                       r->in.info.info2->max_users,
+                                       0,
+                                       NULL);
+               if (status != WERR_OK) {
+                       return status;
+               }
+               break;
+       }
+       case 501:
+       {
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       r->in.info.info501->name,
+                                       NULL,
+                                       r->in.info.info501->comment,
+                                       NULL,
+                                       r->in.info.info501->type,
+                                       0,
+                                       r->in.info.info501->csc_policy,
+                                       NULL);
+               if (status != WERR_OK) {
+                       return status;
+               }
+               break;
+       }
+       case 502:
+       {
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       r->in.info.info502->name,
+                                       r->in.info.info502->path,
+                                       r->in.info.info502->comment,
+                                       r->in.info.info502->password,
+                                       r->in.info.info502->type,
+                                       r->in.info.info502->max_users,
+                                       0,
+                                       r->in.info.info502->sd);
+               if (status != WERR_OK) {
+                       return status;
+               }
+               break;
        }
        case 1004:
        {
-               WERROR status;
-               union srvsvc_NetShareInfo info;
-
-               /* r->in.info.comment; */
-
-               return WERR_NOT_SUPPORTED;
+               status = srvsvc_fill_share_info(info, &count,
+                                       r->in.share_name, r->in.level,
+                                       NULL,
+                                       NULL,
+                                       r->in.info.info1004->comment,
+                                       NULL,
+                                       0,
+                                       0,
+                                       0,
+                                       NULL);
+               if (status != WERR_OK) {
+                       return status;
+               }
+               break;
        }
        case 1005:
        {
-               WERROR status;
-               union srvsvc_NetShareInfo info;
-
                /* r->in.info.dfs_flags; */
                
                if (r->in.parm_error) {
@@ -1349,7 +1359,16 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_
                return WERR_UNKNOWN_LEVEL;
        }
 
-       return WERR_UNKNOWN_LEVEL;
+       nterr = share_set(sctx, r->in.share_name, info, count);
+       if (!NT_STATUS_IS_OK(nterr)) {
+               return ntstatus_to_werror(nterr);
+       }
+
+       if (r->in.parm_error) {
+               r->out.parm_error = r->in.parm_error;
+       }
+               
+       return WERR_OK;
 }
 
 
index 685a71cfa3d37eb6d3fbecf13055c2f0d5f733f6..696a42d167b1b906c91655795b54173dd3157780 100644 (file)
@@ -500,6 +500,230 @@ static BOOL test_NetShareGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return ret;
 }
 
+static BOOL test_NetShareAddSetDel(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
+{
+       NTSTATUS status;
+       struct srvsvc_NetShareAdd a;
+       struct srvsvc_NetShareSetInfo r;
+       struct srvsvc_NetShareGetInfo q;
+       struct srvsvc_NetShareDel d;
+       struct {
+               uint32_t level;
+               WERROR expected;
+       } levels[] = {
+                { 0,           WERR_UNKNOWN_LEVEL },
+                { 1,           WERR_OK },
+                { 2,           WERR_OK },
+                { 501,         WERR_UNKNOWN_LEVEL },
+                { 502,         WERR_OK },
+                { 1004,        WERR_OK },
+                { 1005,        WERR_OK },
+                { 1006,        WERR_OK },
+/*              { 1007,        WERR_OK }, */
+                { 1501,        WERR_OK },
+       };
+       int i;
+       BOOL ret = True;
+
+       a.in.server_unc = r.in.server_unc = q.in.server_unc = d.in.server_unc =
+               talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+       r.in.share_name = talloc_strdup(mem_ctx, "testshare");
+
+       a.in.level = 2;
+       a.in.info.info2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
+       a.in.info.info2->name = r.in.share_name;
+       a.in.info.info2->type = STYPE_DISKTREE;
+       a.in.info.info2->comment = talloc_strdup(mem_ctx, "test comment");
+       a.in.info.info2->permissions = 123434566;
+       a.in.info.info2->max_users = -1;
+       a.in.info.info2->current_users = 0;
+       a.in.info.info2->path = talloc_strdup(mem_ctx, "C:\\");
+       a.in.info.info2->password = NULL;
+
+       a.in.parm_error = NULL;
+
+       status = dcerpc_srvsvc_NetShareAdd(p, mem_ctx, &a);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("NetShareAdd level 2 on share 'testshare' failed - %s\n",
+                        nt_errstr(status));
+               return False;
+       } else if (!W_ERROR_EQUAL(a.out.result, WERR_OK)) {
+               d_printf("NetShareAdd level 2 on share 'testshare' failed - %s\n",
+                        win_errstr(a.out.result));
+               return False;
+       }
+
+       r.in.parm_error = NULL;
+
+       q.in.level = 502;
+
+       for (i = 0; i < ARRAY_SIZE(levels); i++) {
+
+               r.in.level = levels[i].level;
+               ZERO_STRUCT(r.out);
+
+               d_printf("testing NetShareSetInfo level %u on share '%s'\n", 
+                      r.in.level, r.in.share_name);
+
+               switch (levels[i].level) {
+               case 0:
+                       r.in.info.info0 = talloc(mem_ctx, struct srvsvc_NetShareInfo0);
+                       r.in.info.info0->name = r.in.share_name;
+                       break;
+               case 1:
+                       r.in.info.info1 = talloc(mem_ctx, struct srvsvc_NetShareInfo1);
+                       r.in.info.info1->name = r.in.share_name;
+                       r.in.info.info1->type = STYPE_DISKTREE;
+                       r.in.info.info1->comment = talloc_strdup(mem_ctx, "test comment 1");
+                       break;
+               case 2: 
+                       r.in.info.info2 = talloc(mem_ctx, struct srvsvc_NetShareInfo2);
+                       r.in.info.info2->name = r.in.share_name;
+                       r.in.info.info2->type = STYPE_DISKTREE;
+                       r.in.info.info2->comment = talloc_strdup(mem_ctx, "test comment 2");
+                       r.in.info.info2->permissions = 0;
+                       r.in.info.info2->max_users = 2;
+                       r.in.info.info2->current_users = 1;
+                       r.in.info.info2->path = talloc_strdup(mem_ctx, "::BLaH::"); /* "C:\\"); */
+                       r.in.info.info2->password = NULL;
+                       break;
+               case 501:
+                       r.in.info.info501 = talloc(mem_ctx, struct srvsvc_NetShareInfo501);
+                       r.in.info.info501->name = r.in.share_name;
+                       r.in.info.info501->type = STYPE_DISKTREE;
+                       r.in.info.info501->comment = talloc_strdup(mem_ctx, "test comment 501");
+                       r.in.info.info501->csc_policy = 0;
+                       break;
+               case 502:
+                       r.in.info.info502 = talloc(mem_ctx, struct srvsvc_NetShareInfo502);
+                       r.in.info.info502->name = r.in.share_name;
+                       r.in.info.info502->type = STYPE_DISKTREE;
+                       r.in.info.info502->comment = talloc_strdup(mem_ctx, "test comment 502");
+                       r.in.info.info502->permissions = 0;
+                       r.in.info.info502->max_users = 502;
+                       r.in.info.info502->current_users = 1;
+                       r.in.info.info502->path = talloc_strdup(mem_ctx, "C:\\");
+                       r.in.info.info502->password = NULL;
+                       r.in.info.info502->unknown = 0;
+                       r.in.info.info502->sd = NULL;
+                       break;
+               case 1004:
+                       r.in.info.info1004 = talloc(mem_ctx, struct srvsvc_NetShareInfo1004);
+                       r.in.info.info1004->comment = talloc_strdup(mem_ctx, "test comment 1004");
+                       break;
+               case 1005:
+                       r.in.info.info1005 = talloc(mem_ctx, struct srvsvc_NetShareInfo1005);
+                       r.in.info.info1005->dfs_flags = 0;
+                       break;
+               case 1006:
+                       r.in.info.info1006 = talloc(mem_ctx, struct srvsvc_NetShareInfo1006);
+                       r.in.info.info1006->max_users = 1006;
+                       break;
+/*             case 1007:
+                       r.in.info.info1007 = talloc(mem_ctx, struct srvsvc_NetShareInfo1007);
+                       r.in.info.info1007->flags = 0;
+                       r.in.info.info1007->alternate_directory_name = talloc_strdup(mem_ctx, "test");
+                       break;
+*/
+               case 1501:
+                       r.in.info.info1501 = talloc_zero(mem_ctx, struct sec_desc_buf);
+                       break;
+               }
+               
+               status = dcerpc_srvsvc_NetShareSetInfo(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
+                               r.in.level, r.in.share_name, nt_errstr(status));
+                       ret = False;
+                       continue;
+               } else if (!W_ERROR_EQUAL(r.out.result, levels[i].expected)) {
+                       d_printf("NetShareSetInfo level %u on share '%s' failed - %s (expected %s)\n",
+                               r.in.level, r.in.share_name, win_errstr(r.out.result),
+                               win_errstr(levels[i].expected));
+                       ret = False;
+                       continue;
+               }
+               
+               q.in.share_name = r.in.share_name;
+
+               status = dcerpc_srvsvc_NetShareGetInfo(p, mem_ctx, &q);
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
+                               q.in.level, q.in.share_name, nt_errstr(status));
+                       ret = False;
+                       continue;
+               } else if (!W_ERROR_EQUAL(q.out.result, WERR_OK)) {
+                       d_printf("NetShareGetInfo level %u on share '%s' failed - %s\n",
+                               q.in.level, q.in.share_name, win_errstr(q.out.result));
+                       ret = False;
+                       continue;
+               }
+
+               if (strcmp(q.out.info.info502->name, r.in.share_name) != 0) {
+                       ret = False;
+               }
+               switch (levels[i].level) {
+               case 0:
+                       break;
+               case 1:
+                       if (strcmp(q.out.info.info502->comment, "test comment 1") != 0)
+                               ret = False;
+                       break;
+               case 2:
+                       if (strcmp(q.out.info.info502->comment, "test comment 2") != 0)
+                               ret = False;
+                       if (q.out.info.info2->max_users != 2)
+                               ret = False;
+                       if (strcmp(q.out.info.info2->path, "C:\\") != 0)
+                               ret = False;
+                       break;
+               case 501:
+                       if (strcmp(q.out.info.info501->comment, "test comment 501") != 0)
+                               ret = False;
+                       break;
+               case 502:
+                       if (strcmp(q.out.info.info502->comment, "test comment 502") != 0)
+                               ret = False;
+                       if (q.out.info.info2->max_users != 502)
+                               ret = False;
+                       if (strcmp(q.out.info.info2->path, "C:\\") != 0)
+                               ret = False;
+                       break;
+               case 1004:
+                       if (strcmp(q.out.info.info502->comment, "test comment 1004") != 0)
+                               ret = False;
+                       break;
+               case 1005:
+                       break;
+               case 1006:
+                       if (q.out.info.info2->max_users != 1006)
+                               ret = False;
+                       break;
+/*             case 1007:
+                       break;
+*/
+               case 1501:
+                       break;
+               }
+       }
+
+       d.in.share_name = r.in.share_name;
+       d.in.reserved = 0;
+
+       status = dcerpc_srvsvc_NetShareDel(p, mem_ctx, &d);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("NetShareDel on share 'testshare502' failed - %s\n",
+                        nt_errstr(status));
+               ret = False;
+       } else if (!W_ERROR_EQUAL(a.out.result, WERR_OK)) {
+               d_printf("NetShareDel on share 'testshare502' failed - %s\n",
+                        win_errstr(d.out.result));
+               ret = False;
+       }
+
+       return ret;
+}
+
 /**************************/
 /* srvsvc_NetShare        */
 /**************************/
@@ -776,7 +1000,8 @@ static BOOL test_NetNameValidate(struct dcerpc_pipe *p,
        NTSTATUS status;
        struct srvsvc_NetNameValidate r;
        char *invalidc;
-       int i, n;
+       char *name;
+       int i, n, min, max;
 
        r.in.server_unc = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
        r.in.flags = 0x0;
@@ -787,31 +1012,44 @@ static BOOL test_NetNameValidate(struct dcerpc_pipe *p,
        for (i = 1; i < 14; i++) {
 
 again:
-               /* Find maximum length accepted by this type */
-               ZERO_STRUCT(r.out);
-               r.in.name_type = i;
-               r.in.name = talloc_strdup(mem_ctx, "A");
-               n = 0;
+               /* let's limit ourselves to a maximum of 4096 bytes */
+               r.in.name = name = talloc_array(mem_ctx, char, 4097);
+               max = 4096;
+               min = 0;
+               n = max;
+
+               while (1) {
+
+                       /* Find maximum length accepted by this type */
+                       ZERO_STRUCT(r.out);
+                       r.in.name_type = i;
+                       memset(name, 'A', n);
+                       name[n] = '\0';
 
-               while (W_ERROR_IS_OK(r.out.result)) {
                        status = dcerpc_srvsvc_NetNameValidate(p, mem_ctx, &r);
                        if (!NT_STATUS_IS_OK(status)) {
                                d_printf("NetNameValidate failed while checking maximum size (%s)\n",
                                                nt_errstr(status));
                                break;
                        }
-                       
-                       r.in.name = talloc_append_string(mem_ctx, r.in.name, "A");
-                       if (!r.in.name) {
-                               d_printf("NetNameValidate: Out of memory!\n");
-                               return False;
+
+                       if (W_ERROR_IS_OK(r.out.result)) {
+                               min = n;
+                               n += (max - min + 1)/2;
+                               continue;
+                               
+                       } else {
+                               if ((min + 1) >= max) break; /* found it */
+                               
+                               max = n;
+                               n -= (max - min)/2;
+                               continue;
                        }
-                       n++;
                }
 
                talloc_free(r.in.name);
 
-               d_printf("Maximum length for type %2d, flags %08x: %d\n", i, r.in.flags, n);
+               d_printf("Maximum length for type %2d, flags %08x: %d\n", i, r.in.flags, max);
 
                /* find invalid chars for this type check only ASCII between 0x20 and 0x7e */
 
@@ -877,6 +1115,7 @@ BOOL torture_rpc_srvsvc(struct torture_context *torture)
        ret &= test_NetRemoteTOD(p, mem_ctx);
        ret &= test_NetShareEnum(p, mem_ctx, True);
        ret &= test_NetShareGetInfo(p, mem_ctx, "ADMIN$", True);
+       ret &= test_NetShareAddSetDel(p, mem_ctx);
        ret &= test_NetNameValidate(p, mem_ctx);
        
        status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_srvsvc);