diff options
-rw-r--r-- | source4/param/share.c | 16 | ||||
-rw-r--r-- | source4/param/share.h | 18 | ||||
-rw-r--r-- | source4/param/share_classic.c | 20 | ||||
-rw-r--r-- | source4/param/share_ldb.c | 143 | ||||
-rw-r--r-- | source4/rpc_server/srvsvc/dcesrv_srvsvc.c | 75 |
5 files changed, 246 insertions, 26 deletions
diff --git a/source4/param/share.c b/source4/param/share.c index a87fe38f8e..c27619b11b 100644 --- a/source4/param/share.c +++ b/source4/param/share.c @@ -54,6 +54,22 @@ 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) +{ + if (sctx->ops->create) { + return sctx->ops->create(sctx, info); + } + return NT_STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS share_remove(struct share_context *sctx, const char *name) +{ + if (sctx->ops->remove) { + return sctx->ops->remove(sctx, name); + } + return NT_STATUS_NOT_IMPLEMENTED; +} + /* List of currently available share backends */ static struct share_ops **backends = NULL; diff --git a/source4/param/share.h b/source4/param/share.h index af5bd0ebba..ca3accd4ef 100644 --- a/source4/param/share.h +++ b/source4/param/share.h @@ -36,6 +36,16 @@ struct share_config { void *opaque; }; +struct share_info { + const char *name; + const char *type; + const char *path; + const char *comment; + const char *password; + int32_t max_users; + struct security_descriptor *sd; +}; + struct share_ops { const char *name; NTSTATUS (*init)(TALLOC_CTX *, const struct share_ops*, struct share_context **); @@ -45,8 +55,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_obj)(struct share_context *, const char *); - NTSTATUS (*delete_obj)(struct share_context *, const char *); + NTSTATUS (*create)(struct share_context *, struct share_info *); + NTSTATUS (*remove)(struct share_context *, const char *); }; #include "param/share_proto.h" @@ -56,14 +66,14 @@ struct share_ops { #define SHARE_NAME "name" #define SHARE_PATH "path" #define SHARE_COMMENT "comment" -#define SHARE_PASSWORD "password" +#define SHARE_PASSWORD "password" #define SHARE_HOSTS_ALLOW "hosts-allow" #define SHARE_HOSTS_DENY "hosts-deny" #define SHARE_NTVFS_HANDLER "ntvfs-handler" #define SHARE_TYPE "type" #define SHARE_VOLUME "volume" #define SHARE_CSC_POLICY "csc-policy" -#define SHARE_AVAILABLE "available" +#define SHARE_AVAILABLE "available" #define SHARE_BROWSEABLE "browseable" #define SHARE_MAX_CONNECTIONS "max-connections" diff --git a/source4/param/share_classic.c b/source4/param/share_classic.c index 59c58e4d54..75f66b1fd4 100644 --- a/source4/param/share_classic.c +++ b/source4/param/share_classic.c @@ -312,16 +312,16 @@ NTSTATUS sclassic_get_config(TALLOC_CTX *mem_ctx, NTSTATUS share_classic_init(void) { - struct share_ops ops; - - ops.name = "classic"; - ops.init = sclassic_init; - ops.string_option = sclassic_string_option; - ops.int_option = sclassic_int_option; - ops.bool_option = sclassic_bool_option; - ops.string_list_option = sclassic_string_list_option; - ops.list_all = sclassic_list_all; - ops.get_config = sclassic_get_config; + static struct share_ops ops = { + .name = "classic", + .init = sclassic_init, + .string_option = sclassic_string_option, + .int_option = sclassic_int_option, + .bool_option = sclassic_bool_option, + .string_list_option = sclassic_string_list_option, + .list_all = sclassic_list_all, + .get_config = sclassic_get_config + }; return share_register(&ops); } diff --git a/source4/param/share_ldb.c b/source4/param/share_ldb.c index 8349ad7fe5..2fd43c04a7 100644 --- a/source4/param/share_ldb.c +++ b/source4/param/share_ldb.c @@ -263,18 +263,141 @@ 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); \ + if (err != LDB_SUCCESS) { \ + DEBUG(2,("ERROR: unable to add share %s to ldb msg\n", type)); \ + ret = NT_STATUS_UNSUCCESSFUL; \ + goto done; \ + } } while(0) + +NTSTATUS sldb_create(struct share_context *ctx, struct share_info *info) +{ + 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) { + 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 info->name */ + msg->dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", info->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); + } + + /* TODO: Security Descriptor */ + + 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; + goto done; + } + + ret = NT_STATUS_OK; +done: + talloc_free(tmp_ctx); + return ret; +} + +NTSTATUS sldb_remove(struct share_context *ctx, const char *name) +{ + struct ldb_context *ldb; + struct ldb_dn *dn; + TALLOC_CTX *tmp_ctx; + NTSTATUS ret; + int err; + + 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); + + dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", name); + if (!dn) { + DEBUG(0,("ERROR: Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + err = ldb_delete(ldb, dn); + if (err != LDB_SUCCESS) { + DEBUG(2,("ERROR: unable to remove share %s from share.ldb\n" + " err=%d [%s]\n", name, err, ldb_errstring(ldb))); + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + ret = NT_STATUS_OK; +done: + talloc_free(tmp_ctx); + return ret; +} + NTSTATUS share_ldb_init(void) { - struct share_ops ops; - - ops.name = "ldb"; - ops.init = sldb_init; - ops.string_option = sldb_string_option; - ops.int_option = sldb_int_option; - ops.bool_option = sldb_bool_option; - ops.string_list_option = sldb_string_list_option; - ops.list_all = sldb_list_all; - ops.get_config = sldb_get_config; + static struct share_ops ops = { + .name = "ldb", + .init = sldb_init, + .string_option = sldb_string_option, + .int_option = sldb_int_option, + .bool_option = sldb_bool_option, + .string_list_option = sldb_string_list_option, + .list_all = sldb_list_all, + .get_config = sldb_get_config, + .create = sldb_create, + .remove = sldb_remove + }; return share_register(&ops); } diff --git a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c index 2464da447a..68ab1498c2 100644 --- a/source4/rpc_server/srvsvc/dcesrv_srvsvc.c +++ b/source4/rpc_server/srvsvc/dcesrv_srvsvc.c @@ -452,10 +452,68 @@ static WERROR srvsvc_NetShareAdd(struct dcesrv_call_state *dce_call, TALLOC_CTX } case 502: { + NTSTATUS nterr; + struct share_info *info; + struct share_context *sctx; + + 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); + W_ERROR_HAVE_NO_MEMORY(info); + + info->name = talloc_strdup(info, r->in.info.info502->name); + W_ERROR_HAVE_NO_MEMORY(info->name); + switch (r->in.info.info502->type) { + case 0x00: + info->type = talloc_strdup(mem_ctx, "DISK"); + break; + case 0x01: + info->type = talloc_strdup(mem_ctx, "PRINTER"); + break; + case 0x03: + info->type = talloc_strdup(mem_ctx, "IPC"); + break; + default: + return WERR_INVALID_PARAM; + } + W_ERROR_HAVE_NO_MEMORY(info->type); + + /* Windows will send a path in a form of C:\example\path */ + if (r->in.info.info502->path[1] == ':') { + info->path = talloc_strdup(info, &r->in.info.info502->path[2]); + } else { + info->path = talloc_strdup(info, r->in.info.info502->path); + } + W_ERROR_HAVE_NO_MEMORY(info->path); + all_string_sub(info->path, "\\", "/", 0); + + 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); + } + + 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->max_users = r->in.info.info502->max_users; + /* TODO: security descriptor */ + + + nterr = share_create(sctx, info); + 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; } default: return WERR_UNKNOWN_LEVEL; @@ -1808,7 +1866,20 @@ static WERROR srvsvc_NETRSERVERTRANSPORTDELEX(struct dcesrv_call_state *dce_call static WERROR srvsvc_NetShareDel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct srvsvc_NetShareDel *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + NTSTATUS nterr; + struct share_context *sctx; + + nterr = share_get_context(mem_ctx, &sctx); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + nterr = share_remove(sctx, r->in.share_name); + if (!NT_STATUS_IS_OK(nterr)) { + return ntstatus_to_werror(nterr); + } + + return WERR_OK; } /* |