diff options
-rw-r--r-- | source4/param/share.c | 12 | ||||
-rw-r--r-- | source4/param/share.h | 17 | ||||
-rw-r--r-- | source4/param/share_ldb.c | 243 | ||||
-rw-r--r-- | source4/rpc_server/srvsvc/dcesrv_srvsvc.c | 340 |
4 files changed, 548 insertions, 64 deletions
diff --git a/source4/param/share.c b/source4/param/share.c index c27619b11b..7cbaa8a85c 100644 --- a/source4/param/share.c +++ b/source4/param/share.c @@ -54,10 +54,18 @@ NTSTATUS share_get_config(TALLOC_CTX *mem_ctx, struct share_context *sctx, const return sctx->ops->get_config(mem_ctx, sctx, name, scfg); } -NTSTATUS share_create(struct share_context *sctx, struct share_info *info) +NTSTATUS share_create(struct share_context *sctx, const char *name, struct share_info *info, int count) { if (sctx->ops->create) { - return sctx->ops->create(sctx, info); + return sctx->ops->create(sctx, name, info, count); + } + return NT_STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS share_set(struct share_context *sctx, const char *name, struct share_info *info, int count) +{ + if (sctx->ops->set) { + return sctx->ops->set(sctx, name, info, count); } return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source4/param/share.h b/source4/param/share.h index ca3accd4ef..93b02255b6 100644 --- a/source4/param/share.h +++ b/source4/param/share.h @@ -36,14 +36,16 @@ struct share_config { void *opaque; }; +enum share_info_type { + SHARE_INFO_STRING, + SHARE_INFO_INT, + SHARE_INFO_BLOB +}; + struct share_info { + enum share_info_type type; const char *name; - const char *type; - const char *path; - const char *comment; - const char *password; - int32_t max_users; - struct security_descriptor *sd; + void *value; }; struct share_ops { @@ -55,7 +57,8 @@ struct share_ops { const char **(*string_list_option)(TALLOC_CTX *, struct share_config *, const char *); NTSTATUS (*list_all)(TALLOC_CTX *, struct share_context *, int *, const char ***); NTSTATUS (*get_config)(TALLOC_CTX *, struct share_context *, const char *, struct share_config **); - NTSTATUS (*create)(struct share_context *, struct share_info *); + NTSTATUS (*create)(struct share_context *, const char *, struct share_info *, int); + NTSTATUS (*set)(struct share_context *, const char *, struct share_info *, int); NTSTATUS (*remove)(struct share_context *, const char *); }; diff --git a/source4/param/share_ldb.c b/source4/param/share_ldb.c index 2fd43c04a7..21f6938f69 100644 --- a/source4/param/share_ldb.c +++ b/source4/param/share_ldb.c @@ -174,7 +174,7 @@ static NTSTATUS sldb_list_all(TALLOC_CTX *mem_ctx, ret = ldb_search(ldb, ldb_dn_explode(tmp_ctx, "CN=SHARES"), LDB_SCOPE_SUBTREE, "(name=*)", NULL, &res); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_BAD_NETWORK_NAME; } talloc_steal(tmp_ctx, res); @@ -230,7 +230,7 @@ static NTSTATUS sldb_get_config(TALLOC_CTX *mem_ctx, ret = ldb_search(ldb, ldb_dn_explode(tmp_ctx, "CN=SHARES"), LDB_SCOPE_SUBTREE, filter, NULL, &res); if (ret != LDB_SUCCESS || res->count != 1) { talloc_free(tmp_ctx); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + return NT_STATUS_BAD_NETWORK_NAME; } talloc_steal(tmp_ctx, res); @@ -263,24 +263,48 @@ static NTSTATUS sldb_get_config(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -#define SHARE_ADD_STRING(type, data) do { \ - err = ldb_msg_add_string(msg, type, data); \ +#define SHARE_ADD_STRING(name, value) do { \ + err = ldb_msg_add_string(msg, name, value); \ if (err != LDB_SUCCESS) { \ - DEBUG(2,("ERROR: unable to add share %s to ldb msg\n", type)); \ + DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \ ret = NT_STATUS_UNSUCCESSFUL; \ goto done; \ } } while(0) -NTSTATUS sldb_create(struct share_context *ctx, struct share_info *info) +#define SHARE_ADD_INT(name, value) do { \ + err = ldb_msg_add_fmt(msg, name, "%d", value); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +#define SHARE_ADD_BLOB(name, value) do { \ + err = ldb_msg_add_value(msg, name, value); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +NTSTATUS sldb_create(struct share_context *ctx, const char *name, struct share_info *info, int count) { struct ldb_context *ldb; struct ldb_message *msg; TALLOC_CTX *tmp_ctx; NTSTATUS ret; - char *conns; - int err; - - if (!info->name || !info->type || !info->path) { + int err, i, j; + + for (i = 0, j = 0; i < count || j != 0x03; i++) { + if (strcasecmp(info[i].name, SHARE_TYPE) == 0) j |= 0x02; + if (strcasecmp(info[i].name, SHARE_PATH) == 0) j |= 0x01; + if (strcasecmp(info[i].name, SHARE_NAME) == 0) { + if (strcasecmp(name, (char *)info[i].value) != 0) { + return NT_STATUS_INVALID_PARAMETER; + } + } + } + if (!name || j != 0x03) { return NT_STATUS_INVALID_PARAMETER; } @@ -300,29 +324,36 @@ NTSTATUS sldb_create(struct share_context *ctx, struct share_info *info) } /* TODO: escape info->name */ - msg->dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", info->name); + msg->dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", name); if (!msg->dn) { DEBUG(0,("ERROR: Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } - SHARE_ADD_STRING("cn", info->name); SHARE_ADD_STRING("objectClass", "top"); SHARE_ADD_STRING("objectClass", "share"); - - SHARE_ADD_STRING(SHARE_NAME, info->name); - SHARE_ADD_STRING(SHARE_TYPE, info->type); - SHARE_ADD_STRING(SHARE_PATH, info->path); - if (strcmp(info->type, "DISK") == 0) { - SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "default"); - } - if (info->comment) { - SHARE_ADD_STRING(SHARE_COMMENT, info->comment); - } - - if (info->password) { - SHARE_ADD_STRING(SHARE_PASSWORD, info->password); + SHARE_ADD_STRING("cn", name); + SHARE_ADD_STRING(SHARE_NAME, name); + + for (i = 0; i < count; i++) { + if (strcasecmp(info[i].name, SHARE_NAME) == 0) continue; + + switch (info[i].type) { + case SHARE_INFO_STRING: + SHARE_ADD_STRING(info[i].name, (char *)info[i].value); + break; + case SHARE_INFO_INT: + SHARE_ADD_INT(info[i].name, *((int *)info[i].value)); + break; + case SHARE_INFO_BLOB: + SHARE_ADD_BLOB(info[i].name, (DATA_BLOB *)info[i].value); + break; + default: + DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name)); + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } } /* TODO: Security Descriptor */ @@ -330,14 +361,167 @@ NTSTATUS sldb_create(struct share_context *ctx, struct share_info *info) SHARE_ADD_STRING(SHARE_AVAILABLE, "True"); SHARE_ADD_STRING(SHARE_BROWSEABLE, "True"); SHARE_ADD_STRING(SHARE_READONLY, "False"); - conns = talloc_asprintf(tmp_ctx, "%d", info->max_users); - SHARE_ADD_STRING(SHARE_MAX_CONNECTIONS, conns); err = ldb_add(ldb, msg); if (err != LDB_SUCCESS) { DEBUG(2,("ERROR: unable to add share %s to share.ldb\n" - " err=%d [%s]\n", info->name, err, ldb_errstring(ldb))); - ret = NT_STATUS_UNSUCCESSFUL; + " err=%d [%s]\n", name, err, ldb_errstring(ldb))); + if (err == LDB_ERR_NO_SUCH_OBJECT) { + ret = NT_STATUS_BAD_NETWORK_NAME; + } else { + ret = NT_STATUS_UNSUCCESSFUL; + } + goto done; + } + + ret = NT_STATUS_OK; +done: + talloc_free(tmp_ctx); + return ret; +} + +#define SHARE_MOD_STRING(name, value) do { \ + err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } \ + err = ldb_msg_add_string(msg, name, value); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +#define SHARE_MOD_INT(name, value) do { \ + err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } \ + err = ldb_msg_add_fmt(msg, name, "%d", value); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +#define SHARE_MOD_BLOB(name, value) do { \ + err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } \ + err = ldb_msg_add_value(msg, name, value); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +NTSTATUS sldb_set(struct share_context *ctx, const char *name, struct share_info *info, int count) +{ + struct ldb_context *ldb; + struct ldb_message *msg; + TALLOC_CTX *tmp_ctx; + NTSTATUS ret; + bool rename = False; + char *newname; + int err, i; + + if (!name) { + return NT_STATUS_INVALID_PARAMETER; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + DEBUG(0,("ERROR: Out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + ldb = talloc_get_type(ctx->priv_data, struct ldb_context); + + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + DEBUG(0,("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + /* TODO: escape name */ + msg->dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", name); + if (!msg->dn) { + DEBUG(0,("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + for (i = 0; i < count; i++) { + if (strcasecmp(info[i].name, SHARE_NAME) == 0) { + if (strcasecmp(name, (char *)info[i].value) != 0) { + rename = True; + newname = (char *)info[i].value; + SHARE_MOD_STRING("cn", (char *)info[i].value); + } + } + + switch (info[i].type) { + case SHARE_INFO_STRING: + SHARE_MOD_STRING(info[i].name, (char *)info[i].value); + break; + case SHARE_INFO_INT: + SHARE_MOD_INT(info[i].name, *((int *)info[i].value)); + break; + case SHARE_INFO_BLOB: + SHARE_MOD_BLOB(info[i].name, (DATA_BLOB *)info[i].value); + break; + default: + DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name)); + ret = NT_STATUS_INVALID_PARAMETER; + goto done; + } + } + + if (rename) { + struct ldb_dn *olddn, *newdn; + + olddn = msg->dn; + + /* TODO: escape newname */ + newdn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", newname); + if (!newdn) { + DEBUG(0,("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + err = ldb_rename(ldb, olddn, newdn); + if (err != LDB_SUCCESS) { + DEBUG(2,("ERROR: unable to rename share %s (to %s)\n" + " err=%d [%s]\n", name, newname, err, ldb_errstring(ldb))); + if (err == LDB_ERR_NO_SUCH_OBJECT) { + ret = NT_STATUS_BAD_NETWORK_NAME; + } else { + ret = NT_STATUS_UNSUCCESSFUL; + } + goto done; + } + + msg->dn = newdn; + } + + err = ldb_modify(ldb, msg); + if (err != LDB_SUCCESS) { + DEBUG(2,("ERROR: unable to add share %s to share.ldb\n" + " err=%d [%s]\n", name, err, ldb_errstring(ldb))); + if (err == LDB_ERR_NO_SUCH_OBJECT) { + ret = NT_STATUS_BAD_NETWORK_NAME; + } else { + ret = NT_STATUS_UNSUCCESSFUL; + } goto done; } @@ -396,6 +580,7 @@ NTSTATUS share_ldb_init(void) .list_all = sldb_list_all, .get_config = sldb_get_config, .create = sldb_create, + .set = sldb_set, .remove = sldb_remove }; diff --git a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c index 2ca5c8ee97..b8da68e920 100644 --- a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c +++ b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c @@ -438,10 +438,94 @@ static WERROR srvsvc_NetShareAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX } case 2: { + NTSTATUS nterr; + struct share_info *info; + struct share_context *sctx; + int count = 8; + int i; + + nterr = share_get_context(mem_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + /* 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; + + 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++; + + if (r->in.info.info2->path && r->in.info.info2->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]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, r->in.info.info2->path); + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + all_string_sub((char *)info[i].value, "\\", "/", 0); + + 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]) { + 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); + + i++; + } + + 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; + i++; + + /* TODO: security descriptor */ + + nterr = share_create(sctx, r->in.info.info2->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_NOT_SUPPORTED; + + return WERR_OK; } case 501: { @@ -455,59 +539,82 @@ static WERROR srvsvc_NetShareAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX NTSTATUS nterr; struct share_info *info; struct share_context *sctx; + int count = 10; + int i; nterr = share_get_context(mem_ctx, &sctx); if (!NT_STATUS_IS_OK(nterr)) { return ntstatus_to_werror(nterr); } - - info = talloc_zero(mem_ctx, struct share_info); + + /* there are no more than 10 options in struct srvsvc_NetShareInfo502 */ + info = talloc_array(mem_ctx, struct share_info, count); W_ERROR_HAVE_NO_MEMORY(info); - info->name = talloc_strdup(info, r->in.info.info502->name); - W_ERROR_HAVE_NO_MEMORY(info->name); + i = 0; + + info[i].name = SHARE_TYPE; + info[i].type = SHARE_INFO_STRING; switch (r->in.info.info502->type) { case 0x00: - info->type = talloc_strdup(mem_ctx, "DISK"); + info[i].value = talloc_strdup(info, "DISK"); break; case 0x01: - info->type = talloc_strdup(mem_ctx, "PRINTER"); + info[i].value = talloc_strdup(info, "PRINTER"); break; case 0x03: - info->type = talloc_strdup(mem_ctx, "IPC"); + info[i].value = talloc_strdup(info, "IPC"); break; default: return WERR_INVALID_PARAM; } - W_ERROR_HAVE_NO_MEMORY(info->type); + 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; + info[i].type = SHARE_INFO_STRING; + /* Windows will send a path in a form of C:\example\path */ - if (strncmp(r->in.info.info502->path, "C:", 2) == 0) { - info->path = talloc_strdup(info, &r->in.info.info502->path[2]); + 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->path = talloc_strdup(info, r->in.info.info502->path); + info[i].value = talloc_strdup(info, r->in.info.info502->path); } - W_ERROR_HAVE_NO_MEMORY(info->path); - all_string_sub(info->path, "\\", "/", 0); + 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->comment = talloc_strdup(info, r->in.info.info502->comment); - W_ERROR_HAVE_NO_MEMORY(info->comment); + info[i].name = SHARE_COMMENT; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info.info502->comment); + W_ERROR_HAVE_NO_MEMORY(info[i].value); + + i++; } if (r->in.info.info502->password && r->in.info.info502->password[0]) { - info->password = talloc_strdup(info, r->in.info.info502->password); - W_ERROR_HAVE_NO_MEMORY(info->password); + 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); + + i++; } - info->max_users = r->in.info.info502->max_users; + 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++; + /* TODO: security descriptor */ - - nterr = share_create(sctx, info); + nterr = share_create(sctx, r->in.info.info502->name, info, i); if (!NT_STATUS_IS_OK(nterr)) { return ntstatus_to_werror(nterr); } @@ -1030,7 +1137,95 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_ } case 2: { - return WERR_NOT_SUPPORTED; + struct share_info *info; + int count = 8; + int i; + + /* 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++; + } + + 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++; + + if (r->in.info.info2->path && r->in.info.info2->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]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, r->in.info.info2->path); + } + W_ERROR_HAVE_NO_MEMORY(info[i].value); + all_string_sub((char *)info[i].value, "\\", "/", 0); + + 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]) { + 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); + + i++; + } + + 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; + 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: { @@ -1038,14 +1233,103 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_ } case 502: { - return WERR_NOT_SUPPORTED; + 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++; + } + + info[i].name = SHARE_TYPE; + info[i].type = SHARE_INFO_STRING; + switch (r->in.info.info502->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++; + + if (r->in.info.info502->path && r->in.info.info502->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.info502->path[2]); + } else { + /* very strange let's try to set as is */ + info[i].value = talloc_strdup(info, r->in.info.info502->path); + } + 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; + info[i].type = SHARE_INFO_STRING; + info[i].value = talloc_strdup(info, r->in.info.info502->comment); + 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); + + i++; + } + + 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++; + + /* 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 1004: { WERROR status; union srvsvc_NetShareInfo info; - /* r->out.info.comment; */ + /* r->in.info.comment; */ + return WERR_NOT_SUPPORTED; } case 1005: @@ -1053,9 +1337,13 @@ static WERROR srvsvc_NetShareSetInfo(struct dcesrv_call_state *dce_call, TALLOC_ WERROR status; union srvsvc_NetShareInfo info; - /* r->out.info.dfs_flags; */ + /* r->in.info.dfs_flags; */ - return WERR_NOT_SUPPORTED; + if (r->in.parm_error) { + r->out.parm_error = r->in.parm_error; + } + + return WERR_OK; } default: return WERR_UNKNOWN_LEVEL; |