} END_TEST START_TEST (test_replica_mapping_id_to_guid) { struct GUID *ret_guid, client_guid = GUID_random(); enum MAPISTATUS ret; TALLOC_CTX *mem_ctx; uint16_t repl_id; mem_ctx = talloc_new(NULL); ck_assert(mem_ctx != NULL); ret_guid = talloc_zero(mem_ctx, struct GUID); ck_assert(ret_guid != NULL); ret = openchangedb_replica_mapping_replid_to_guid(g_oc_ctx, USER1, 0x23, ret_guid); ck_assert(ret == MAPI_E_NOT_FOUND); ret = openchangedb_replica_mapping_guid_to_replid(g_oc_ctx, USER1, &client_guid, &repl_id); ck_assert(ret == MAPI_E_SUCCESS); ret = openchangedb_replica_mapping_replid_to_guid(g_oc_ctx, USER1, repl_id, ret_guid); ck_assert(ret == MAPI_E_SUCCESS); ck_assert(GUID_equal(&client_guid, ret_guid)); ck_assert(repl_id > 0x01); talloc_free(mem_ctx); } END_TEST
/* allocate a new rpc handle */ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_context *context, uint8_t handle_type) { struct dcesrv_handle *h; struct dom_sid *sid; sid = context->conn->auth_state.session_info->security_token->user_sid; h = talloc(context->assoc_group, struct dcesrv_handle); if (!h) { return NULL; } h->data = NULL; h->sid = dom_sid_dup(h, sid); if (h->sid == NULL) { talloc_free(h); return NULL; } h->assoc_group = context->assoc_group; h->iface = context->iface; h->wire_handle.handle_type = handle_type; h->wire_handle.uuid = GUID_random(); DLIST_ADD(context->assoc_group->handles, h); talloc_set_destructor(h, dcesrv_handle_destructor); return h; }
/** * basic test for doing a durable open * and do a durable reopen on the same connection * while the first open is still active (fails) */ bool test_durable_v2_open_reopen1(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io; struct GUID create_guid = GUID_random(); bool ret = true; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_reopen1_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, true); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, io.in.timeout); /* try a durable reconnect while the file is still open */ ZERO_STRUCT(io); io.in.fname = ""; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
static bool test_random_uuid(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct rpc_request *req; struct GUID uuid; struct dssetup_DsRoleGetPrimaryDomainInformation r1; struct lsa_GetUserName r2; struct lsa_String *authority_name_p = NULL; struct lsa_String *account_name_p = NULL; torture_comment(torture, "RPC-OBJECTUUID-RANDOM\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_dssetup); torture_assert_ntstatus_ok(torture, status, "opening dsetup pipe1"); status = torture_rpc_connection(torture, &p2, &ndr_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); uuid = GUID_random(); r1.in.level = DS_ROLE_BASIC_INFORMATION; status = dcerpc_ndr_request(p1, &uuid, &ndr_table_dssetup, NDR_DSSETUP_DSROLEGETPRIMARYDOMAININFORMATION, torture, &r1); torture_assert_ntstatus_ok(torture, status, "DsRoleGetPrimaryDomainInformation failed"); torture_assert_werr_ok(torture, r1.out.result, "DsRoleGetPrimaryDomainInformation failed"); uuid = GUID_random(); r2.in.system_name = "\\"; r2.in.account_name = &account_name_p; r2.in.authority_name = &authority_name_p; r2.out.account_name = &account_name_p; r2.out.authority_name = &authority_name_p; status = dcerpc_ndr_request(p2, &uuid, &ndr_table_lsarpc, NDR_LSA_GETUSERNAME, torture, &r2); torture_assert_ntstatus_ok(torture, status, "lsaClose failed"); torture_assert_ntstatus_ok(torture, r2.out.result, "lsaClose failed"); return true; }
} END_TEST START_TEST (test_IDSET_includes_guid_glob) { struct GUID server_guid = GUID_random(); struct GUID random_guid = GUID_random(); int i; struct idset *idset_in; struct rawidset *rawidset_in; const uint16_t repl_id = 0x0001; const uint64_t ids[] = {0x180401000000, 0x190401000000, 0x1a0401000000, 0x1b0401000000, 0x500401000000, 0x520401000000, 0x530401000000, 0x710401000000}; const uint64_t not_in_id = 0x2a0401000000; const size_t ids_size = sizeof(ids) / sizeof(uint64_t); rawidset_in = RAWIDSET_make(mem_ctx, true, false); ck_assert(rawidset_in != NULL); for (i = 0; i < ids_size; i++) { RAWIDSET_push_eid(rawidset_in, (ids[i] << 16) | repl_id); } ck_assert_int_eq(rawidset_in->count, ids_size); rawidset_in->idbased = false; rawidset_in->repl.guid = server_guid; idset_in = RAWIDSET_convert_to_idset(mem_ctx, rawidset_in); ck_assert(idset_in != NULL); /* Case: All inserted elements in the range */ for (i = 0; i < ids_size; i++) { ck_assert(IDSET_includes_guid_glob(idset_in, &server_guid, ids[i])); } /* Case: a different guid for the same id */ ck_assert(!IDSET_includes_guid_glob(idset_in, &random_guid, ids[0])); /* Case: Not in range and different guid */ ck_assert(!IDSET_includes_guid_glob(idset_in, &random_guid, not_in_id)); /* Case: Not in range */ ck_assert(!IDSET_includes_guid_glob(idset_in, &server_guid, not_in_id)); } END_TEST
} END_TEST START_TEST(test_call_replica_mapping_guid_to_replid) { struct GUID guid = GUID_random(); uint16_t replid = 0; CHECK_SUCCESS(openchangedb_replica_mapping_guid_to_replid(oc_ctx, "recipient", &guid, &replid)); ck_assert_int_eq(functions_called.guid_to_replid, 1); ck_assert_int_eq(replid, 0x03); } END_TEST
bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) { struct GUID *dyn_guid; fstring key; size_t size = 0; struct GUID new_guid; #if _SAMBA_BUILD_ == 4 if (strequal(domain, get_global_sam_name()) && (pdb_capabilities() & PDB_CAP_ADS)) { struct pdb_domain_info *domain_info; domain_info = pdb_get_domain_info(talloc_tos()); if (!domain_info) { /* If we have a ADS-capable passdb backend, we * must never make up our own SID, it will * already be in the directory */ DEBUG(0, ("Unable to fetch a Domain GUID from the directory!\n")); return false; } *guid = domain_info->guid; return true; } #endif slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); dyn_guid = (struct GUID *)secrets_fetch(key, &size); if (!dyn_guid) { if (lp_server_role() == ROLE_DOMAIN_PDC) { new_guid = GUID_random(); if (!secrets_store_domain_guid(domain, &new_guid)) return False; dyn_guid = (struct GUID *)secrets_fetch(key, &size); } if (dyn_guid == NULL) { return False; } } if (size != sizeof(struct GUID)) { DEBUG(1,("UUID size %d is wrong!\n", (int)size)); SAFE_FREE(dyn_guid); return False; } *guid = *dyn_guid; SAFE_FREE(dyn_guid); return True; }
static bool test_one_durable_v2_open_lease(struct torture_context *tctx, struct smb2_tree *tree, const char *fname, bool request_persistent, struct durable_open_vs_lease test) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); struct smb2_handle _h; struct smb2_handle *h = NULL; bool ret = true; struct smb2_create io; struct smb2_lease ls; uint64_t lease; smb2_util_unlink(tree, fname); lease = random(); smb2_lease_create_share(&io, &ls, false /* dir */, fname, smb2_util_share_access(test.share_mode), lease, smb2_util_lease_state(test.type)); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = request_persistent; io.in.create_guid = GUID_random(); status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, test.durable); CHECK_VAL(io.out.persistent_open, test.persistent); CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); CHECK_VAL(io.out.lease_response.lease_key.data[0], lease); CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease); CHECK_VAL(io.out.lease_response.lease_state, smb2_util_lease_state(test.type)); done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(mem_ctx); return ret; }
} END_TEST START_TEST (test_replica_mapping_sanity_checks) { struct GUID client_guid = GUID_random(); enum MAPISTATUS ret; ret = openchangedb_replica_mapping_guid_to_replid(g_oc_ctx, USER1, NULL, NULL); ck_assert(ret == MAPI_E_INVALID_PARAMETER); ret = openchangedb_replica_mapping_guid_to_replid(g_oc_ctx, USER1, &client_guid, NULL); ck_assert(ret == MAPI_E_INVALID_PARAMETER); ret = openchangedb_replica_mapping_replid_to_guid(g_oc_ctx, USER1, 0x23, NULL); ck_assert(ret == MAPI_E_INVALID_PARAMETER); } END_TEST
} END_TEST START_TEST (test_replica_mapping_guid_to_id) { struct GUID client_guid = GUID_random(); enum MAPISTATUS ret; uint16_t repl_id; ret = openchangedb_replica_mapping_guid_to_replid(g_oc_ctx, USER1, &client_guid, &repl_id); ck_assert(ret == MAPI_E_SUCCESS); ck_assert_int_eq(repl_id, 0x03); ret = openchangedb_replica_mapping_guid_to_replid(g_oc_ctx, USER1, &client_guid, &repl_id); ck_assert(ret == MAPI_E_SUCCESS); ck_assert_int_eq(repl_id, 0x03); } END_TEST
static bool test_RemoteActivation(struct torture_context *tctx, struct dcerpc_pipe *p) { struct RemoteActivation r; NTSTATUS status; struct GUID iids[1]; uint16_t protseq[3] = { EPM_PROTOCOL_TCP, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }; ZERO_STRUCT(r.in); r.in.this_object.version.MajorVersion = 5; r.in.this_object.version.MinorVersion = 1; r.in.this_object.cid = GUID_random(); GUID_from_string(CLSID_IMAGEDOC, &r.in.Clsid); r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY; r.in.num_protseqs = 3; r.in.protseq = protseq; r.in.Interfaces = 1; GUID_from_string(DCERPC_IUNKNOWN_UUID, &iids[0]); r.in.pIIDs = iids; status = dcerpc_RemoteActivation(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "RemoteActivation"); torture_assert_werr_ok(tctx, r.out.result, "RemoteActivation"); torture_assert_werr_ok(tctx, *r.out.hr, "RemoteActivation"); torture_assert_werr_ok(tctx, r.out.results[0], "RemoteActivation"); GUID_from_string(DCERPC_ICLASSFACTORY_UUID, &iids[0]); r.in.Interfaces = 1; r.in.Mode = MODE_GET_CLASS_OBJECT; status = dcerpc_RemoteActivation(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "RemoteActivation(GetClassObject)"); torture_assert_werr_ok(tctx, r.out.result, "RemoteActivation(GetClassObject)"); torture_assert_werr_ok(tctx, *r.out.hr, "RemoteActivation(GetClassObject)"); torture_assert_werr_ok(tctx, r.out.results[0], "RemoteActivation(GetClassObject)"); return true; }
void lpcfg_smbcli_options(struct loadparm_context *lp_ctx, struct smbcli_options *options) { options->max_xmit = lpcfg_max_xmit(lp_ctx); options->max_mux = lpcfg_max_mux(lp_ctx); options->use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_client_use_spnego(lp_ctx); options->signing = lpcfg_client_signing(lp_ctx); options->request_timeout = SMB_REQUEST_TIMEOUT; options->ntstatus_support = lpcfg_nt_status_support(lp_ctx); options->min_protocol = lpcfg_client_min_protocol(lp_ctx); options->max_protocol = lpcfg__client_max_protocol(lp_ctx); options->unicode = lpcfg_unicode(lp_ctx); options->use_oplocks = true; options->use_level2_oplocks = true; options->smb2_capabilities = SMB2_CAP_ALL; options->client_guid = GUID_random(); }
static bool test_one_durable_v2_open_oplock(struct torture_context *tctx, struct smb2_tree *tree, const char *fname, bool request_persistent, struct durable_open_vs_oplock test) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); struct smb2_handle _h; struct smb2_handle *h = NULL; bool ret = true; struct smb2_create io; smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(test.share_mode), smb2_util_oplock_level(test.level)); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = request_persistent; io.in.create_guid = GUID_random(); status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, test.durable); CHECK_VAL(io.out.persistent_open, test.persistent); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(test.level)); done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(mem_ctx); return ret; }
/** \details Test the SyncOpenAdvisor (0x83) and SetSyncNotificationGuid (0x88) operations This function: -# logs on -# creates a notification advisor -# sets a GUID on the advisor -# cleans up \param mt pointer on the top-level mapitest structure \return true on success, otherwise false */ _PUBLIC_ bool mapitest_oxcnotif_SyncOpenAdvisor(struct mapitest *mt) { enum MAPISTATUS retval; bool ret = true; mapi_object_t obj_store; mapi_object_t obj_notifier; mapi_object_init(&obj_store); mapi_object_init(&obj_notifier); /* Logon */ retval = OpenMsgStore(mt->session, &obj_store); mapitest_print_retval_clean(mt, "OpenMsgStore", retval); if (retval != MAPI_E_SUCCESS) { ret = false; goto cleanup; } /* Create advisor */ retval = SyncOpenAdvisor(&obj_store, &obj_notifier); mapitest_print_retval_clean(mt, "SyncOpenAdvisor", retval); if (retval != MAPI_E_SUCCESS) { ret = false; goto cleanup; } /* Set GUID */ retval = SetSyncNotificationGuid(&obj_notifier, GUID_random()); mapitest_print_retval_clean(mt, "SetSyncNotificationGuid", retval); if (retval != MAPI_E_SUCCESS) { ret = false; goto cleanup; } /* Cleanup */ cleanup: mapi_object_release(&obj_notifier); mapi_object_release(&obj_store); return ret; }
/* create a transport structure based on an established socket */ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock, TALLOC_CTX *parent_ctx, struct smbcli_options *options) { struct smb2_transport *transport; struct GUID client_guid; uint32_t smb2_capabilities = 0; transport = talloc_zero(parent_ctx, struct smb2_transport); if (!transport) return NULL; transport->ev = sock->event.ctx; transport->options = *options; TALLOC_FREE(sock->event.fde); TALLOC_FREE(sock->event.te); client_guid = GUID_random(); /* TODO: hand this in via the options? */ smb2_capabilities = SMB2_CAP_ALL; transport->conn = smbXcli_conn_create(transport, sock->sock->fd, sock->hostname, options->signing, 0, /* smb1_capabilities */ &client_guid, smb2_capabilities); if (transport->conn == NULL) { talloc_free(transport); return NULL; } sock->sock->fd = -1; TALLOC_FREE(sock); talloc_set_destructor(transport, transport_destructor); return transport; }
static PyObject *uuid_random(PyObject *self, PyObject *args) { struct GUID guid; PyObject *pyobj; char *str; if (!PyArg_ParseTuple(args, "")) return NULL; guid = GUID_random(); str = GUID_string(NULL, &guid); if (str == NULL) { PyErr_SetString(PyExc_TypeError, "can't convert uuid to string"); return NULL; } pyobj = PyString_FromString(str); talloc_free(str); return pyobj; }
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; }
/** * lease_v2 variant of reopen2 * basic test for doing a durable open * tcp disconnect, reconnect, do a durable reopen (succeeds) */ bool test_durable_v2_open_reopen2_lease_v2(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io; struct GUID create_guid = GUID_random(); struct smb2_lease ls; uint64_t lease_key; bool ret = true; struct smbcli_options options; uint32_t caps; caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); if (!(caps & SMB2_CAP_LEASING)) { torture_skip(tctx, "leases are not supported"); } options = tree->session->transport->options; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_reopen2_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); lease_key = random(); smb2_lease_v2_create(&io, &ls, false /* dir */, fname, lease_key, 0, /* parent lease key */ smb2_util_lease_state("RWH"), 0 /* lease epoch */); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, true); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, io.in.timeout); CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); CHECK_VAL(io.out.lease_response_v2.lease_key.data[0], lease_key); CHECK_VAL(io.out.lease_response_v2.lease_key.data[1], ~lease_key); /* disconnect, reconnect and then do durable reopen */ TALLOC_FREE(tree); if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } /* a few failure tests: */ /* * several attempts without lease attached: * all fail with NT_STATUS_OBJECT_NAME_NOT_FOUND * irrespective of file name provided */ ZERO_STRUCT(io); io.in.fname = ""; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io); io.in.fname = "__non_existing_fname__"; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); /* * attempt with lease provided, but * with a changed lease key. => fails */ ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; io.in.lease_request_v2 = &ls; io.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE; /* a wrong lease key lets the request fail */ ls.lease_key.data[0]++; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); /* restore the correct lease key */ ls.lease_key.data[0]--; /* * this last failing attempt is almost correct: * only problem is: we use the wrong filename... * Note that this gives INVALID_PARAMETER. * This is different from oplocks! */ ZERO_STRUCT(io); io.in.fname = "__non_existing_fname__"; io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; io.in.lease_request_v2 = &ls; io.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); /* * Now for a succeeding reconnect: */ ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; io.in.lease_request_v2 = &ls; io.in.oplock_level = SMB2_OPLOCK_LEVEL_LEASE; /* the requested lease state is irrelevant */ ls.lease_state = smb2_util_lease_state(""); h = NULL; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */ CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); CHECK_VAL(io.out.lease_response_v2.lease_key.data[0], lease_key); CHECK_VAL(io.out.lease_response_v2.lease_key.data[1], ~lease_key); CHECK_VAL(io.out.lease_response_v2.lease_state, smb2_util_lease_state("RWH")); CHECK_VAL(io.out.lease_response_v2.lease_flags, 0); CHECK_VAL(io.out.lease_response_v2.lease_duration, 0); _h = io.out.file.handle; h = &_h; /* disconnect one more time */ TALLOC_FREE(tree); if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } /* * demonstrate that various parameters are ignored * in the reconnect */ ZERO_STRUCT(io); /* * These are completely ignored by the server */ io.in.security_flags = 0x78; io.in.oplock_level = 0x78; io.in.impersonation_level = 0x12345678; io.in.create_flags = 0x12345678; io.in.reserved = 0x12345678; io.in.desired_access = 0x12345678; io.in.file_attributes = 0x12345678; io.in.share_access = 0x12345678; io.in.create_disposition = 0x12345678; io.in.create_options = 0x12345678; io.in.fname = "__non_existing_fname__"; /* * only these are checked: * - io.in.fname * - io.in.durable_handle_v2, * - io.in.create_guid * - io.in.lease_request_v2->lease_key */ io.in.fname = fname; io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; io.in.lease_request_v2 = &ls; /* the requested lease state is irrelevant */ ls.lease_state = smb2_util_lease_state(""); h = NULL; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */ CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); CHECK_VAL(io.out.lease_response_v2.lease_key.data[0], lease_key); CHECK_VAL(io.out.lease_response_v2.lease_key.data[1], ~lease_key); CHECK_VAL(io.out.lease_response_v2.lease_state, smb2_util_lease_state("RWH")); CHECK_VAL(io.out.lease_response_v2.lease_flags, 0); CHECK_VAL(io.out.lease_response_v2.lease_duration, 0); _h = io.out.file.handle; h = &_h; done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/** * Test durable request / reconnect with AppInstanceId */ bool test_durable_v2_open_app_instance(struct torture_context *tctx, struct smb2_tree *tree1, struct smb2_tree *tree2) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h1, _h2; struct smb2_handle *h1 = NULL, *h2 = NULL; struct smb2_create io1, io2; bool ret = true; struct GUID create_guid_1 = GUID_random(); struct GUID create_guid_2 = GUID_random(); struct GUID app_instance_id = GUID_random(); /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_app_instance_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree1, fname); ZERO_STRUCT(break_info); tree1->session->transport->oplock.handler = torture_oplock_handler; tree1->session->transport->oplock.private_data = tree1; smb2_oplock_create_share(&io1, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io1.in.durable_open = false; io1.in.durable_open_v2 = true; io1.in.persistent_open = false; io1.in.create_guid = create_guid_1; io1.in.app_instance_id = &app_instance_id; io1.in.timeout = UINT32_MAX; status = smb2_create(tree1, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); _h1 = io1.out.file.handle; h1 = &_h1; CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io1.out.durable_open, false); CHECK_VAL(io1.out.durable_open_v2, true); CHECK_VAL(io1.out.persistent_open, false); CHECK_VAL(io1.out.timeout, io1.in.timeout); /* * try to open the file as durable from a second tree with * a different create guid but the same app_instance_id * while the first handle is still open. */ smb2_oplock_create_share(&io2, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io2.in.durable_open = false; io2.in.durable_open_v2 = true; io2.in.persistent_open = false; io2.in.create_guid = create_guid_2; io2.in.app_instance_id = &app_instance_id; io2.in.timeout = UINT32_MAX; status = smb2_create(tree2, mem_ctx, &io2); CHECK_STATUS(status, NT_STATUS_OK); _h2 = io2.out.file.handle; h2 = &_h2; CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io2.out.durable_open, false); CHECK_VAL(io2.out.durable_open_v2, true); CHECK_VAL(io2.out.persistent_open, false); CHECK_VAL(io2.out.timeout, io2.in.timeout); CHECK_VAL(break_info.count, 0); status = smb2_util_close(tree1, *h1); CHECK_STATUS(status, NT_STATUS_FILE_CLOSED); h1 = NULL; done: if (h1 != NULL) { smb2_util_close(tree1, *h1); } if (h2 != NULL) { smb2_util_close(tree2, *h2); } smb2_util_unlink(tree2, fname); talloc_free(tree1); talloc_free(tree2); talloc_free(mem_ctx); return ret; }
/** * Basic test for doing a durable open * and do a session reconnect while the first * session is still active and the handle is * still open in the client. * This closes the original session and a * durable reconnect on the new session succeeds. */ bool test_durable_v2_open_reopen1a(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io, io2; struct GUID create_guid = GUID_random(); bool ret = true; struct smb2_tree *tree2 = NULL; uint64_t previous_session_id; struct smbcli_options options; options = tree->session->transport->options; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_reopen1a_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, true); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, io.in.timeout); /* * a session reconnect on a second tcp connection */ previous_session_id = smb2cli_session_current_id(tree->session->smbXcli); if (!torture_smb2_connection_ext(tctx, previous_session_id, &options, &tree2)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } /* * check that this has deleted the old session */ ZERO_STRUCT(io); io.in.fname = ""; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED); /* * but a durable reconnect on the new session succeeds: */ ZERO_STRUCT(io2); io2.in.fname = ""; io2.in.durable_handle_v2 = h; io2.in.create_guid = create_guid; status = smb2_create(tree2, mem_ctx, &io2); CHECK_STATUS(status, NT_STATUS_OK); CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io2.out.durable_open, false); CHECK_VAL(io2.out.durable_open_v2, false); /* no dh2q response blob */ CHECK_VAL(io2.out.persistent_open, false); CHECK_VAL(io2.out.timeout, io.in.timeout); _h = io2.out.file.handle; h = &_h; done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
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; }
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; }
/** * testing various create blob combinations. */ bool test_durable_v2_open_create_blob(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io; struct GUID create_guid = GUID_random(); bool ret = true; struct smbcli_options options; options = tree->session->transport->options; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_create_blob_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, true); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, io.in.timeout); /* disconnect */ TALLOC_FREE(tree); /* create a new session (same client_guid) */ if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } /* * check invalid combinations of durable handle * request and reconnect blobs * See MS-SMB2: 3.3.5.9.12 * Handling the SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context */ ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; /* durable v2 reconnect request */ io.in.durable_open = true; /* durable v1 handle request */ io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle = h; /* durable v1 reconnect request */ io.in.durable_open_v2 = true; /* durable v2 handle request */ io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle = h; /* durable v1 reconnect request */ io.in.durable_handle_v2 = h; /* durable v2 reconnect request */ io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; /* durable v2 reconnect request */ io.in.durable_open_v2 = true; /* durable v2 handle request */ io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/* test netlogon operations */ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) { struct cldap_socket *cldap; NTSTATUS status; struct cldap_netlogon search, empty_search; struct netlogon_samlogon_response n1; struct GUID guid; int i; struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); struct tsocket_address *dest_addr; int ret; ret = tsocket_address_inet_from_strings(tctx, "ip", dest, lp_cldap_port(tctx->lp_ctx), &dest_addr); status = cldap_socket_init(tctx, NULL, NULL, dest_addr, &cldap); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(search); search.in.dest_address = NULL; search.in.dest_port = 0; search.in.acct_control = -1; search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; empty_search = search; printf("Trying without any attributes\n"); search = empty_search; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; search.in.user = "******"; search.in.realm = n1.data.nt5_ex.dns_domain; search.in.host = "__cldap_torture__"; printf("Scanning for netlogon levels\n"); for (i=0;i<256;i++) { search.in.version = i; printf("Trying netlogon level %d\n", i); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } printf("Scanning for netlogon level bits\n"); for (i=0;i<31;i++) { search.in.version = (1<<i); printf("Trying netlogon level 0x%x\n", i); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=NULL\n"); search.in.user = NULL; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); printf("Trying with User=Administrator\n"); search.in.user = "******"; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); search.in.version = NETLOGON_NT_VERSION_5; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=NULL\n"); search.in.user = NULL; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE); printf("Trying with User=Administrator\n"); search.in.user = "******"; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN); search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; printf("Trying with a GUID\n"); search.in.realm = NULL; search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid); printf("Trying with a incorrect GUID\n"); guid = GUID_random(); search.in.user = NULL; search.in.domain_guid = GUID_string(tctx, &guid); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a AAC\n"); search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST; search.in.realm = n1.data.nt5_ex.dns_domain; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a zero AAC\n"); search.in.acct_control = 0x0; search.in.realm = n1.data.nt5_ex.dns_domain; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a zero AAC and user=Administrator\n"); search.in.acct_control = 0x0; search.in.user = "******"; search.in.realm = n1.data.nt5_ex.dns_domain; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator"); printf("Trying with a bad AAC\n"); search.in.user = NULL; search.in.acct_control = 0xFF00FF00; search.in.realm = n1.data.nt5_ex.dns_domain; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a user only\n"); search = empty_search; search.in.user = "******"; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); printf("Trying with just a bad username\n"); search.in.user = "******"; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); printf("Trying with just a bad domain\n"); search = empty_search; search.in.realm = "___no_such_domain___"; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a incorrect domain and correct guid\n"); search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); printf("Trying with a incorrect domain and incorrect guid\n"); search.in.domain_guid = GUID_string(tctx, &guid); status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); printf("Trying with a incorrect GUID and correct domain\n"); search.in.domain_guid = GUID_string(tctx, &guid); search.in.realm = n1.data.nt5_ex.dns_domain; status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); return true; }
/** * durable reconnect test: * connect with v1, reconnect with v2 : fails (no create_guid...) */ bool test_durable_v2_open_reopen2c(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io; struct GUID create_guid = GUID_random(); bool ret = true; struct smbcli_options options; options = tree->session->transport->options; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_reopen2c_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io.in.durable_open = true; io.in.durable_open_v2 = false; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io.out.durable_open, true); CHECK_VAL(io.out.durable_open_v2, false); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, 0); /* disconnect, leaving the durable open */ TALLOC_FREE(tree); if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; /* durable v2 reconnect */ io.in.create_guid = create_guid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
NTSTATUS gp_create_gpo (struct gp_context *gp_ctx, const char *display_name, struct gp_object **ret) { struct GUID guid_struct; char *guid_str; char *name; struct security_descriptor *sd; TALLOC_CTX *mem_ctx; struct gp_object *gpo; NTSTATUS status; /* Create a forked memory context, as a base for everything here */ mem_ctx = talloc_new(gp_ctx); NT_STATUS_HAVE_NO_MEMORY(mem_ctx); /* Create the gpo struct to return later */ gpo = talloc(gp_ctx, struct gp_object); if (gpo == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Generate a GUID */ guid_struct = GUID_random(); guid_str = GUID_string2(mem_ctx, &guid_struct); if (guid_str == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } name = strupper_talloc(mem_ctx, guid_str); if (name == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Prepare the GPO struct */ gpo->dn = NULL; gpo->name = name; gpo->flags = 0; gpo->version = 0; gpo->display_name = talloc_strdup(gpo, display_name); if (gpo->display_name == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } gpo->file_sys_path = talloc_asprintf(gpo, "\\\\%s\\sysvol\\%s\\Policies\\%s", lpcfg_dnsdomain(gp_ctx->lp_ctx), lpcfg_dnsdomain(gp_ctx->lp_ctx), name); if (gpo->file_sys_path == NULL) { TALLOC_FREE(mem_ctx); return NT_STATUS_NO_MEMORY; } /* Create the GPT */ status = gp_create_gpt(gp_ctx, name, gpo->file_sys_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create GPT\n")); talloc_free(mem_ctx); return status; } /* Create the LDAP GPO, including CN=User and CN=Machine */ status = gp_create_ldap_gpo(gp_ctx, gpo); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create LDAP group policy object\n")); talloc_free(mem_ctx); return status; } /* Get the new security descriptor */ status = gp_get_gpo_info(gp_ctx, gpo->dn, &gpo); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to fetch LDAP group policy object\n")); talloc_free(mem_ctx); return status; } /* Create matching file and DS security descriptors */ status = gp_create_gpt_security_descriptor(mem_ctx, gpo->security_descriptor, &sd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to convert ADS security descriptor to filesystem security descriptor\n")); talloc_free(mem_ctx); return status; } /* Set the security descriptor on the filesystem for this GPO */ status = gp_set_gpt_security_descriptor(gp_ctx, gpo, sd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to set security descriptor (ACL) on the file system\n")); talloc_free(mem_ctx); return status; } talloc_free(mem_ctx); *ret = gpo; return NT_STATUS_OK; }
/* test netlogon operations */ static bool test_ldap_netlogon(struct torture_context *tctx, request_netlogon_t request_netlogon, void *cldap, const char *dest) { NTSTATUS status; struct cldap_netlogon search, empty_search; struct netlogon_samlogon_response n1; struct GUID guid; int i; ZERO_STRUCT(search); search.in.dest_address = NULL; search.in.dest_port = 0; search.in.acct_control = -1; search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; empty_search = search; printf("Trying without any attributes\n"); search = empty_search; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; search.in.user = "******"; search.in.realm = n1.data.nt5_ex.dns_domain; search.in.host = "__cldap_torture__"; printf("Scanning for netlogon levels\n"); for (i=0;i<256;i++) { search.in.version = i; printf("Trying netlogon level %d\n", i); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } printf("Scanning for netlogon level bits\n"); for (i=0;i<31;i++) { search.in.version = (1<<i); printf("Trying netlogon level 0x%x\n", i); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=NULL\n"); search.in.user = NULL; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); torture_assert(tctx, strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, "PDC name should not be in UNC form"); printf("Trying with User=Administrator\n"); search.in.user = "******"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); torture_assert(tctx, strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, "PDC name should not be in UNC form"); search.in.version = NETLOGON_NT_VERSION_5; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=NULL\n"); search.in.user = NULL; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); torture_assert(tctx, strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL, "PDC name should be in UNC form"); printf("Trying with User=Administrator\n"); search.in.user = "******"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); torture_assert(tctx, strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL, "PDC name should be in UNC form"); search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; printf("Trying with a GUID\n"); search.in.realm = NULL; search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid); torture_assert(tctx, strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL, "PDC name should not be in UNC form"); printf("Trying with a incorrect GUID\n"); guid = GUID_random(); search.in.user = NULL; search.in.domain_guid = GUID_string(tctx, &guid); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a AAC\n"); search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST; search.in.realm = n1.data.nt5_ex.dns_domain; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a zero AAC\n"); search.in.acct_control = 0x0; search.in.realm = n1.data.nt5_ex.dns_domain; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a zero AAC and user=Administrator\n"); search.in.acct_control = 0x0; search.in.user = "******"; search.in.realm = n1.data.nt5_ex.dns_domain; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator"); printf("Trying with a bad AAC\n"); search.in.user = NULL; search.in.acct_control = 0xFF00FF00; search.in.realm = n1.data.nt5_ex.dns_domain; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); printf("Trying with a user only\n"); search = empty_search; search.in.user = "******"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); printf("Trying with just a bad username\n"); search.in.user = "******"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); printf("Trying with just a bad domain\n"); search = empty_search; search.in.realm = "___no_such_domain___"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a incorrect domain and correct guid\n"); search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); printf("Trying with a incorrect domain and incorrect guid\n"); search.in.domain_guid = GUID_string(tctx, &guid); status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); printf("Trying with a incorrect GUID and correct domain\n"); search.in.domain_guid = GUID_string(tctx, &guid); search.in.realm = n1.data.nt5_ex.dns_domain; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, ""); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); printf("Proof other results\n"); search.in.user = "******"; status = request_netlogon(cldap, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain); CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name); CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user); CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site); CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site); return true; }
/** * basic test for doing a durable open * tcp disconnect, reconnect, do a durable reopen (succeeds) */ bool test_durable_v2_open_reopen2(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h; struct smb2_handle *h = NULL; struct smb2_create io; struct GUID create_guid = GUID_random(); struct GUID create_guid_invalid = GUID_random(); bool ret = true; /* Choose a random name in case the state is left a little funky. */ snprintf(fname, 256, "durable_v2_open_reopen2_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); io.in.durable_open = false; io.in.durable_open_v2 = true; io.in.persistent_open = false; io.in.create_guid = create_guid; io.in.timeout = UINT32_MAX; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); _h = io.out.file.handle; h = &_h; CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, true); CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.timeout, io.in.timeout); /* disconnect, leaving the durable open */ TALLOC_FREE(tree); if (!torture_smb2_connection(tctx, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } /* * first a few failure cases */ ZERO_STRUCT(io); io.in.fname = ""; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io); io.in.fname = "__non_existing_fname__"; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); /* a non-zero but non-matching create_guid does not change it: */ ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid_invalid; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); /* * now success: * The important difference is that the create_guid is provided. */ ZERO_STRUCT(io); io.in.fname = fname; io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; h = NULL; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */ CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); _h = io.out.file.handle; h = &_h; /* disconnect one more time */ TALLOC_FREE(tree); if (!torture_smb2_connection(tctx, &tree)) { torture_warning(tctx, "couldn't reconnect, bailing\n"); ret = false; goto done; } ZERO_STRUCT(io); /* These are completely ignored by the server */ io.in.security_flags = 0x78; io.in.oplock_level = 0x78; io.in.impersonation_level = 0x12345678; io.in.create_flags = 0x12345678; io.in.reserved = 0x12345678; io.in.desired_access = 0x12345678; io.in.file_attributes = 0x12345678; io.in.share_access = 0x12345678; io.in.create_disposition = 0x12345678; io.in.create_options = 0x12345678; io.in.fname = "__non_existing_fname__"; /* * only io.in.durable_handle_v2 and * io.in.create_guid are checked */ io.in.durable_open_v2 = false; io.in.durable_handle_v2 = h; io.in.create_guid = create_guid; h = NULL; status = smb2_create(tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io.out.durable_open, false); CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */ CHECK_VAL(io.out.persistent_open, false); CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); _h = io.out.file.handle; h = &_h; done: if (h != NULL) { smb2_util_close(tree, *h); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/* test netlogon operations */ static BOOL test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest) { struct cldap_socket *cldap = cldap_socket_init(mem_ctx, NULL); NTSTATUS status; struct cldap_netlogon search, empty_search; union nbt_cldap_netlogon n1; struct GUID guid; int i; BOOL ret = True; ZERO_STRUCT(search); search.in.dest_address = dest; search.in.acct_control = -1; search.in.version = 6; empty_search = search; printf("Trying without any attributes\n"); search = empty_search; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; search.in.user = "******"; search.in.realm = n1.logon5.dns_domain; search.in.host = "__cldap_torture__"; printf("Scanning for netlogon levels\n"); for (i=0;i<256;i++) { search.in.version = i; printf("Trying netlogon level %d\n", i); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } printf("Scanning for netlogon level bits\n"); for (i=0;i<31;i++) { search.in.version = (1<<i); printf("Trying netlogon level 0x%x\n", i); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } search.in.version = 6; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=NULL\n"); search.in.user = NULL; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with User=Administrator\n"); search.in.user = "******"; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with a GUID\n"); search.in.realm = NULL; search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with a incorrect GUID\n"); guid = GUID_random(); search.in.user = NULL; search.in.domain_guid = GUID_string(mem_ctx, &guid); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a AAC\n"); search.in.acct_control = 0x180; search.in.realm = n1.logon5.dns_domain; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with a bad AAC\n"); search.in.acct_control = 0xFF00FF00; search.in.realm = n1.logon5.dns_domain; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with a user only\n"); search = empty_search; search.in.user = "******"; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with just a bad username\n"); search.in.user = "******"; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with just a bad domain\n"); search = empty_search; search.in.realm = "___no_such_domain___"; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a incorrect domain and correct guid\n"); search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); printf("Trying with a incorrect domain and incorrect guid\n"); search.in.domain_guid = GUID_string(mem_ctx, &guid); status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_NOT_FOUND); printf("Trying with a incorrect GUID and correct domain\n"); search.in.domain_guid = GUID_string(mem_ctx, &guid); search.in.realm = n1.logon5.dns_domain; status = cldap_netlogon(cldap, mem_ctx, &search); CHECK_STATUS(status, NT_STATUS_OK); done: return ret; }
struct cli_state *cli_state_create(TALLOC_CTX *mem_ctx, int fd, const char *remote_name, const char *remote_realm, int signing_state, int flags) { struct cli_state *cli = NULL; bool use_spnego = lp_client_use_spnego(); bool force_dos_errors = false; bool force_ascii = false; bool use_level_II_oplocks = false; uint32_t smb1_capabilities = 0; uint32_t smb2_capabilities = 0; struct GUID client_guid = GUID_random(); /* Check the effective uid - make sure we are not setuid */ if (is_setuid_root()) { DEBUG(0,("libsmb based programs must *NOT* be setuid root.\n")); return NULL; } cli = talloc_zero(mem_ctx, struct cli_state); if (!cli) { return NULL; } cli->server_domain = talloc_strdup(cli, ""); if (!cli->server_domain) { goto error; } cli->server_os = talloc_strdup(cli, ""); if (!cli->server_os) { goto error; } cli->server_type = talloc_strdup(cli, ""); if (!cli->server_type) { goto error; } cli->dfs_mountpoint = talloc_strdup(cli, ""); if (!cli->dfs_mountpoint) { goto error; } cli->raw_status = NT_STATUS_INTERNAL_ERROR; cli->map_dos_errors = true; /* remove this */ cli->timeout = CLIENT_TIMEOUT; cli->case_sensitive = false; /* Set the CLI_FORCE_DOSERR environment variable to test client routines using DOS errors instead of STATUS32 ones. This intended only as a temporary hack. */ if (getenv("CLI_FORCE_DOSERR")) { force_dos_errors = true; } if (flags & CLI_FULL_CONNECTION_FORCE_DOS_ERRORS) { force_dos_errors = true; } if (getenv("CLI_FORCE_ASCII")) { force_ascii = true; } if (!lp_unicode()) { force_ascii = true; } if (flags & CLI_FULL_CONNECTION_FORCE_ASCII) { force_ascii = true; } if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) { use_spnego = false; } else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) { cli->use_kerberos = true; } if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) && cli->use_kerberos) { cli->fallback_after_kerberos = true; } if (flags & CLI_FULL_CONNECTION_USE_CCACHE) { cli->use_ccache = true; } if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) { cli->pw_nt_hash = true; } if (flags & CLI_FULL_CONNECTION_OPLOCKS) { cli->use_oplocks = true; } if (flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) { use_level_II_oplocks = true; } if (signing_state == SMB_SIGNING_DEFAULT) { signing_state = lp_client_signing(); } smb1_capabilities = 0; smb1_capabilities |= CAP_LARGE_FILES; smb1_capabilities |= CAP_NT_SMBS | CAP_RPC_REMOTE_APIS; smb1_capabilities |= CAP_LOCK_AND_READ | CAP_NT_FIND; smb1_capabilities |= CAP_DFS | CAP_W2K_SMBS; smb1_capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX; smb1_capabilities |= CAP_LWIO; if (!force_dos_errors) { smb1_capabilities |= CAP_STATUS32; } if (!force_ascii) { smb1_capabilities |= CAP_UNICODE; } if (use_spnego) { smb1_capabilities |= CAP_EXTENDED_SECURITY; } if (use_level_II_oplocks) { smb1_capabilities |= CAP_LEVEL_II_OPLOCKS; } smb2_capabilities = SMB2_CAP_ALL; if (remote_realm) { cli->remote_realm = talloc_strdup(cli, remote_realm); if (cli->remote_realm == NULL) { goto error; } } cli->conn = smbXcli_conn_create(cli, fd, remote_name, signing_state, smb1_capabilities, &client_guid, smb2_capabilities); if (cli->conn == NULL) { goto error; } cli->smb1.pid = (uint16_t)getpid(); cli->smb1.vc_num = cli->smb1.pid; cli->smb1.tcon = smbXcli_tcon_create(cli); if (cli->smb1.tcon == NULL) { goto error; } smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX); cli->smb1.session = smbXcli_session_create(cli, cli->conn); if (cli->smb1.session == NULL) { goto error; } cli->initialised = 1; return cli; /* Clean up after malloc() error */ error: TALLOC_FREE(cli); return NULL; }