static bool test_sids2unixids1(TALLOC_CTX *memctx, struct idmap_domain *dom) { NTSTATUS status; struct id_map uid_map, gid_map, **test_maps; ZERO_STRUCT(uid_map); ZERO_STRUCT(gid_map); /* create two mappings for a UID and GID */ uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1000"); uid_map.xid.type = ID_TYPE_UID; gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1001"); gid_map.xid.type = ID_TYPE_GID; status = idmap_tdb_common_new_mapping(dom, &uid_map); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2unixids1: could not create uid map!\n")); return false; } status = idmap_tdb_common_new_mapping(dom, &gid_map); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2unixids1: could not create gid map!\n")); return false; } /* now read them back */ test_maps = talloc_zero_array(memctx, struct id_map*, 3); test_maps[0] = talloc(test_maps, struct id_map); test_maps[1] = talloc(test_maps, struct id_map); test_maps[2] = NULL; test_maps[0]->sid = talloc(test_maps, struct dom_sid); test_maps[1]->sid = talloc(test_maps, struct dom_sid); sid_copy(test_maps[0]->sid, uid_map.sid); sid_copy(test_maps[1]->sid, gid_map.sid); status = idmap_tdb_common_sids_to_unixids(dom, test_maps); if(!NT_STATUS_IS_OK(status)) { DEBUG(0, ("test_sids2sunixids1: sids2unixids failed!\n")); talloc_free(test_maps); return false; } if(test_maps[0]->xid.id!=uid_map.xid.id || test_maps[1]->xid.id!=gid_map.xid.id ) { DEBUG(0, ("test_sids2unixids1: sid2unixid returned wrong xid!\n")); talloc_free(test_maps); return false; } DEBUG(0, ("test_sids2unixids1: PASSED!\n")); talloc_free(test_maps); return true; }
static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain, const char *name, const char **authority_name, struct dom_sid **sid, uint32_t *rtype) { int i; for (i=0; well_known[i].sid; i++) { if (domain) { if (strcasecmp_m(domain, well_known[i].domain) == 0 && strcasecmp_m(name, well_known[i].name) == 0) { *authority_name = well_known[i].domain; *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid); *rtype = well_known[i].rtype; return NT_STATUS_OK; } } else { if (strcasecmp_m(name, well_known[i].name) == 0) { *authority_name = well_known[i].domain; *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid); *rtype = well_known[i].rtype; return NT_STATUS_OK; } } } return NT_STATUS_NOT_FOUND; }
static bool desc_ace_has_generic(TALLOC_CTX *mem_ctx, struct security_ace *ace) { struct dom_sid *co, *cg; co = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_OWNER); cg = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_GROUP); if (ace->access_mask & SEC_GENERIC_ALL || ace->access_mask & SEC_GENERIC_READ || ace->access_mask & SEC_GENERIC_WRITE || ace->access_mask & SEC_GENERIC_EXECUTE) { return true; } if (dom_sid_equal(&ace->trustee, co) || dom_sid_equal(&ace->trustee, cg)) { return true; } return false; }
/* convert a string to a dom_sid, returning a talloc'd dom_sid */ struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid) { char p[sid->length+1]; memcpy(p, sid->data, sid->length); p[sid->length] = '\0'; return dom_sid_parse_talloc(mem_ctx, p); }
static PyObject *py_samdb_set_domain_sid(PyLdbObject *self, PyObject *args) { PyObject *py_ldb, *py_sid; struct ldb_context *ldb; struct dom_sid *sid; bool ret; if (!PyArg_ParseTuple(args, "OO", &py_ldb, &py_sid)) return NULL; PyErr_LDB_OR_RAISE(py_ldb, ldb); sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid)); if (sid == NULL) { PyErr_NoMemory(); return NULL; } ret = samdb_set_domain_sid(ldb, sid); talloc_free(sid); if (!ret) { PyErr_SetString(PyExc_RuntimeError, "set_domain_sid failed"); return NULL; } Py_RETURN_NONE; }
NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call) { struct composite_context *ctx; struct wbsrv_service *service = s3call->wbconn->listen_socket->service; struct dom_sid *sid; DEBUG(5, ("wbsrv_samba3_lookupsid called\n")); sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid); if (sid == NULL) { DEBUG(5, ("Could not parse sid %s\n", s3call->request.data.sid)); return NT_STATUS_NO_MEMORY; } ctx = wb_cmd_lookupsid_send(s3call, service, sid); NT_STATUS_HAVE_NO_MEMORY(ctx); /* setup the callbacks */ ctx->async.fn = lookupsid_recv_name; ctx->async.private_data = s3call; s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; return NT_STATUS_OK; }
static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx, struct netr_SamInfo3 *info3) { NTSTATUS status; struct dom_sid *system_sid; /* Set account name */ init_lsa_String(&info3->base.account_name, "SYSTEM"); /* Set domain name */ init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY"); /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */ /* Domain sid is NT_AUTHORITY */ system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM); if (system_sid == NULL) { return NT_STATUS_NO_MEMORY; } status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid, &info3->base.rid); TALLOC_FREE(system_sid); if (!NT_STATUS_IS_OK(status)) { return status; } /* Primary gid is the same */ info3->base.primary_gid = info3->base.rid; return NT_STATUS_OK; }
static void desc_expand_generic(TALLOC_CTX *mem_ctx, struct security_ace *new_ace, struct dom_sid *owner, struct dom_sid *group) { struct dom_sid *co, *cg; co = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_OWNER); cg = dom_sid_parse_talloc(mem_ctx, SID_CREATOR_GROUP); new_ace->access_mask = map_generic_rights_ds(new_ace->access_mask); if (dom_sid_equal(&new_ace->trustee, co)) { new_ace->trustee = *owner; } if (dom_sid_equal(&new_ace->trustee, cg)) { new_ace->trustee = *group; } new_ace->flags = 0x0; }
/* do some samr ops using the schannel connection */ static BOOL test_samr_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct samr_GetDomPwInfo r; struct samr_Connect connect; struct samr_OpenDomain opendom; int i; struct lsa_String name; struct policy_handle handle; struct policy_handle domain_handle; name.string = lp_workgroup(); r.in.domain_name = &name; connect.in.system_name = 0; connect.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; connect.out.connect_handle = &handle; printf("Testing Connect and OpenDomain on BUILTIN\n"); status = dcerpc_samr_Connect(p, mem_ctx, &connect); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { printf("Connect failed (expected, schannel mapped to anonymous): %s\n", nt_errstr(status)); } else { printf("Connect failed - %s\n", nt_errstr(status)); return False; } } else { opendom.in.connect_handle = &handle; opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; opendom.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32"); opendom.out.domain_handle = &domain_handle; status = dcerpc_samr_OpenDomain(p, mem_ctx, &opendom); if (!NT_STATUS_IS_OK(status)) { printf("OpenDomain failed - %s\n", nt_errstr(status)); return False; } } printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string); /* do several ops to test credential chaining */ for (i=0;i<5;i++) { status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { printf("GetDomPwInfo op %d failed - %s\n", i, nt_errstr(status)); return False; } } } return True; }
/* convert a string to a dom_sid, returning a talloc'd dom_sid */ struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid) { struct dom_sid *ret; char *p = talloc_strndup(mem_ctx, (char *)sid->data, sid->length); if (!p) { return NULL; } ret = dom_sid_parse_talloc(mem_ctx, p); talloc_free(p); return ret; }
bool security_token_is_sid_string(const struct security_token *token, const char *sid_string) { bool ret; struct dom_sid *sid = dom_sid_parse_talloc(NULL, sid_string); if (!sid) return false; ret = security_token_is_sid(token, sid); talloc_free(sid); return ret; }
/* decode a SID It can either be a special 2 letter code, or in S-* format */ static struct dom_sid *sddl_decode_sid(TALLOC_CTX *mem_ctx, const char **sddlp, const struct dom_sid *domain_sid) { const char *sddl = (*sddlp); int i; /* see if its in the numeric format */ if (strncmp(sddl, "S-", 2) == 0) { struct dom_sid *sid; char *sid_str; size_t len = strspn(sddl+2, "-0123456789"); sid_str = talloc_strndup(mem_ctx, sddl, len+2); if (!sid_str) { return NULL; } (*sddlp) += len+2; sid = dom_sid_parse_talloc(mem_ctx, sid_str); talloc_free(sid_str); return sid; } /* now check for one of the special codes */ for (i=0;i<ARRAY_SIZE(sid_codes);i++) { if (strncmp(sid_codes[i].code, sddl, 2) == 0) break; } if (i == ARRAY_SIZE(sid_codes)) { DEBUG(1,("Unknown sddl sid code '%2.2s'\n", sddl)); return NULL; } (*sddlp) += 2; if (sid_codes[i].sid == NULL) { return dom_sid_add_rid(mem_ctx, domain_sid, sid_codes[i].rid); } return dom_sid_parse_talloc(mem_ctx, sid_codes[i].sid); }
/* test the SidToGid interface */ static bool test_sidtogid(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct unixinfo_SidToGid r; struct dom_sid *sid; uint64_t gid; sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1234-5432"); r.in.sid = *sid; r.out.gid = &gid; status = dcerpc_unixinfo_SidToGid(p, tctx, &r); if (NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, status)) { } else torture_assert_ntstatus_ok(tctx, status, "SidToGid failed"); return true; }
static bool nbt_netlogon_packet_check(struct torture_context *tctx, struct nbt_netlogon_packet *r) { torture_assert_int_equal(tctx, r->command, LOGON_SAM_LOGON_REQUEST, "command"); torture_assert_int_equal(tctx, r->req.logon.request_count, 0, "request_count"); torture_assert_str_equal(tctx, r->req.logon.computer_name, "LENNY", "computer_name"); torture_assert_str_equal(tctx, r->req.logon.user_name, "LENNY$", "user_name"); torture_assert_str_equal(tctx, r->req.logon.mailslot_name, "\\MAILSLOT\\NET\\GETDC52EAA8C0", "mailslot_name"); torture_assert_int_equal(tctx, r->req.logon.acct_control, 0x00000080, "acct_control"); torture_assert_int_equal(tctx, r->req.logon.sid_size, 24, "sid_size"); torture_assert_int_equal(tctx, r->req.logon._pad.length, 2, "_pad.length"); torture_assert_sid_equal(tctx, &r->req.logon.sid, dom_sid_parse_talloc(tctx, "S-1-5-21-4284042908-2889457889-3672286761"), "sid"); torture_assert_int_equal(tctx, r->req.logon.nt_version, NETLOGON_NT_VERSION_1, "nt_version"); torture_assert_int_equal(tctx, r->req.logon.lmnt_token, 0xffff, "lmnt_token"); torture_assert_int_equal(tctx, r->req.logon.lm20_token, 0xffff, "lm20_token"); return true; }
static PyObject *py_admin_session(PyObject *module, PyObject *args) { PyObject *py_lp_ctx; PyObject *py_sid; struct loadparm_context *lp_ctx = NULL; struct auth_session_info *session; struct dom_sid *domain_sid = NULL; if (!PyArg_ParseTuple(args, "OO", &py_lp_ctx, &py_sid)) return NULL; lp_ctx = lp_from_py_object(py_lp_ctx); if (lp_ctx == NULL) return NULL; domain_sid = dom_sid_parse_talloc(NULL, PyString_AsString(py_sid)); session = admin_session(NULL, lp_ctx, domain_sid); return PyAuthSession_FromSession(session); }
NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call) { struct composite_context *ctx; struct wbsrv_service *service = s3call->wbconn->listen_socket->service; struct dom_sid *sid; DEBUG(5, ("wbsrv_samba3_sid2gid called\n")); sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid); NT_STATUS_HAVE_NO_MEMORY(sid); ctx = wb_sid2gid_send(s3call, service, sid); NT_STATUS_HAVE_NO_MEMORY(ctx); ctx->async.fn = sid2gid_recv; ctx->async.private_data = s3call; s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC; return NT_STATUS_OK; }
/* test one SDDL example */ static bool test_sddl(struct torture_context *tctx, const void *test_data) { struct security_descriptor *sd, *sd2; struct dom_sid *domain; const char *sddl = (const char *)test_data; const char *sddl2; TALLOC_CTX *mem_ctx = tctx; domain = dom_sid_parse_talloc(mem_ctx, "S-1-2-3-4"); sd = sddl_decode(mem_ctx, sddl, domain); torture_assert(tctx, sd != NULL, talloc_asprintf(tctx, "Failed to decode '%s'\n", sddl)); sddl2 = sddl_encode(mem_ctx, sd, domain); torture_assert(tctx, sddl2 != NULL, talloc_asprintf(tctx, "Failed to re-encode '%s'\n", sddl)); sd2 = sddl_decode(mem_ctx, sddl2, domain); torture_assert(tctx, sd2 != NULL, talloc_asprintf(tctx, "Failed to decode2 '%s'\n", sddl2)); torture_assert(tctx, security_descriptor_equal(sd, sd2), talloc_asprintf(tctx, "Failed equality test for '%s'\n", sddl)); #if 0 /* flags don't have a canonical order ... */ if (strcmp(sddl, sddl2) != 0) { printf("Failed sddl equality test\norig: %s\n new: %s\n", sddl, sddl2); } #endif if (DEBUGLVL(2)) { NDR_PRINT_DEBUG(security_descriptor, sd); } talloc_free(sd); talloc_free(domain); return true; }
static bool forest_trust_info_check_out(struct torture_context *tctx, struct ForestTrustInfo *r) { torture_assert_int_equal(tctx, r->version, 1, "version"); torture_assert_int_equal(tctx, r->count, 2, "count"); torture_assert_int_equal(tctx, r->records[0].record_size, 0x00000018, "record size"); torture_assert_int_equal(tctx, r->records[0].record.flags, 0, "record flags"); torture_assert_u64_equal(tctx, r->records[0].record.timestamp, 0x9BD5AF0001CACA3EULL, "record timestamp"); torture_assert_int_equal(tctx, r->records[0].record.type, FOREST_TRUST_TOP_LEVEL_NAME, "record type"); torture_assert_int_equal(tctx, r->records[0].record.data.name.size, 7, "record name size"); torture_assert_str_equal(tctx, r->records[0].record.data.name.string, "f2.test", "record name string"); torture_assert_int_equal(tctx, r->records[1].record_size, 0x0000003a, "record size"); torture_assert_int_equal(tctx, r->records[1].record.flags, 0, "record flags"); torture_assert_u64_equal(tctx, r->records[1].record.timestamp, 0x9BD5AF0001CACA3EULL, "record timestamp"); torture_assert_int_equal(tctx, r->records[1].record.type, FOREST_TRUST_DOMAIN_INFO, "record type"); torture_assert_int_equal(tctx, r->records[1].record.data.info.sid_size, 0x00000018, "record info sid_size"); torture_assert_sid_equal(tctx, &r->records[1].record.data.info.sid, dom_sid_parse_talloc(tctx, "S-1-5-21-677661288-1956808876-2402106903"), "record info sid"); torture_assert_int_equal(tctx, r->records[1].record.data.info.dns_name.size, 7, "record name size"); torture_assert_str_equal(tctx, r->records[1].record.data.info.dns_name.string, "f2.test", "record info dns_name string"); torture_assert_int_equal(tctx, r->records[1].record.data.info.netbios_name.size, 2, "record info netbios_name size"); torture_assert_str_equal(tctx, r->records[1].record.data.info.netbios_name.string, "F2", "record info netbios_name string"); return true; }
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_policy_state **_state) { struct lsa_policy_state *state; struct ldb_result *dom_res; const char *dom_attrs[] = { "objectSid", "objectGUID", "nTMixedDomain", "fSMORoleOwner", NULL }; char *p; int ret; state = talloc(mem_ctx, struct lsa_policy_state); if (!state) { return NT_STATUS_NO_MEMORY; } /* make sure the sam database is accessible */ state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); if (state->sam_ldb == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } /* work out the domain_dn - useful for so many calls its worth fetching here */ state->domain_dn = ldb_get_default_basedn(state->sam_ldb); if (!state->domain_dn) { return NT_STATUS_NO_MEMORY; } /* work out the forest root_dn - useful for so many calls its worth fetching here */ state->forest_dn = samdb_root_dn(state->sam_ldb); if (!state->forest_dn) { return NT_STATUS_NO_MEMORY; } ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res, state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL); if (ret != LDB_SUCCESS) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } if (dom_res->count != 1) { return NT_STATUS_NO_SUCH_DOMAIN; } state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid"); if (!state->domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0); talloc_free(dom_res); state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn); if (!state->domain_dns) { return NT_STATUS_NO_SUCH_DOMAIN; } p = strchr(state->domain_dns, '/'); if (p) { *p = '\0'; } state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn); if (!state->forest_dns) { return NT_STATUS_NO_SUCH_DOMAIN; } p = strchr(state->forest_dns, '/'); if (p) { *p = '\0'; } /* work out the builtin_dn - useful for so many calls its worth fetching here */ state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)"); if (!state->builtin_dn) { return NT_STATUS_NO_SUCH_DOMAIN; } /* work out the system_dn - useful for so many calls its worth fetching here */ state->system_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(&(objectClass=container)(cn=System))"); if (!state->system_dn) { return NT_STATUS_NO_SUCH_DOMAIN; } state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN); if (!state->builtin_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY); if (!state->nt_authority_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN); if (!state->creator_owner_domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN); if (!state->world_domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } *_state = state; return NT_STATUS_OK; }
NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name, struct auth_user_info_dc **_user_info_dc) { struct auth_user_info_dc *user_info_dc; struct auth_user_info *info; user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); NT_STATUS_HAVE_NO_MEMORY(user_info_dc); /* This returns a pointer to a struct dom_sid, which is the * same as a 1 element list of struct dom_sid */ user_info_dc->num_sids = 1; user_info_dc->sids = dom_sid_parse_talloc(user_info_dc, SID_NT_SYSTEM); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->sids); /* annoying, but the Anonymous really does have a session key, and it is all zeros! */ user_info_dc->user_session_key = data_blob_talloc(user_info_dc, NULL, 16); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->user_session_key.data); user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, NULL, 16); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->lm_session_key.data); data_blob_clear(&user_info_dc->user_session_key); data_blob_clear(&user_info_dc->lm_session_key); user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info); info->account_name = talloc_strdup(info, "SYSTEM"); NT_STATUS_HAVE_NO_MEMORY(info->account_name); info->domain_name = talloc_strdup(info, "NT AUTHORITY"); NT_STATUS_HAVE_NO_MEMORY(info->domain_name); info->full_name = talloc_strdup(info, "System"); NT_STATUS_HAVE_NO_MEMORY(info->full_name); info->logon_script = talloc_strdup(info, ""); NT_STATUS_HAVE_NO_MEMORY(info->logon_script); info->profile_path = talloc_strdup(info, ""); NT_STATUS_HAVE_NO_MEMORY(info->profile_path); info->home_directory = talloc_strdup(info, ""); NT_STATUS_HAVE_NO_MEMORY(info->home_directory); info->home_drive = talloc_strdup(info, ""); NT_STATUS_HAVE_NO_MEMORY(info->home_drive); info->logon_server = talloc_strdup(info, netbios_name); NT_STATUS_HAVE_NO_MEMORY(info->logon_server); info->last_logon = 0; info->last_logoff = 0; info->acct_expiry = 0; info->last_password_change = 0; info->allow_password_change = 0; info->force_password_change = 0; info->logon_count = 0; info->bad_password_count = 0; info->acct_flags = ACB_NORMAL; info->authenticated = true; *_user_info_dc = user_info_dc; return NT_STATUS_OK; }
/* lookup a SID for 1 name */ static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx, struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, const char *name, const char **authority_name, struct dom_sid **sid, enum lsa_SidType *rtype, uint32_t *rid) { int ret, i; uint32_t atype; struct ldb_message **res; const char * const attrs[] = { "objectSid", "sAMAccountType", NULL}; const char *p; const char *domain; const char *username; struct ldb_dn *domain_dn; struct dom_sid *domain_sid; NTSTATUS status; p = strchr_m(name, '\\'); if (p != NULL) { domain = talloc_strndup(mem_ctx, name, p-name); if (!domain) { return NT_STATUS_NO_MEMORY; } username = p + 1; } else if (strchr_m(name, '@')) { status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status))); return status; } } else { domain = NULL; username = name; } if (!domain) { /* Look up table of well known names */ status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype); if (NT_STATUS_IS_OK(status)) { dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } if (username == NULL) { *authority_name = NAME_BUILTIN; *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { *authority_name = NAME_NT_AUTHORITY; *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); *rtype = SID_NAME_DOMAIN; dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } if (strcasecmp_m(username, NAME_BUILTIN) == 0) { *authority_name = NAME_BUILTIN; *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN); *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, state->domain_dns) == 0) { *authority_name = state->domain_name; *sid = state->domain_sid; *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } if (strcasecmp_m(username, state->domain_name) == 0) { *authority_name = state->domain_name; *sid = state->domain_sid; *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } /* Perhaps this is a well known user? */ name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } /* Perhaps this is a BUILTIN user? */ name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } /* OK, I give up - perhaps we need to assume the user is in our domain? */ name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username); if (!name) { return NT_STATUS_NO_MEMORY; } status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid); if (NT_STATUS_IS_OK(status)) { return status; } return STATUS_SOME_UNMAPPED; } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) { if (!*username) { *authority_name = NAME_NT_AUTHORITY; *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY); *rtype = SID_NAME_DOMAIN; dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } /* Look up table of well known names */ status = lookup_well_known_names(mem_ctx, domain, username, authority_name, sid, rtype); if (NT_STATUS_IS_OK(status)) { dom_sid_split_rid(NULL, *sid, NULL, rid); } return status; } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) { *authority_name = NAME_BUILTIN; domain_dn = state->builtin_dn; } else if (strcasecmp_m(domain, state->domain_dns) == 0) { *authority_name = state->domain_name; domain_dn = state->domain_dn; } else if (strcasecmp_m(domain, state->domain_name) == 0) { *authority_name = state->domain_name; domain_dn = state->domain_dn; } else { /* Not local, need to ask winbind in future */ return STATUS_SOME_UNMAPPED; } ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs); if (ret == 1) { domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid"); if (domain_sid == NULL) { return NT_STATUS_INVALID_SID; } } else { return NT_STATUS_INVALID_SID; } if (!*username) { *sid = domain_sid; *rtype = SID_NAME_DOMAIN; *rid = 0xFFFFFFFF; return NT_STATUS_OK; } ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, "(&(sAMAccountName=%s)(objectSid=*))", ldb_binary_encode_string(mem_ctx, username)); if (ret == -1) { return NT_STATUS_INVALID_SID; } for (i=0; i < ret; i++) { *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid"); if (*sid == NULL) { return NT_STATUS_INVALID_SID; } /* Check that this is in the domain */ if (!dom_sid_in_domain(domain_sid, *sid)) { continue; } atype = samdb_result_uint(res[i], "sAMAccountType", 0); *rtype = ds_atype_map(atype); if (*rtype == SID_NAME_UNKNOWN) { return STATUS_SOME_UNMAPPED; } dom_sid_split_rid(NULL, *sid, NULL, rid); return NT_STATUS_OK; } /* need to check for an allocated sid */ return NT_STATUS_INVALID_SID; }
/* setup config options for a posix share */ static void pvfs_setup_options(struct pvfs_state *pvfs) { struct share_config *scfg = pvfs->ntvfs->ctx->config; const char *eadb; bool def_perm_override = false; if (share_bool_option(scfg, SHARE_MAP_HIDDEN, SHARE_MAP_HIDDEN_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_HIDDEN; if (share_bool_option(scfg, SHARE_MAP_ARCHIVE, SHARE_MAP_ARCHIVE_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE; if (share_bool_option(scfg, SHARE_MAP_SYSTEM, SHARE_MAP_SYSTEM_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_SYSTEM; if (share_bool_option(scfg, SHARE_READONLY, SHARE_READONLY_DEFAULT)) pvfs->flags |= PVFS_FLAG_READONLY; if (share_bool_option(scfg, SHARE_STRICT_SYNC, SHARE_STRICT_SYNC_DEFAULT)) pvfs->flags |= PVFS_FLAG_STRICT_SYNC; if (share_bool_option(scfg, SHARE_STRICT_LOCKING, SHARE_STRICT_LOCKING_DEFAULT)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING; if (share_bool_option(scfg, SHARE_CI_FILESYSTEM, SHARE_CI_FILESYSTEM_DEFAULT)) pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM; if (share_bool_option(scfg, PVFS_FAKE_OPLOCKS, PVFS_FAKE_OPLOCKS_DEFAULT)) pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS; if (share_bool_option(scfg, PVFS_AIO, false)) pvfs->flags |= PVFS_FLAG_LINUX_AIO; #if defined(O_DIRECTORY) && defined(O_NOFOLLOW) /* set PVFS_PERM_OVERRIDE by default only if the system * supports the necessary capabilities to make it secure */ def_perm_override = true; #endif if (share_bool_option(scfg, PVFS_PERM_OVERRIDE, def_perm_override)) pvfs->flags |= PVFS_FLAG_PERM_OVERRIDE; /* file perm options */ pvfs->options.create_mask = share_int_option(scfg, SHARE_CREATE_MASK, SHARE_CREATE_MASK_DEFAULT); pvfs->options.dir_mask = share_int_option(scfg, SHARE_DIR_MASK, SHARE_DIR_MASK_DEFAULT); pvfs->options.force_dir_mode = share_int_option(scfg, SHARE_FORCE_DIR_MODE, SHARE_FORCE_DIR_MODE_DEFAULT); pvfs->options.force_create_mode = share_int_option(scfg, SHARE_FORCE_CREATE_MODE, SHARE_FORCE_CREATE_MODE_DEFAULT); /* this must be a power of 2 */ pvfs->alloc_size_rounding = share_int_option(scfg, PVFS_ALLOCATION_ROUNDING, PVFS_ALLOCATION_ROUNDING_DEFAULT); pvfs->search.inactivity_time = share_int_option(scfg, PVFS_SEARCH_INACTIVITY, PVFS_SEARCH_INACTIVITY_DEFAULT); #if HAVE_XATTR_SUPPORT if (share_bool_option(scfg, PVFS_XATTR, PVFS_XATTR_DEFAULT)) pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; #endif pvfs->sharing_violation_delay = share_int_option(scfg, PVFS_SHARE_DELAY, PVFS_SHARE_DELAY_DEFAULT); pvfs->oplock_break_timeout = share_int_option(scfg, PVFS_OPLOCK_TIMEOUT, PVFS_OPLOCK_TIMEOUT_DEFAULT); pvfs->writetime_delay = share_int_option(scfg, PVFS_WRITETIME_DELAY, PVFS_WRITETIME_DELAY_DEFAULT); pvfs->share_name = talloc_strdup(pvfs, scfg->name); pvfs->fs_attribs = FS_ATTR_CASE_SENSITIVE_SEARCH | FS_ATTR_CASE_PRESERVED_NAMES | FS_ATTR_UNICODE_ON_DISK | FS_ATTR_SPARSE_FILES; /* allow xattrs to be stored in a external tdb */ eadb = share_string_option(scfg, PVFS_EADB, NULL); if (eadb != NULL) { pvfs->ea_db = tdb_wrap_open(pvfs, eadb, 50000, TDB_DEFAULT, O_RDWR|O_CREAT, 0600, pvfs->ntvfs->ctx->lp_ctx); if (pvfs->ea_db != NULL) { pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; } else { DEBUG(0,("Failed to open eadb '%s' - %s\n", eadb, strerror(errno))); pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE; } } if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS; } if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS; } pvfs->sid_cache.creator_owner = dom_sid_parse_talloc(pvfs, SID_CREATOR_OWNER); pvfs->sid_cache.creator_group = dom_sid_parse_talloc(pvfs, SID_CREATOR_GROUP); /* check if the system really supports xattrs */ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs_xattr_probe(pvfs); } /* enable an ACL backend */ pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr")); }
_PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, /* Optional, if you don't want privilages */ struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */ struct auth_user_info_dc *user_info_dc, uint32_t session_info_flags, struct auth_session_info **_session_info) { struct auth_session_info *session_info; NTSTATUS nt_status; unsigned int i, num_sids = 0; const char *filter; struct dom_sid *sids = NULL; const struct dom_sid *anonymous_sid, *system_sid; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); session_info = talloc_zero(tmp_ctx, struct auth_session_info); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info, tmp_ctx); session_info->info = talloc_reference(session_info, user_info_dc->info); session_info->torture = talloc_zero(session_info, struct auth_user_info_torture); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->torture, tmp_ctx); session_info->torture->num_dc_sids = user_info_dc->num_sids; session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->torture->dc_sids, tmp_ctx); /* unless set otherwise, the session key is the user session * key from the auth subsystem */ session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length); if (!session_info->session_key.data && session_info->session_key.length) { NT_STATUS_HAVE_NO_MEMORY_AND_FREE(session_info->session_key.data, tmp_ctx); } anonymous_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_ANONYMOUS); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(anonymous_sid, tmp_ctx); system_sid = dom_sid_parse_talloc(tmp_ctx, SID_NT_SYSTEM); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(system_sid, tmp_ctx); sids = talloc_array(tmp_ctx, struct dom_sid, user_info_dc->num_sids); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sids, tmp_ctx); if (!sids) { talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } num_sids = user_info_dc->num_sids; for (i=0; i < user_info_dc->num_sids; i++) { sids[i] = user_info_dc->sids[i]; } if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(anonymous_sid, &user_info_dc->sids[PRIMARY_USER_SID_INDEX])) { /* Don't expand nested groups of system, anonymous etc*/ } else if (user_info_dc->num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(system_sid, &user_info_dc->sids[PRIMARY_USER_SID_INDEX])) { /* Don't expand nested groups of system, anonymous etc*/ } else if (sam_ctx) { filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", GROUP_TYPE_BUILTIN_LOCAL_GROUP); /* Search for each group in the token */ for (i = 0; i < user_info_dc->num_sids; i++) { char *sid_string; const char *sid_dn; DATA_BLOB sid_blob; sid_string = dom_sid_string(tmp_ctx, &user_info_dc->sids[i]); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_string, user_info_dc); sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string); talloc_free(sid_string); NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_dn, user_info_dc); sid_blob = data_blob_string_const(sid_dn); /* This function takes in memberOf values and expands * them, as long as they meet the filter - so only * builtin groups * * We already have the SID in the token, so set * 'only childs' flag to true */ nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter, tmp_ctx, &sids, &num_sids); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(tmp_ctx); return nt_status; } } } nt_status = security_token_create(session_info, lp_ctx, num_sids, sids, session_info_flags, &session_info->security_token); NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, tmp_ctx); session_info->credentials = NULL; talloc_steal(mem_ctx, session_info); *_session_info = session_info; talloc_free(tmp_ctx); return NT_STATUS_OK; }
/** * test renaming after reauth. * compare security descriptors before and after rename/reauth */ bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char dname[256]; char fname[256]; char fname2[256]; struct smb2_handle _dh1; struct smb2_handle *dh1 = NULL; struct smb2_handle _h1; struct smb2_handle *h1 = NULL; struct smb2_create io1; bool ret = true; bool ok; union smb_fileinfo qfinfo; union smb_setfileinfo sfinfo; struct cli_credentials *anon_creds = NULL; uint32_t secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_PROTECTED_DACL | SECINFO_UNPROTECTED_DACL; struct security_descriptor *f_sd1; struct security_descriptor *d_sd1 = NULL; struct security_ace ace; struct dom_sid *extra_sid; /* Add some random component to the file name. */ snprintf(dname, 256, "session_reauth5_%s.d", generate_random_str(tctx, 8)); snprintf(fname, 256, "%s\\file.dat", dname); ok = smb2_util_setup_dir(tctx, tree, dname); CHECK_VAL(ok, true); status = torture_smb2_testdir(tree, dname, &_dh1); CHECK_STATUS(status, NT_STATUS_OK); dh1 = &_dh1; smb2_oplock_create_share(&io1, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); status = smb2_create(tree, 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")); /* get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); f_sd1 = qfinfo.query_secdesc.out.sd; /* re-authenticate as anonymous */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* try to rename the file: fails */ snprintf(fname2, 256, "%s\\file2.dat", dname); smb2_util_unlink(tree, fname2); ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* re-authenticate as original user again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* give full access on the file to anonymous */ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS); ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_RIGHTS_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(f_sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _h1; sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags; sfinfo.set_secdesc.in.sd = f_sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-authenticate as anonymous - again */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* try to rename the file: fails */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* give full access on the parent dir to anonymous */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _dh1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); d_sd1 = qfinfo.query_secdesc.out.sd; ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_RIGHTS_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(d_sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _dh1; sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags; sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL; sfinfo.set_secdesc.in.sd = d_sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _dh1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); smb2_util_close(tree, _dh1); dh1 = NULL; /* try to rename the file: still fails */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); /* re-authenticate as original user - again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* rename the file - for verification that it works */ ZERO_STRUCT(sfinfo); sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION; sfinfo.rename_information.in.file.handle = _h1; sfinfo.rename_information.in.overwrite = true; sfinfo.rename_information.in.new_name = fname2; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* closs the file, check it is gone and reopen under the new name */ smb2_util_close(tree, _h1); ZERO_STRUCT(io1); smb2_generic_create_share(&io1, NULL /* lease */, false /* dir */, fname, NTCREATEX_DISP_OPEN, smb2_util_share_access(""), smb2_util_oplock_level("b"), 0 /* leasekey */, 0 /* leasestate */); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); ZERO_STRUCT(io1); smb2_generic_create_share(&io1, NULL /* lease */, false /* dir */, fname2, NTCREATEX_DISP_OPEN, smb2_util_share_access(""), smb2_util_oplock_level("b"), 0 /* leasekey */, 0 /* leasestate */); status = smb2_create(tree, mem_ctx, &io1); CHECK_STATUS(status, NT_STATUS_OK); _h1 = io1.out.file.handle; h1 = &_h1; CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b")); /* try to access the file via the old handle */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); done: if (dh1 != NULL) { smb2_util_close(tree, *dh1); } if (h1 != NULL) { smb2_util_close(tree, *h1); } smb2_deltree(tree, dname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/** * test setting security descriptor after reauth. */ bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; TALLOC_CTX *mem_ctx = talloc_new(tctx); char fname[256]; struct smb2_handle _h1; struct smb2_handle *h1 = NULL; struct smb2_create io1; bool ret = true; union smb_fileinfo qfinfo; union smb_setfileinfo sfinfo; struct cli_credentials *anon_creds = NULL; uint32_t secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_PROTECTED_DACL | SECINFO_UNPROTECTED_DACL; struct security_descriptor *sd1; struct security_ace ace; struct dom_sid *extra_sid; /* Add some random component to the file name. */ snprintf(fname, 256, "session_reauth4_%s.dat", generate_random_str(tctx, 8)); smb2_util_unlink(tree, fname); smb2_oplock_create_share(&io1, fname, smb2_util_share_access(""), smb2_util_oplock_level("b")); status = smb2_create(tree, 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")); /* get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); sd1 = qfinfo.query_secdesc.out.sd; /* re-authenticate as anonymous */ anon_creds = cli_credentials_init_anon(mem_ctx); torture_assert(tctx, (anon_creds != NULL), "talloc error"); status = smb2_session_setup_spnego(tree->session, anon_creds, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* give full access on the file to anonymous */ extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS); ZERO_STRUCT(ace); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL; ace.trustee = *extra_sid; status = security_descriptor_dacl_add(sd1, &ace); CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(sfinfo); sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; sfinfo.set_secdesc.in.file.handle = _h1; sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL; sfinfo.set_secdesc.in.sd = sd1; status = smb2_setinfo_file(tree, &sfinfo); CHECK_STATUS(status, NT_STATUS_OK); /* re-authenticate as original user again */ status = smb2_session_setup_spnego(tree->session, cmdline_credentials, 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); /* re-get the security descriptor */ ZERO_STRUCT(qfinfo); qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC; qfinfo.query_secdesc.in.file.handle = _h1; qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags; status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); CHECK_STATUS(status, NT_STATUS_OK); ret = true; done: if (h1 != NULL) { smb2_util_close(tree, *h1); } smb2_util_unlink(tree, fname); talloc_free(tree); talloc_free(mem_ctx); return ret; }
/* try creating with acls */ static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir) { bool ret = true; struct smb2_create io; NTSTATUS status; struct security_ace ace; struct security_descriptor *sd; struct dom_sid *test_sid; union smb_fileinfo q = {}; uint32_t attrib = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0); NTSTATUS (*delete_func)(struct smb2_tree *, const char *) = test_dir ? smb2_util_rmdir : smb2_util_unlink; smb2_deltree(tree, FNAME); ZERO_STRUCT(io); io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; io.in.create_disposition = NTCREATEX_DISP_CREATE; io.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE | NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 | (test_dir ? NTCREATEX_OPTIONS_DIRECTORY : (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)); io.in.fname = FNAME; torture_comment(tctx, "basic create\n"); status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = io.out.file.handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); sd = q.query_secdesc.out.sd; status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); status = delete_func(tree, FNAME); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "adding a new ACE\n"); test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS); ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED; ace.flags = 0; ace.access_mask = SEC_STD_ALL; ace.trustee = *test_sid; status = security_descriptor_dacl_add(sd, &ace); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "creating a file with an initial ACL\n"); io.in.sec_desc = sd; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); status = delete_func(tree, FNAME); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "creating with attributes\n"); io.in.sec_desc = NULL; io.in.file_attributes = attrib; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); status = delete_func(tree, FNAME); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "creating with attributes and ACL\n"); io.in.sec_desc = sd; io.in.file_attributes = attrib; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); status = delete_func(tree, FNAME); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "creating with attributes, ACL and owner\n"); sd = security_descriptor_dacl_create(tctx, 0, SID_WORLD, SID_BUILTIN_USERS, SID_WORLD, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_READ | SEC_STD_ALL, 0, NULL); io.in.sec_desc = sd; io.in.file_attributes = attrib; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd)); FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib)); done: status = smb2_util_close(tree, io.out.file.handle); CHECK_STATUS(status, NT_STATUS_OK); status = delete_func(tree, FNAME); CHECK_STATUS(status, NT_STATUS_OK); return ret; }
/* do some samr ops using the schannel connection */ static bool test_samr_ops(struct torture_context *tctx, struct dcerpc_binding_handle *b) { struct samr_GetDomPwInfo r; struct samr_PwInfo info; struct samr_Connect connect_r; struct samr_OpenDomain opendom; int i; struct lsa_String name; struct policy_handle handle; struct policy_handle domain_handle; name.string = lpcfg_workgroup(tctx->lp_ctx); r.in.domain_name = &name; r.out.info = &info; connect_r.in.system_name = 0; connect_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; connect_r.out.connect_handle = &handle; torture_comment(tctx, "Testing Connect and OpenDomain on BUILTIN\n"); torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &connect_r), "Connect failed"); if (!NT_STATUS_IS_OK(connect_r.out.result)) { if (NT_STATUS_EQUAL(connect_r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "Connect failed (expected, schannel mapped to anonymous): %s\n", nt_errstr(connect_r.out.result)); } else { torture_comment(tctx, "Connect failed - %s\n", nt_errstr(connect_r.out.result)); return false; } } else { opendom.in.connect_handle = &handle; opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; opendom.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); opendom.out.domain_handle = &domain_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &opendom), "OpenDomain failed"); if (!NT_STATUS_IS_OK(opendom.out.result)) { torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(opendom.out.result)); return false; } } torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string); /* do several ops to test credential chaining */ for (i=0;i<5;i++) { torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r), "GetDomPwInfo failed"); if (!NT_STATUS_IS_OK(r.out.result)) { if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) { torture_comment(tctx, "GetDomPwInfo op %d failed - %s\n", i, nt_errstr(r.out.result)); return false; } } } return true; }
/* setup config options for a posix share */ static void pvfs_setup_options(struct pvfs_state *pvfs) { struct share_config *scfg = pvfs->ntvfs->ctx->config; const char *eadb; if (share_bool_option(scfg, SHARE_MAP_HIDDEN, SHARE_MAP_HIDDEN_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_HIDDEN; if (share_bool_option(scfg, SHARE_MAP_ARCHIVE, SHARE_MAP_ARCHIVE_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_ARCHIVE; if (share_bool_option(scfg, SHARE_MAP_SYSTEM, SHARE_MAP_SYSTEM_DEFAULT)) pvfs->flags |= PVFS_FLAG_MAP_SYSTEM; if (share_bool_option(scfg, SHARE_READONLY, SHARE_READONLY_DEFAULT)) pvfs->flags |= PVFS_FLAG_READONLY; if (share_bool_option(scfg, SHARE_STRICT_SYNC, SHARE_STRICT_SYNC_DEFAULT)) pvfs->flags |= PVFS_FLAG_STRICT_SYNC; if (share_bool_option(scfg, SHARE_STRICT_LOCKING, SHARE_STRICT_LOCKING_DEFAULT)) pvfs->flags |= PVFS_FLAG_STRICT_LOCKING; if (share_bool_option(scfg, SHARE_CI_FILESYSTEM, SHARE_CI_FILESYSTEM_DEFAULT)) pvfs->flags |= PVFS_FLAG_CI_FILESYSTEM; if (share_bool_option(scfg, PVFS_FAKE_OPLOCKS, PVFS_FAKE_OPLOCKS_DEFAULT)) { pvfs->flags |= PVFS_FLAG_FAKE_OPLOCKS; } /* this must be a power of 2 */ pvfs->alloc_size_rounding = share_int_option(scfg, PVFS_ALLOCATION_ROUNDING, PVFS_ALLOCATION_ROUNDING_DEFAULT); pvfs->search.inactivity_time = share_int_option(scfg, PVFS_SEARCH_INACTIVITY, PVFS_SEARCH_INACTIVITY_DEFAULT); #if HAVE_XATTR_SUPPORT if (share_bool_option(scfg, PVFS_XATTR, PVFS_XATTR_DEFAULT)) pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; #endif pvfs->sharing_violation_delay = share_int_option(scfg, PVFS_SHARE_DELAY, PVFS_SHARE_DELAY_DEFAULT); pvfs->share_name = talloc_strdup(pvfs, scfg->name); pvfs->fs_attribs = FS_ATTR_CASE_SENSITIVE_SEARCH | FS_ATTR_CASE_PRESERVED_NAMES | FS_ATTR_UNICODE_ON_DISK | FS_ATTR_SPARSE_FILES; /* allow xattrs to be stored in a external tdb */ eadb = share_string_option(scfg, PVFS_EADB, NULL); if (eadb != NULL) { pvfs->ea_db = tdb_wrap_open(pvfs, eadb, 50000, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); if (pvfs->ea_db != NULL) { pvfs->flags |= PVFS_FLAG_XATTR_ENABLE; } else { DEBUG(0,("Failed to open eadb '%s' - %s\n", eadb, strerror(errno))); pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE; } } if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs->fs_attribs |= FS_ATTR_NAMED_STREAMS; } if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs->fs_attribs |= FS_ATTR_PERSISTANT_ACLS; } pvfs->sid_cache.creator_owner = dom_sid_parse_talloc(pvfs, SID_CREATOR_OWNER); pvfs->sid_cache.creator_group = dom_sid_parse_talloc(pvfs, SID_CREATOR_GROUP); /* check if the system really supports xattrs */ if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { pvfs_xattr_probe(pvfs); } /* enable an ACL backend */ pvfs->acl_ops = pvfs_acl_backend_byname(share_string_option(scfg, PVFS_ACL, "xattr")); }
static bool spoolss_access_setup_membership(struct torture_context *tctx, struct dcerpc_pipe *p, uint32_t num_members, uint32_t *members, struct dom_sid *user_sid) { struct dcerpc_binding_handle *b = p->binding_handle; struct policy_handle connect_handle, domain_handle; int i; torture_comment(tctx, "Setting up BUILTIN membership for %s\n", dom_sid_string(tctx, user_sid)); for (i=0; i < num_members; i++) { torture_comment(tctx, "adding user to S-1-5-32-%d\n", members[i]); } { struct samr_Connect2 r; r.in.system_name = ""; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &connect_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r), "samr_Connect2 failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_Connect2 failed"); } { struct samr_OpenDomain r; r.in.connect_handle = &connect_handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32"); r.out.domain_handle = &domain_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r), "samr_OpenDomain failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_OpenDomain failed"); } for (i=0; i < num_members; i++) { struct policy_handle alias_handle; { struct samr_OpenAlias r; r.in.domain_handle = &domain_handle; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.in.rid = members[i]; r.out.alias_handle = &alias_handle; torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r), "samr_OpenAlias failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_OpenAlias failed"); } { struct samr_AddAliasMember r; r.in.alias_handle = &alias_handle; r.in.sid = user_sid; torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r), "samr_AddAliasMember failed"); torture_assert_ntstatus_ok(tctx, r.out.result, "samr_AddAliasMember failed"); } test_samr_handle_Close(b, tctx, &alias_handle); } test_samr_handle_Close(b, tctx, &domain_handle); test_samr_handle_Close(b, tctx, &connect_handle); return true; }
static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module, const struct ldb_message *msg, struct ldb_message **ret_msg) { struct ldb_message *msg2; const char *rdn_name; struct dom_sid *dom_sid; struct dom_sid *sid; const char *dom_attrs[] = { "name", NULL }; struct ldb_message **dom_msgs; const char *errstr; int ret; TALLOC_CTX *mem_ctx = talloc_new(msg); if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; } /* build the new msg */ msg2 = ldb_msg_copy(mem_ctx, msg); if (!msg2) { ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincpal_object: ldb_msg_copy failed!\n"); talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } ret = samdb_copy_template(module->ldb, msg2, "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))", &errstr); if (ret != 0) { ldb_asprintf_errstring(module->ldb, "samldb_fill_foreignSecurityPrincipal_object: " "Error copying template: %s", errstr); talloc_free(mem_ctx); return ret; } rdn_name = ldb_dn_get_rdn_name(msg2->dn); if (strcasecmp(rdn_name, "cn") != 0) { ldb_asprintf_errstring(module->ldb, "Bad RDN (%s=) for ForeignSecurityPrincipal, should be CN=!", rdn_name); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } /* Slightly different for the foreign sids. We don't want * domain SIDs ending up there, it would cause all sorts of * pain */ sid = dom_sid_parse_talloc(msg2, (const char *)ldb_dn_get_rdn_val(msg2->dn)->data); if (!sid) { ldb_set_errstring(module->ldb, "No valid found SID in ForeignSecurityPrincipal CN!"); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } if ( ! samldb_msg_add_sid(module, msg2, "objectSid", sid)) { talloc_free(sid); return LDB_ERR_OPERATIONS_ERROR; } dom_sid = dom_sid_dup(mem_ctx, sid); if (!dom_sid) { talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } /* get the domain component part of the provided SID */ dom_sid->num_auths--; /* find the domain DN */ ret = gendb_search(module->ldb, mem_ctx, NULL, &dom_msgs, dom_attrs, "(&(objectSid=%s)(objectclass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid)); if (ret >= 1) { /* We don't really like the idea of foreign sids that are not foreign, but it happens */ const char *name = samdb_result_string(dom_msgs[0], "name", NULL); ldb_debug(module->ldb, LDB_DEBUG_TRACE, "NOTE (strange but valid): Adding foreign SID record with SID %s, but this domian (%s) is already in the database", dom_sid_string(mem_ctx, sid), name); } else if (ret == -1) { ldb_asprintf_errstring(module->ldb, "samldb_fill_foreignSecurityPrincipal_object: error searching for a domain with this sid: %s\n", dom_sid_string(mem_ctx, dom_sid)); talloc_free(dom_msgs); return LDB_ERR_OPERATIONS_ERROR; } /* This isn't an operation on a domain we know about, so just * check for the SID, looking for duplicates via the common * code */ ret = samldb_notice_sid(module, msg2, sid); if (ret == 0) { talloc_steal(msg, msg2); *ret_msg = msg2; } return ret; }