Ejemplo n.º 1
0
uint32_t _fss_PrepareShadowCopySet(struct pipes_struct *p,
				   struct fss_PrepareShadowCopySet *r)
{
	struct fss_sc_set *sc_set;

	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	if (sc_set->state != FSS_SC_ADDED) {
		return FSRVP_E_BAD_STATE;
	}

	/* stop msg sequence timer */
	TALLOC_FREE(fss_global.seq_tmr);

	/*
	 * Windows Server "8" Beta takes ~60s here, presumably flushing
	 * everything to disk. We may want to do something similar.
	 */

	/* start msg sequence timer, 1800 on success */
	fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);

	return 0;
}
Ejemplo n.º 2
0
uint32_t _fss_IsPathSupported(struct pipes_struct *p,
			      struct fss_IsPathSupported *r)
{
	int snum;
	char *service;
	char *base_vol;
	NTSTATUS status;
	struct connection_struct *conn;
	char *share;
	TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx);
	if (tmp_ctx == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	if (!fss_permitted(p)) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	status = fss_unc_parse(tmp_ctx, r->in.ShareName, NULL, &share);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return fss_ntstatus_map(status);
	}

	snum = find_service(tmp_ctx, share, &service);
	if ((snum == -1) || (service == NULL)) {
		DEBUG(0, ("share at %s not found\n", r->in.ShareName));
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	status = fss_vfs_conn_create(tmp_ctx, server_event_context(),
				     p->msg_ctx, p->session_info, snum, &conn);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}
	if (!become_user_by_session(conn, p->session_info)) {
		DEBUG(0, ("failed to become user\n"));
		talloc_free(tmp_ctx);
		fss_vfs_conn_destroy(conn);
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}
	status = SMB_VFS_SNAP_CHECK_PATH(conn, tmp_ctx,
					 lp_path(tmp_ctx, snum),
					 &base_vol);
	unbecome_user();
	fss_vfs_conn_destroy(conn);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return FSRVP_E_NOT_SUPPORTED;
	}

	*r->out.OwnerMachineName = lp_netbios_name();
	*r->out.SupportedByThisProvider = 1;
	talloc_free(tmp_ctx);
	return 0;
}
Ejemplo n.º 3
0
static uint32_t map_share_name(struct fss_sc_smap *sc_smap,
			       const struct fss_sc *sc)
{
	bool hidden_base = false;

	if (*(sc_smap->share_name + strlen(sc_smap->share_name) - 1) == '$') {
		/*
		 * If MappedShare.ShareName ends with a $ character (meaning
		 * that the share is hidden), then the exposed share name will
		 * have the $ suffix appended.
		 * FIXME: turns out Windows doesn't do this, contrary to docs
		 */
		hidden_base = true;
	}

	sc_smap->sc_share_name = talloc_asprintf(sc_smap, "%s@{%s}%s",
						sc_smap->share_name,
						sc->id_str,
						hidden_base ? "$" : "");
	if (sc_smap->sc_share_name == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	return 0;
}
Ejemplo n.º 4
0
static uint32_t map_share_comment(struct fss_sc_smap *sc_smap,
				  const struct fss_sc *sc)
{
	char *time_str;

	time_str = http_timestring(sc_smap, sc->create_ts);
	if (time_str == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	sc_smap->sc_share_comment = talloc_asprintf(sc_smap, "Shadow copy of %s taken %s",
						   sc_smap->share_name, time_str);
	if (sc_smap->sc_share_comment == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	return 0;
}
Ejemplo n.º 5
0
uint32_t _fss_IsPathShadowCopied(struct pipes_struct *p,
				 struct fss_IsPathShadowCopied *r)
{
	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	/* not yet supported */
	return FSRVP_E_NOT_SUPPORTED;
}
Ejemplo n.º 6
0
uint32_t _fss_AbortShadowCopySet(struct pipes_struct *p,
				 struct fss_AbortShadowCopySet *r)
{
	NTSTATUS status;
	struct fss_sc_set *sc_set;

	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	DEBUG(6, ("%s: aborting shadow-copy set\n", sc_set->id_str));

	if ((sc_set->state == FSS_SC_COMMITED)
	 || (sc_set->state == FSS_SC_EXPOSED)
	 || (sc_set->state == FSS_SC_RECOVERED)) {
		return 0;
	}

	if (sc_set->state == FSS_SC_CREATING) {
		return FSRVP_E_BAD_STATE;
	}

	DLIST_REMOVE(fss_global.sc_sets, sc_set);
	talloc_free(sc_set);
	fss_global.sc_sets_count--;
	become_root();
	status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
				 fss_global.sc_sets_count, fss_global.db_path);
	unbecome_root();
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("failed to store fss server state: %s\n",
			  nt_errstr(status)));
	}

	return 0;
}
Ejemplo n.º 7
0
uint32_t _fss_RecoveryCompleteShadowCopySet(struct pipes_struct *p,
				struct fss_RecoveryCompleteShadowCopySet *r)
{
	NTSTATUS status;
	struct fss_sc_set *sc_set;

	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	if (sc_set->state != FSS_SC_EXPOSED) {
		return FSRVP_E_BAD_STATE;
	}

	/* stop msg sequence timer */
	TALLOC_FREE(fss_global.seq_tmr);

	if (sc_set->context & ATTR_NO_AUTO_RECOVERY) {
		/* TODO set read-only */
	}

	sc_set->state = FSS_SC_RECOVERED;
	fss_global.cur_ctx = 0;
	fss_global.ctx_set = false;

	become_root();
	status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
				 fss_global.sc_sets_count, fss_global.db_path);
	unbecome_root();
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("failed to store fss server state: %s\n",
			  nt_errstr(status)));
	}

	return 0;
}
Ejemplo n.º 8
0
uint32_t _fss_GetSupportedVersion(struct pipes_struct *p,
				  struct fss_GetSupportedVersion *r)
{
	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	*r->out.MinVersion = fss_global.min_vers;
	*r->out.MaxVersion = fss_global.max_vers;

	return 0;
}
Ejemplo n.º 9
0
static uint32_t fss_ntstatus_map(NTSTATUS status)
{
	int i;

	if (NT_STATUS_IS_OK(status))
		return 0;

	/* check fsrvp specific errors first */
	for (i = 0; i < ARRAY_SIZE(ntstatus_to_fsrvp_map); i++) {
		if (NT_STATUS_EQUAL(status, ntstatus_to_fsrvp_map[i].status)) {
			return ntstatus_to_fsrvp_map[i].fsrvp_err;
		}
	}
	/* fall-back to generic hresult values */
	for (i = 0; i < ARRAY_SIZE(ntstatus_to_hres_map); i++) {
		if (NT_STATUS_EQUAL(status, ntstatus_to_hres_map[i].status)) {
			return HRES_ERROR_V(ntstatus_to_hres_map[i].hres);
		}
	}

	return HRES_ERROR_V(HRES_E_FAIL);
}
Ejemplo n.º 10
0
uint32_t _fss_SetContext(struct pipes_struct *p,
			 struct fss_SetContext *r)
{
	if (!fss_permitted(p)) {
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	/* ATTR_AUTO_RECOVERY flag can be applied to any */
	switch (r->in.Context & (~ATTR_AUTO_RECOVERY)) {
	case FSRVP_CTX_BACKUP:
		DEBUG(6, ("fss ctx set backup\n"));
		break;
	case FSRVP_CTX_FILE_SHARE_BACKUP:
		DEBUG(6, ("fss ctx set file share backup\n"));
		break;
	case FSRVP_CTX_NAS_ROLLBACK:
		DEBUG(6, ("fss ctx set nas rollback\n"));
		break;
	case FSRVP_CTX_APP_ROLLBACK:
		DEBUG(6, ("fss ctx set app rollback\n"));
		break;
	default:
		DEBUG(0, ("invalid fss ctx set value: 0x%x\n", r->in.Context));
		return HRES_ERROR_V(HRES_E_INVALIDARG);
		break;	/* not reached */
	}

	fss_global.ctx_set = true;
	fss_global.cur_ctx = r->in.Context;

	TALLOC_FREE(fss_global.seq_tmr);	/* kill timer if running */
	fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);

	fss_global.cur_ctx = r->in.Context;

	return 0;
}
Ejemplo n.º 11
0
uint32_t _fss_StartShadowCopySet(struct pipes_struct *p,
				 struct fss_StartShadowCopySet *r)
{
	struct fss_sc_set *sc_set;
	uint32_t ret;

	if (!fss_permitted(p)) {
		ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
		goto err_out;
	}

	if (!fss_global.ctx_set) {
		DEBUG(3, ("invalid sequence: start sc set requested without "
			  "prior context set\n"));
		ret = FSRVP_E_BAD_STATE;
		goto err_out;
	}

	/*
	 * At any given time, Windows servers allow only one shadow copy set to
	 * be going through the creation process.
	 */
	if (sc_set_active(fss_global.sc_sets)) {
		DEBUG(3, ("StartShadowCopySet called while in progress\n"));
		ret = FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS;
		goto err_out;
	}

	/* stop msg seq timer */
	TALLOC_FREE(fss_global.seq_tmr);

	sc_set = talloc_zero(fss_global.mem_ctx, struct fss_sc_set);
	if (sc_set == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_tmr_restart;
	}

	sc_set->id = GUID_random();	/* Windows servers ignore client ids */
	sc_set->id_str = GUID_string(sc_set, &sc_set->id);
	if (sc_set->id_str == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_sc_set_free;
	}
	sc_set->state = FSS_SC_STARTED;
	sc_set->context = fss_global.cur_ctx;
	DLIST_ADD_END(fss_global.sc_sets, sc_set, struct fss_sc_set *);
	fss_global.sc_sets_count++;
	DEBUG(6, ("%s: shadow-copy set %u added\n",
		  sc_set->id_str, fss_global.sc_sets_count));

	/* start msg seq timer */
	fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);

	r->out.pShadowCopySetId = &sc_set->id;

	return 0;

err_sc_set_free:
	talloc_free(sc_set);
err_tmr_restart:
	fss_seq_tout_set(fss_global.mem_ctx, 180, NULL, &fss_global.seq_tmr);
err_out:
	return ret;
}
Ejemplo n.º 12
0
static bool test_fsrvp_sc_create(struct torture_context *tctx,
				 struct dcerpc_pipe *p,
				 const char *share,
				 enum test_fsrvp_inject inject,
				 struct fssagent_share_mapping_1 **sc_map)
{
	struct fss_IsPathSupported r_pathsupport_get;
	struct fss_GetSupportedVersion r_version_get;
	struct fss_SetContext r_context_set;
	struct fss_StartShadowCopySet r_scset_start;
	struct fss_AddToShadowCopySet r_scset_add1;
	struct fss_AddToShadowCopySet r_scset_add2;
	struct fss_PrepareShadowCopySet r_scset_prep;
	struct fss_CommitShadowCopySet r_scset_commit;
	struct fss_ExposeShadowCopySet r_scset_expose;
	struct fss_GetShareMapping r_sharemap_get;
	struct dcerpc_binding_handle *b = p->binding_handle;
	NTSTATUS status;
	time_t start_time;
	TALLOC_CTX *tmp_ctx = talloc_new(tctx);
	struct fssagent_share_mapping_1 *map = NULL;
	int sleep_time;

	/*
	 * PrepareShadowCopySet & CommitShadowCopySet often exceed the default
	 * 60 second dcerpc request timeout against Windows Server "8" Beta.
	 */
	dcerpc_binding_handle_set_timeout(b, 240);

	ZERO_STRUCT(r_pathsupport_get);
	r_pathsupport_get.in.ShareName = share;
	status = dcerpc_fss_IsPathSupported_r(b, tmp_ctx, &r_pathsupport_get);
	torture_assert_ntstatus_ok(tctx, status,
				   "IsPathSupported failed");
	torture_assert_int_equal(tctx, r_pathsupport_get.out.result, 0,
				 "failed IsPathSupported response");
	torture_assert(tctx, r_pathsupport_get.out.SupportedByThisProvider,
		       "path not supported");

	ZERO_STRUCT(r_version_get);
	status = dcerpc_fss_GetSupportedVersion_r(b, tmp_ctx, &r_version_get);
	torture_assert_ntstatus_ok(tctx, status,
				   "GetSupportedVersion failed");
	torture_assert_int_equal(tctx, r_version_get.out.result, 0,
				 "failed GetSupportedVersion response");

	ZERO_STRUCT(r_context_set);
	r_context_set.in.Context = FSRVP_CTX_BACKUP;
	status = dcerpc_fss_SetContext_r(b, tmp_ctx, &r_context_set);
	torture_assert_ntstatus_ok(tctx, status, "SetContext failed");
	torture_assert_int_equal(tctx, r_context_set.out.result, 0,
				 "failed SetContext response");

	if (inject == TEST_FSRVP_TOUT_SET_CTX) {
		sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss",
					    "sequence timeout", 180);
		torture_comment(tctx, "sleeping for %d\n", sleep_time);
		smb_msleep((sleep_time * 1000) + 500);
	}

	ZERO_STRUCT(r_scset_start);
	r_scset_start.in.ClientShadowCopySetId = GUID_random();
	status = dcerpc_fss_StartShadowCopySet_r(b, tmp_ctx, &r_scset_start);
	torture_assert_ntstatus_ok(tctx, status,
				   "StartShadowCopySet failed");
	if (inject == TEST_FSRVP_TOUT_SET_CTX) {
		/* expect error due to message sequence timeout after set_ctx */
		torture_assert_int_equal(tctx, r_scset_start.out.result,
					 FSRVP_E_BAD_STATE,
					 "StartShadowCopySet timeout response");
		goto done;
	}
	torture_assert_int_equal(tctx, r_scset_start.out.result, 0,
				 "failed StartShadowCopySet response");
	torture_comment(tctx, "%s: shadow-copy set created\n",
			GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId));

	if (inject == TEST_FSRVP_TOUT_START_SET) {
		sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss",
					    "sequence timeout", 180);
		torture_comment(tctx, "sleeping for %d\n", sleep_time);
		smb_msleep((sleep_time * 1000) + 500);
	}

	ZERO_STRUCT(r_scset_add1);
	r_scset_add1.in.ClientShadowCopyId = GUID_random();
	r_scset_add1.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
	r_scset_add1.in.ShareName = share;
	status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add1);
	torture_assert_ntstatus_ok(tctx, status,
				   "AddToShadowCopySet failed");
	if (inject == TEST_FSRVP_TOUT_START_SET) {
		torture_assert_int_equal(tctx, r_scset_add1.out.result,
					 HRES_ERROR_V(HRES_E_INVALIDARG),
					 "AddToShadowCopySet timeout response");
		goto done;
	}
	torture_assert_int_equal(tctx, r_scset_add1.out.result, 0,
				 "failed AddToShadowCopySet response");
	torture_comment(tctx, "%s(%s): %s added to shadow-copy set\n",
			GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
			GUID_string(tmp_ctx, r_scset_add1.out.pShadowCopyId),
			r_scset_add1.in.ShareName);

	/* attempts to add the same share twice should fail */
	ZERO_STRUCT(r_scset_add2);
	r_scset_add2.in.ClientShadowCopyId = GUID_random();
	r_scset_add2.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
	r_scset_add2.in.ShareName = share;
	status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add2);
	torture_assert_ntstatus_ok(tctx, status,
				   "AddToShadowCopySet failed");
	torture_assert_int_equal(tctx, r_scset_add2.out.result,
				 FSRVP_E_OBJECT_ALREADY_EXISTS,
				 "failed AddToShadowCopySet response");

	if (inject == TEST_FSRVP_TOUT_ADD_TO_SET) {
		sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss",
					    "sequence timeout", 1800);
		torture_comment(tctx, "sleeping for %d\n", sleep_time);
		smb_msleep((sleep_time * 1000) + 500);
	}

	start_time = time_mono(NULL);
	ZERO_STRUCT(r_scset_prep);
	r_scset_prep.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
//	r_scset_prep.in.TimeOutInMilliseconds = (1800 * 1000);	/* win8 */
	r_scset_prep.in.TimeOutInMilliseconds = (240 * 1000);
	status = dcerpc_fss_PrepareShadowCopySet_r(b, tmp_ctx, &r_scset_prep);
	torture_assert_ntstatus_ok(tctx, status,
				   "PrepareShadowCopySet failed");
	if (inject == TEST_FSRVP_TOUT_ADD_TO_SET) {
		torture_assert_int_equal(tctx, r_scset_prep.out.result,
					 HRES_ERROR_V(HRES_E_INVALIDARG),
					 "PrepareShadowCopySet tout response");
		goto done;
	}
	torture_assert_int_equal(tctx, r_scset_prep.out.result, 0,
				 "failed PrepareShadowCopySet response");
	torture_comment(tctx, "%s: prepare completed in %llu secs\n",
			GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
			(unsigned long long)(time_mono(NULL) - start_time));

	if (inject == TEST_FSRVP_TOUT_PREPARE) {
		sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss",
					    "sequence timeout", 1800);
		torture_comment(tctx, "sleeping for %d\n", sleep_time);
		smb_msleep((sleep_time * 1000) + 500);
	}

	start_time = time_mono(NULL);
	ZERO_STRUCT(r_scset_commit);
	r_scset_commit.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
	r_scset_commit.in.TimeOutInMilliseconds = (180 * 1000);	/* win8 */
	status = dcerpc_fss_CommitShadowCopySet_r(b, tmp_ctx, &r_scset_commit);
	torture_assert_ntstatus_ok(tctx, status,
				   "CommitShadowCopySet failed");
	if (inject == TEST_FSRVP_TOUT_PREPARE) {
		torture_assert_int_equal(tctx, r_scset_commit.out.result,
					 HRES_ERROR_V(HRES_E_INVALIDARG),
					 "CommitShadowCopySet tout response");
		goto done;
	}
	torture_assert_int_equal(tctx, r_scset_commit.out.result, 0,
				 "failed CommitShadowCopySet response");
	torture_comment(tctx, "%s: commit completed in %llu secs\n",
			GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
			(unsigned long long)(time_mono(NULL) - start_time));

	if (inject == TEST_FSRVP_TOUT_COMMIT) {
		sleep_time = lpcfg_parm_int(tctx->lp_ctx, NULL, "fss",
					    "sequence timeout", 180);
		torture_comment(tctx, "sleeping for %d\n", sleep_time);
		smb_msleep((sleep_time * 1000) + 500);
	} else if (inject == TEST_FSRVP_STOP_B4_EXPOSE) {
		/* return partial snapshot information */
		map = talloc_zero(tctx, struct fssagent_share_mapping_1);
		map->ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
		map->ShadowCopyId = *r_scset_add1.out.pShadowCopyId;
		goto done;
	}
Ejemplo n.º 13
0
uint32_t _fss_ExposeShadowCopySet(struct pipes_struct *p,
				  struct fss_ExposeShadowCopySet *r)
{
	NTSTATUS status;
	struct fss_sc_set *sc_set;
	struct fss_sc *sc;
	uint32_t ret;
	struct smbconf_ctx *fconf_ctx;
	struct smbconf_ctx *rconf_ctx;
	sbcErr cerr;
	char *fconf_path;
	TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx);
	if (tmp_ctx == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	if (!fss_permitted(p)) {
		ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
		goto err_out;
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		ret = HRES_ERROR_V(HRES_E_INVALIDARG);
		goto err_out;
	}

	if (sc_set->state != FSS_SC_COMMITED) {
		ret = FSRVP_E_BAD_STATE;
		goto err_out;
	}

	/* stop message sequence timer */
	TALLOC_FREE(fss_global.seq_tmr);

	/*
	 * Prepare to clone the base share definition for the snapshot share.
	 * Create both registry and file conf contexts, as the base share
	 * definition may be located in either. The snapshot share definition
	 * is always written to the registry.
	 */
	cerr = smbconf_init(tmp_ctx, &rconf_ctx, "registry");
	if (!SBC_ERROR_IS_OK(cerr)) {
		DEBUG(0, ("failed registry smbconf init: %s\n",
			  sbcErrorString(cerr)));
		ret = HRES_ERROR_V(HRES_E_FAIL);
		goto err_tmr_restart;
	}
	fconf_path = talloc_asprintf(tmp_ctx, "file:%s", get_dyn_CONFIGFILE());
	if (fconf_path == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_tmr_restart;
	}
	cerr = smbconf_init(tmp_ctx, &fconf_ctx, fconf_path);
	if (!SBC_ERROR_IS_OK(cerr)) {
		DEBUG(0, ("failed %s smbconf init: %s\n",
			  fconf_path, sbcErrorString(cerr)));
		ret = HRES_ERROR_V(HRES_E_FAIL);
		goto err_tmr_restart;
	}

	/* registry IO must be done as root */
	become_root();
	cerr = smbconf_transaction_start(rconf_ctx);
	if (!SBC_ERROR_IS_OK(cerr)) {
		DEBUG(0, ("error starting transaction: %s\n",
			 sbcErrorString(cerr)));
		ret = HRES_ERROR_V(HRES_E_FAIL);
		unbecome_root();
		goto err_tmr_restart;
	}

	for (sc = sc_set->scs; sc; sc = sc->next) {
		ret = fss_sc_expose(fconf_ctx, rconf_ctx, tmp_ctx, sc);
		if (ret) {
			DEBUG(0,("failed to expose shadow copy of %s\n",
				 sc->volume_name));
			goto err_cancel;
		}
	}

	cerr = smbconf_transaction_commit(rconf_ctx);
	if (!SBC_ERROR_IS_OK(cerr)) {
		DEBUG(0, ("error committing transaction: %s\n",
			  sbcErrorString(cerr)));
		ret = HRES_ERROR_V(HRES_E_FAIL);
		goto err_cancel;
	}
	unbecome_root();

	message_send_all(p->msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
	for (sc = sc_set->scs; sc; sc = sc->next) {
		struct fss_sc_smap *sm;
		for (sm = sc->smaps; sm; sm = sm->next)
			sm->is_exposed = true;
	}
	sc_set->state = FSS_SC_EXPOSED;
	become_root();
	status = fss_state_store(fss_global.mem_ctx, fss_global.sc_sets,
				 fss_global.sc_sets_count, fss_global.db_path);
	unbecome_root();
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("failed to store fss server state: %s\n",
			  nt_errstr(status)));
	}
	/* start message sequence timer */
	fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
	talloc_free(tmp_ctx);
	return 0;

err_cancel:
	smbconf_transaction_cancel(rconf_ctx);
	unbecome_root();
err_tmr_restart:
	fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
err_out:
	talloc_free(tmp_ctx);
	return ret;
}
Ejemplo n.º 14
0
/*
 * Expose a new share using libsmbconf, cloning the existing configuration
 * from the base share. The base share may be defined in either the registry
 * or smb.conf.
 * XXX this is called as root
 */
static uint32_t fss_sc_expose(struct smbconf_ctx *fconf_ctx,
			      struct smbconf_ctx *rconf_ctx,
			      TALLOC_CTX *mem_ctx,
			      struct fss_sc *sc)
{
	struct fss_sc_smap *sc_smap;
	uint32_t err = 0;

	for (sc_smap = sc->smaps; sc_smap; sc_smap = sc_smap->next) {
		sbcErr cerr;
		struct smbconf_service *base_service = NULL;
		struct security_descriptor *sd;
		size_t sd_size;

		cerr = fss_conf_get_share_def(fconf_ctx, rconf_ctx, mem_ctx,
					    sc_smap->share_name, &base_service);
		if (!SBC_ERROR_IS_OK(cerr)) {
			DEBUG(0, ("failed to get base share %s definition: "
				  "%s\n", sc_smap->share_name,
				  sbcErrorString(cerr)));
			err = HRES_ERROR_V(HRES_E_FAIL);
			break;
		}

		/* smap share name already defined when added */
		err = map_share_comment(sc_smap, sc);
		if (err) {
			DEBUG(0, ("failed to map share comment\n"));
			break;
		}

		base_service->name = sc_smap->sc_share_name;

		cerr = smbconf_create_set_share(rconf_ctx, base_service);
		if (!SBC_ERROR_IS_OK(cerr)) {
			DEBUG(0, ("failed to create share %s: %s\n",
				  base_service->name, sbcErrorString(cerr)));
			err = HRES_ERROR_V(HRES_E_FAIL);
			break;
		}
		cerr = smbconf_set_parameter(rconf_ctx, sc_smap->sc_share_name,
					     "path", sc->sc_path);
		if (!SBC_ERROR_IS_OK(cerr)) {
			DEBUG(0, ("failed to set path param: %s\n",
				  sbcErrorString(cerr)));
			err = HRES_ERROR_V(HRES_E_FAIL);
			break;
		}
		if (sc_smap->sc_share_comment != NULL) {
			cerr = smbconf_set_parameter(rconf_ctx,
						    sc_smap->sc_share_name,
						    "comment",
						    sc_smap->sc_share_comment);
			if (!SBC_ERROR_IS_OK(cerr)) {
				DEBUG(0, ("failed to set comment param: %s\n",
					  sbcErrorString(cerr)));
				err = HRES_ERROR_V(HRES_E_FAIL);
				break;
			}
		}
		talloc_free(base_service);

		/*
		 * Obtain the base share SD, which also needs to be cloned.
		 * Share SDs are stored in share_info.tdb, so are not covered by
		 * the registry transaction.
		 * The base share SD should be cloned at the time of exposure,
		 * rather than when the snapshot is taken. This matches Windows
		 * Server 2012 behaviour.
		 */
		sd = get_share_security(mem_ctx, sc_smap->share_name, &sd_size);
		if (sd == NULL) {
			DEBUG(2, ("no share SD to clone for %s snapshot\n",
				  sc_smap->share_name));
		} else {
			bool ok;
			ok = set_share_security(sc_smap->sc_share_name, sd);
			TALLOC_FREE(sd);
			if (!ok) {
				DEBUG(0, ("failed to set %s share SD\n",
					  sc_smap->sc_share_name));
				err = HRES_ERROR_V(HRES_E_FAIL);
				break;
			}
		}
	}

	return err;
}
Ejemplo n.º 15
0
uint32_t _fss_GetShareMapping(struct pipes_struct *p,
			      struct fss_GetShareMapping *r)
{
	NTSTATUS status;
	struct fss_sc_set *sc_set;
	struct fss_sc *sc;
	struct fss_sc_smap *sc_smap;
	char *share;
	struct fssagent_share_mapping_1 *sm_out;

	TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx);
	if (tmp_ctx == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	if (!fss_permitted(p)) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	/*
	 * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
	 * the call with FSRVP_E_BAD_STATE.
	 * <9> If ShadowCopySet.Status is "Started", "Added",
	 * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
	 * servers return an error value of 0x80042311.
	 */
	if ((sc_set->state == FSS_SC_STARTED)
	 || (sc_set->state == FSS_SC_ADDED)
	 || (sc_set->state == FSS_SC_CREATING)
	 || (sc_set->state == FSS_SC_COMMITED)) {
		talloc_free(tmp_ctx);
		return 0x80042311;	/* documented magic value */
	}

	sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
	if (sc == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	status = fss_unc_parse(tmp_ctx, r->in.ShareName, NULL, &share);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return fss_ntstatus_map(status);
	}

	sc_smap = sc_smap_lookup(sc->smaps, share);
	if (sc_smap == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	if (r->in.Level != 1) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	sm_out = talloc_zero(p->mem_ctx, struct fssagent_share_mapping_1);
	if (sm_out == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}
	sm_out->ShadowCopySetId = sc_set->id;
	sm_out->ShadowCopyId = sc->id;
	sm_out->ShareNameUNC = talloc_asprintf(sm_out, "\\\\%s\\%s",
					       lp_netbios_name(),
					       sc_smap->share_name);
	if (sm_out->ShareNameUNC == NULL) {
		talloc_free(sm_out);
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}
	sm_out->ShadowCopyShareName = sc_smap->sc_share_name;
	unix_to_nt_time(&sm_out->tstamp, sc->create_ts);
	r->out.ShareMapping->ShareMapping1 = sm_out;
	talloc_free(tmp_ctx);

	/* reset msg sequence timer */
	TALLOC_FREE(fss_global.seq_tmr);
	fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);

	return 0;
}
Ejemplo n.º 16
0
uint32_t _fss_AddToShadowCopySet(struct pipes_struct *p,
				 struct fss_AddToShadowCopySet *r)
{
	uint32_t ret;
	struct fss_sc_set *sc_set;
	struct fss_sc *sc;
	struct fss_sc_smap *sc_smap;
	int snum;
	char *service;
	char *base_vol;
	char *share;
	char *path_name;
	struct connection_struct *conn;
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx);
	if (tmp_ctx == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_out;
	}

	if (!fss_permitted(p)) {
		ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
		goto err_tmp_free;
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		ret = HRES_ERROR_V(HRES_E_INVALIDARG);
		goto err_tmp_free;
	}

	status = fss_unc_parse(tmp_ctx, r->in.ShareName, NULL, &share);
	if (!NT_STATUS_IS_OK(status)) {
		ret = fss_ntstatus_map(status);
		goto err_tmp_free;
	}

	snum = find_service(tmp_ctx, share, &service);
	if ((snum == -1) || (service == NULL)) {
		DEBUG(0, ("share at %s not found\n", r->in.ShareName));
		ret = HRES_ERROR_V(HRES_E_INVALIDARG);
		goto err_tmp_free;
	}

	path_name = lp_path(tmp_ctx, snum);
	if (path_name == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_tmp_free;
	}

	status = fss_vfs_conn_create(tmp_ctx, server_event_context(),
				     p->msg_ctx, p->session_info, snum, &conn);
	if (!NT_STATUS_IS_OK(status)) {
		ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
		goto err_tmp_free;
	}
	if (!become_user_by_session(conn, p->session_info)) {
		DEBUG(0, ("failed to become user\n"));
		fss_vfs_conn_destroy(conn);
		ret = HRES_ERROR_V(HRES_E_ACCESSDENIED);
		goto err_tmp_free;
	}

	status = SMB_VFS_SNAP_CHECK_PATH(conn, tmp_ctx, path_name, &base_vol);
	unbecome_user();
	fss_vfs_conn_destroy(conn);
	if (!NT_STATUS_IS_OK(status)) {
		ret = FSRVP_E_NOT_SUPPORTED;
		goto err_tmp_free;
	}

	if ((sc_set->state != FSS_SC_STARTED)
	 && (sc_set->state != FSS_SC_ADDED)) {
		ret = FSRVP_E_BAD_STATE;
		goto err_tmp_free;
	}

	/* stop msg seq timer */
	TALLOC_FREE(fss_global.seq_tmr);

	/*
	 * server MUST look up the ShadowCopy in ShadowCopySet.ShadowCopyList
	 * where ShadowCopy.VolumeName matches the file store on which the
	 * share identified by ShareName is hosted. If an entry is found, the
	 * server MUST fail the call with FSRVP_E_OBJECT_ALREADY_EXISTS.
	 * If no entry is found, the server MUST create a new ShadowCopy
	 * object
	 * XXX Windows appears to allow multiple mappings for the same vol!
	 */
	sc = sc_lookup_volname(sc_set->scs, base_vol);
	if (sc != NULL) {
		ret = FSRVP_E_OBJECT_ALREADY_EXISTS;
		goto err_tmr_restart;
	}

	sc = talloc_zero(sc_set, struct fss_sc);
	if (sc == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_tmr_restart;
	}
	talloc_steal(sc, base_vol);
	sc->volume_name = base_vol;
	sc->sc_set = sc_set;
	sc->create_ts = time(NULL);

	sc->id = GUID_random();	/* Windows servers ignore client ids */
	sc->id_str = GUID_string(sc, &sc->id);
	if (sc->id_str == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_sc_free;
	}

	sc_smap = talloc_zero(sc, struct fss_sc_smap);
	if (sc_smap == NULL) {
		ret = HRES_ERROR_V(HRES_E_OUTOFMEMORY);
		goto err_sc_free;
	}

	talloc_steal(sc_smap, service);
	sc_smap->share_name = service;
	sc_smap->is_exposed = false;
	/*
	 * generate the sc_smap share name now. It is a unique identifier for
	 * the smap used as a tdb key for state storage.
	 */
	ret = map_share_name(sc_smap, sc);
	if (ret) {
		goto err_sc_free;
	}

	/* add share map to shadow-copy */
	DLIST_ADD_END(sc->smaps, sc_smap, struct fss_sc_smap *);
	sc->smaps_count++;
	/* add shadow-copy to shadow-copy set */
	DLIST_ADD_END(sc_set->scs, sc, struct fss_sc *);
	sc_set->scs_count++;
	DEBUG(4, ("added volume %s to shadow copy set with GUID %s\n",
		  sc->volume_name, sc_set->id_str));

	/* start the Message Sequence Timer with timeout of 1800 seconds */
	fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);

	sc_set->state = FSS_SC_ADDED;
	r->out.pShadowCopyId = &sc->id;

	talloc_free(tmp_ctx);
	return 0;

err_sc_free:
	talloc_free(sc);
err_tmr_restart:
	fss_seq_tout_set(fss_global.mem_ctx, 180, sc_set, &fss_global.seq_tmr);
err_tmp_free:
	talloc_free(tmp_ctx);
err_out:
	return ret;
}
Ejemplo n.º 17
0
/*
  push a HRESULT
*/
_PUBLIC_ enum ndr_err_code ndr_push_HRESULT(struct ndr_push *ndr, int ndr_flags, HRESULT status)
{
	return ndr_push_uint32(ndr, NDR_SCALARS, HRES_ERROR_V(status));
}