mirror of
https://github.com/samba-team/samba.git
synced 2025-03-08 04:58:40 +03:00
Compare commits
55 Commits
e37e4d16e9
...
ff4c70e03a
Author | SHA1 | Date | |
---|---|---|---|
|
ff4c70e03a | ||
|
dc84e98ed5 | ||
|
df219ed818 | ||
|
70b3699f8b | ||
|
ff63874306 | ||
|
0dfaa08ce3 | ||
|
fca8887900 | ||
|
7e8bfe738a | ||
|
e0aab377bd | ||
|
890724f8a5 | ||
|
bf20ec9642 | ||
|
e97fbcc4b1 | ||
|
2e8009b4ca | ||
|
e52873766e | ||
|
a7d8d80179 | ||
|
04977dbb67 | ||
|
83f7129e58 | ||
|
663f03996c | ||
|
cf69a9ef14 | ||
|
671186d8f6 | ||
|
f29b06760a | ||
|
9afd9fc7da | ||
|
6262f9a66e | ||
|
719d4f98c4 | ||
|
6098724e8b | ||
|
e166299b18 | ||
|
e1767db3db | ||
|
6b7ca29ffb | ||
|
7116dca925 | ||
|
be20007cc7 | ||
|
c1b9dc9f7a | ||
|
3035f98364 | ||
|
de8babd6af | ||
|
d745a0799b | ||
|
aff7a1fde6 | ||
|
ee3a7b31e0 | ||
|
253e5f4a68 | ||
|
06cca7bf02 | ||
|
69d74563ad | ||
|
2d6d890f45 | ||
|
3a16c35ab4 | ||
|
b768c54bd5 | ||
|
a780c07c24 | ||
|
f41dc1440b | ||
|
84faa9dbb4 | ||
|
ddc88fa8b6 | ||
|
9312bdd271 | ||
|
d6ec1f42c6 | ||
|
391962e262 | ||
|
dddbab8e36 | ||
|
8f1d903524 | ||
|
d088738342 | ||
|
54124677f6 | ||
|
3b2134e231 | ||
|
8ed1b9e874 |
@ -62,7 +62,6 @@
|
||||
<arg choice="opt">--remove-uid-mapping uid,sid</arg>
|
||||
<arg choice="opt">-s sid</arg>
|
||||
<arg choice="opt">--separator</arg>
|
||||
<arg choice="opt">--sequence</arg>
|
||||
<arg choice="opt">--set-auth-user user%password</arg>
|
||||
<arg choice="opt">--set-gid-mapping gid,sid</arg>
|
||||
<arg choice="opt">--set-uid-mapping uid,sid</arg>
|
||||
@ -458,13 +457,6 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>--sequence</term>
|
||||
<listitem><para>This command has been deprecated. Please use
|
||||
the --online-status option instead.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>--set-auth-user <replaceable>username%password</replaceable></term>
|
||||
<listitem><para>Store username and password used by <citerefentry>
|
||||
|
@ -245,8 +245,9 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
|
||||
if (security_token_has_sid(token, sd->owner_sid)) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
granted |= SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
granted |= (SEC_STD_READ_CONTROL |
|
||||
SEC_STD_WRITE_DAC);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
granted |= SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -282,8 +283,8 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
|
||||
if (am_owner && !have_owner_rights_ace) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
granted |= SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
granted |= (SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
granted |= SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -436,8 +437,9 @@ static NTSTATUS se_access_check_implicit_owner(const struct security_descriptor
|
||||
if (am_owner && !have_owner_rights_ace) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
@ -596,10 +598,10 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
|
||||
access_desired |= SEC_RIGHTS_PRIV_RESTORE;
|
||||
}
|
||||
|
||||
DEBUG(10,("se_file_access_check: MAX desired = 0x%x "
|
||||
"mapped to 0x%x\n",
|
||||
orig_access_desired,
|
||||
access_desired));
|
||||
DBG_DEBUG("MAX desired = 0x%0" PRIx32 " mapped to 0x%" PRIx32
|
||||
"\n ",
|
||||
orig_access_desired,
|
||||
access_desired);
|
||||
}
|
||||
|
||||
status = se_access_check_implicit_owner(sd,
|
||||
@ -751,8 +753,9 @@ NTSTATUS sec_access_check_ds_implicit_owner(const struct security_descriptor *sd
|
||||
security_token_has_sid(token, sd->owner_sid)) {
|
||||
switch (implicit_owner_rights) {
|
||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
||||
FALL_THROUGH;
|
||||
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL);
|
||||
break;
|
||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||
break;
|
||||
|
@ -109,26 +109,23 @@ static bool check_integer_range(const struct ace_condition_token *tok)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t pull_integer(TALLOC_CTX *mem_ctx,
|
||||
uint8_t *data, size_t length,
|
||||
struct ace_condition_int *tok)
|
||||
static ssize_t pull_integer(uint8_t *data,
|
||||
size_t length,
|
||||
struct ace_condition_int *tok)
|
||||
{
|
||||
ssize_t bytes_used;
|
||||
size_t consumed;
|
||||
enum ndr_err_code ndr_err;
|
||||
DATA_BLOB v = data_blob_const(data, length);
|
||||
struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
|
||||
if (ndr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ndr_err = ndr_pull_ace_condition_int(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
|
||||
|
||||
ndr_err = ndr_pull_struct_blob_noalloc(
|
||||
data,
|
||||
length,
|
||||
tok,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_ace_condition_int,
|
||||
&consumed);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
TALLOC_FREE(ndr);
|
||||
return -1;
|
||||
}
|
||||
bytes_used = ndr->offset;
|
||||
TALLOC_FREE(ndr);
|
||||
return bytes_used;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static ssize_t push_integer(uint8_t *data, size_t available,
|
||||
@ -335,8 +332,7 @@ static ssize_t pull_composite(TALLOC_CTX *mem_ctx,
|
||||
case CONDITIONAL_ACE_TOKEN_INT16:
|
||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||
consumed = pull_integer(mem_ctx,
|
||||
el_data,
|
||||
consumed = pull_integer(el_data,
|
||||
available,
|
||||
&el->data.int64);
|
||||
ok = check_integer_range(el);
|
||||
@ -507,7 +503,7 @@ static ssize_t pull_end_padding(uint8_t *data, size_t length)
|
||||
*
|
||||
* zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
|
||||
*/
|
||||
ssize_t i;
|
||||
size_t i;
|
||||
if (length > 2) {
|
||||
return -1;
|
||||
}
|
||||
@ -592,8 +588,7 @@ struct ace_condition_script *parse_conditional_ace(TALLOC_CTX *mem_ctx,
|
||||
case CONDITIONAL_ACE_TOKEN_INT16:
|
||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||
consumed = pull_integer(program,
|
||||
tok_data,
|
||||
consumed = pull_integer(tok_data,
|
||||
available,
|
||||
&tok->data.int64);
|
||||
ok = check_integer_range(tok);
|
||||
|
@ -110,20 +110,18 @@ void display_sec_ace_flags(uint8_t flags)
|
||||
****************************************************************************/
|
||||
static void disp_sec_ace_object(struct security_ace_object *object)
|
||||
{
|
||||
char *str;
|
||||
struct GUID_txt_buf buf;
|
||||
|
||||
if (object->flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
|
||||
str = GUID_string(NULL, &object->type.type);
|
||||
if (str == NULL) return;
|
||||
printf("Object type: SEC_ACE_OBJECT_TYPE_PRESENT\n");
|
||||
printf("Object GUID: %s\n", str);
|
||||
talloc_free(str);
|
||||
printf("Object GUID: %s\n",
|
||||
GUID_buf_string(&object->type.type, &buf));
|
||||
}
|
||||
if (object->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
||||
str = GUID_string(NULL, &object->inherited_type.inherited_type);
|
||||
if (str == NULL) return;
|
||||
printf("Object type: SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT\n");
|
||||
printf("Object GUID: %s\n", str);
|
||||
talloc_free(str);
|
||||
printf("Object GUID: %s\n",
|
||||
GUID_buf_string(&object->inherited_type.inherited_type,
|
||||
&buf));
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,8 +184,9 @@ void display_sec_acl(struct security_acl *sec_acl)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
printf("\tACL\tNum ACEs:\t%u\trevision:\t%x\n",
|
||||
sec_acl->num_aces, sec_acl->revision);
|
||||
printf("\tACL\tNum ACEs:\t%" PRIu32 "\trevision:\t%x\n",
|
||||
sec_acl->num_aces,
|
||||
sec_acl->revision);
|
||||
printf("\t---\n");
|
||||
|
||||
if (sec_acl->size != 0 && sec_acl->num_aces != 0) {
|
||||
|
@ -298,7 +298,8 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd,
|
||||
|
||||
if (idx < 0) {
|
||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
} else if (idx > acl->num_aces) {
|
||||
}
|
||||
if (idx > acl->num_aces) {
|
||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
}
|
||||
|
||||
|
@ -51,52 +51,27 @@ struct security_token *security_token_initialise(TALLOC_CTX *mem_ctx,
|
||||
|
||||
struct security_token *security_token_duplicate(TALLOC_CTX *mem_ctx, const struct security_token *src)
|
||||
{
|
||||
TALLOC_CTX *frame = NULL;
|
||||
struct security_token *dst = NULL;
|
||||
DATA_BLOB blob;
|
||||
enum ndr_err_code ndr_err;
|
||||
|
||||
if (src == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame = talloc_stackframe();
|
||||
|
||||
ndr_err = ndr_push_struct_blob(
|
||||
&blob,
|
||||
frame,
|
||||
src,
|
||||
(ndr_push_flags_fn_t)ndr_push_security_token);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
DBG_ERR("Failed to duplicate security_token ndr_push_security_token failed: %s\n",
|
||||
ndr_errstr(ndr_err));
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = talloc_zero(mem_ctx, struct security_token);
|
||||
if (dst == NULL) {
|
||||
DBG_ERR("talloc failed\n");
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ndr_err = ndr_pull_struct_blob(
|
||||
&blob,
|
||||
dst,
|
||||
dst,
|
||||
(ndr_pull_flags_fn_t)ndr_pull_security_token);
|
||||
|
||||
ndr_err = ndr_deepcopy_struct(security_token, src, dst, dst);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
DBG_ERR("Failed to duplicate security_token ndr_pull_security_token "
|
||||
"failed: %s\n",
|
||||
DBG_ERR("Failed to duplicate security_token: %s\n",
|
||||
ndr_errstr(ndr_err));
|
||||
TALLOC_FREE(dst);
|
||||
TALLOC_FREE(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TALLOC_FREE(frame);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
@ -323,16 +323,17 @@ bool sid_peek_check_rid(const struct dom_sid *exp_dom_sid, const struct dom_sid
|
||||
|
||||
void sid_copy(struct dom_sid *dst, const struct dom_sid *src)
|
||||
{
|
||||
int i;
|
||||
const int8_t num_auths = MIN(15, MAX(0, src->num_auths));
|
||||
int8_t i;
|
||||
|
||||
*dst = (struct dom_sid) {
|
||||
.sid_rev_num = src->sid_rev_num,
|
||||
.num_auths = src->num_auths,
|
||||
.num_auths = num_auths,
|
||||
};
|
||||
|
||||
memcpy(&dst->id_auth[0], &src->id_auth[0], sizeof(src->id_auth));
|
||||
|
||||
for (i = 0; i < src->num_auths; i++)
|
||||
for (i = 0; i < num_auths; i++)
|
||||
dst->sub_auths[i] = src->sub_auths[i];
|
||||
}
|
||||
|
||||
|
@ -2527,6 +2527,7 @@ static char* winbind_upn_to_username(struct pwb_context *ctx,
|
||||
/* Convert the UPN to a SID */
|
||||
|
||||
wbc_status = wbcCtxLookupName(ctx->wbc_ctx, domain, name, &sid, &type);
|
||||
TALLOC_FREE(name);
|
||||
if (!WBC_ERROR_IS_OK(wbc_status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -36,24 +36,6 @@ testfail()
|
||||
fi
|
||||
}
|
||||
|
||||
knownfail()
|
||||
{
|
||||
name="$1"
|
||||
shift
|
||||
cmdline="$*"
|
||||
echo "test: $name"
|
||||
$cmdline
|
||||
status=$?
|
||||
if [ x$status = x0 ]; then
|
||||
echo "failure: $name [unexpected success]"
|
||||
status=1
|
||||
else
|
||||
echo "knownfail: $name"
|
||||
status=0
|
||||
fi
|
||||
return $status
|
||||
}
|
||||
|
||||
KRB5CCNAME_PATH="$PREFIX/test_wbinfo_krb5ccache"
|
||||
rm -f $KRB5CCNAME_PATH
|
||||
|
||||
@ -218,9 +200,6 @@ else
|
||||
failed=$(expr $failed + 1)
|
||||
fi
|
||||
|
||||
# this does not work
|
||||
knownfail "wbinfo --sequence against $TARGET" $wbinfo --sequence
|
||||
|
||||
# this is stubbed out now
|
||||
testit "wbinfo -D against $TARGET" $wbinfo -D $DOMAIN || failed=$(expr $failed + 1)
|
||||
|
||||
|
@ -605,14 +605,6 @@ static bool wbinfo_list_own_domain(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* show sequence numbers */
|
||||
static bool wbinfo_show_sequence(const char *domain)
|
||||
{
|
||||
d_printf("This command has been deprecated. Please use the "
|
||||
"--online-status option instead.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* show sequence numbers */
|
||||
static bool wbinfo_show_onlinestatus(const char *domain)
|
||||
{
|
||||
@ -2295,7 +2287,6 @@ enum {
|
||||
OPT_SET_AUTH_USER = 1000,
|
||||
OPT_GET_AUTH_USER,
|
||||
OPT_DOMAIN_NAME,
|
||||
OPT_SEQUENCE,
|
||||
OPT_GETDCNAME,
|
||||
OPT_DSGETDCNAME,
|
||||
OPT_DC_INFO,
|
||||
@ -2581,12 +2572,6 @@ int main(int argc, const char **argv, char **envp)
|
||||
.val = OPT_LIST_OWN_DOMAIN,
|
||||
.descrip = "List own domain",
|
||||
},
|
||||
{
|
||||
.longName = "sequence",
|
||||
.argInfo = POPT_ARG_NONE,
|
||||
.val = OPT_SEQUENCE,
|
||||
.descrip = "Deprecated command, see --online-status",
|
||||
},
|
||||
{
|
||||
.longName = "online-status",
|
||||
.argInfo = POPT_ARG_NONE,
|
||||
@ -3099,13 +3084,6 @@ int main(int argc, const char **argv, char **envp)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case OPT_SEQUENCE:
|
||||
if (!wbinfo_show_sequence(opt_domain_name)) {
|
||||
d_fprintf(stderr,
|
||||
"Could not show sequence numbers\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case OPT_ONLINESTATUS:
|
||||
if (!wbinfo_show_onlinestatus(opt_domain_name)) {
|
||||
d_fprintf(stderr,
|
||||
|
@ -63,8 +63,9 @@ typedef char fstring[FSTRING_LEN];
|
||||
* 31: added "client_name" to the request
|
||||
* 32: added "traceid" to the request
|
||||
* removed WINBINDD_INIT_CONNECTION
|
||||
* 33: removed WINBINDD_SHOW_SEQUENCE
|
||||
*/
|
||||
#define WINBIND_INTERFACE_VERSION 32
|
||||
#define WINBIND_INTERFACE_VERSION 33
|
||||
|
||||
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
|
||||
On a 64bit Linux box, we have to support a constant structure size
|
||||
@ -141,8 +142,6 @@ enum winbindd_cmd {
|
||||
WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */
|
||||
WINBINDD_DC_INFO, /* Which DC are we connected to? */
|
||||
|
||||
WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */
|
||||
|
||||
/* WINS commands */
|
||||
|
||||
WINBINDD_WINS_BYIP,
|
||||
|
@ -607,7 +607,10 @@ struct ea_list {
|
||||
struct ea_struct ea;
|
||||
};
|
||||
|
||||
/* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
|
||||
/*
|
||||
* EA names used internally in Samba. KEEP UP TO DATE with
|
||||
* samba_private_attr_name() in smb2_trans2.c !.
|
||||
*/
|
||||
#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
|
||||
/* EA to use for DOS attributes */
|
||||
#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB transaction2 handling
|
||||
|
||||
@ -11,12 +11,12 @@
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@ -208,7 +208,7 @@ Byte offset Type name description
|
||||
#define SMB_QUERY_FS_DEVICE_INFO 0x104
|
||||
#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
|
||||
#if 0
|
||||
#define SMB_QUERY_FS_QUOTA_INFO
|
||||
#define SMB_QUERY_FS_QUOTA_INFO
|
||||
#endif
|
||||
|
||||
#define l2_vol_fdateCreation 0
|
||||
|
@ -2584,11 +2584,8 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx,
|
||||
int mode;
|
||||
|
||||
if (fsp != NULL) {
|
||||
if (fsp_is_alternate_stream(fsp)) {
|
||||
smb_fname = fsp->base_fsp->fsp_name;
|
||||
} else {
|
||||
smb_fname = fsp->fsp_name;
|
||||
}
|
||||
struct files_struct *meta_fsp = metadata_fsp(fsp);
|
||||
smb_fname = meta_fsp->fsp_name;
|
||||
}
|
||||
|
||||
DEBUG(10, ("ad_get(%s) called for %s\n",
|
||||
|
@ -33,11 +33,11 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
|
||||
size_t converted_size;
|
||||
|
||||
if (!eal) {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (data_size < 6) {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eal->ea.flags = CVAL(pdata,0);
|
||||
@ -45,24 +45,23 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
|
||||
val_len = SVAL(pdata,2);
|
||||
|
||||
if (4 + namelen + 1 + val_len > data_size) {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Ensure the name is null terminated. */
|
||||
if (pdata[namelen + 4] != '\0') {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
|
||||
DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s\n",
|
||||
strerror(errno)));
|
||||
DBG_ERR("pull_ascii_talloc failed: %s\n", strerror(errno));
|
||||
}
|
||||
if (!eal->ea.name) {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
|
||||
if (!eal->ea.value.data) {
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
|
||||
@ -76,10 +75,13 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
|
||||
*pbytes_used = 4 + namelen + 1 + val_len;
|
||||
}
|
||||
|
||||
DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
|
||||
DBG_DEBUG("read ea name %s\n", eal->ea.name);
|
||||
dump_data(10, eal->ea.value.data, eal->ea.value.length);
|
||||
|
||||
return eal;
|
||||
fail:
|
||||
TALLOC_FREE(eal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Authentication utility functions
|
||||
* Copyright (C) Andrew Tridgell 1992-1998
|
||||
@ -13,12 +13,12 @@
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
@ -274,23 +274,20 @@ static int connect_acl_tdb(struct vfs_handle_struct *handle,
|
||||
|
||||
if (config->ignore_system_acls) {
|
||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||
char *create_mask_str = NULL;
|
||||
|
||||
if ((create_mask & 0666) != 0666) {
|
||||
char create_mask_str[16];
|
||||
|
||||
create_mask |= 0666;
|
||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
||||
create_mask);
|
||||
if (create_mask_str == NULL) {
|
||||
DBG_ERR("talloc_asprintf failed\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(create_mask_str,
|
||||
sizeof(create_mask_str),
|
||||
"0%o",
|
||||
create_mask);
|
||||
|
||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||
|
||||
lp_do_parameter (SNUM(handle->conn),
|
||||
"create mask", create_mask_str);
|
||||
|
||||
TALLOC_FREE(create_mask_str);
|
||||
}
|
||||
|
||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
||||
|
@ -218,23 +218,21 @@ static int connect_acl_xattr(struct vfs_handle_struct *handle,
|
||||
|
||||
if (config->ignore_system_acls) {
|
||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||
char *create_mask_str = NULL;
|
||||
|
||||
if ((create_mask & 0666) != 0666) {
|
||||
char create_mask_str[16];
|
||||
|
||||
create_mask |= 0666;
|
||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
||||
create_mask);
|
||||
if (create_mask_str == NULL) {
|
||||
DBG_ERR("talloc_asprintf failed\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(create_mask_str,
|
||||
sizeof(create_mask_str),
|
||||
"0%o",
|
||||
create_mask);
|
||||
|
||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||
|
||||
lp_do_parameter (SNUM(handle->conn),
|
||||
"create mask", create_mask_str);
|
||||
|
||||
TALLOC_FREE(create_mask_str);
|
||||
lp_do_parameter(SNUM(handle->conn),
|
||||
"create mask",
|
||||
create_mask_str);
|
||||
}
|
||||
|
||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
||||
|
@ -158,19 +158,15 @@ static char *stream_dir(vfs_handle_struct *handle,
|
||||
SMB_STRUCT_STAT base_sbuf_tmp;
|
||||
char *tmp = NULL;
|
||||
uint8_t first, second;
|
||||
char *id_hex;
|
||||
struct file_id id;
|
||||
uint8_t id_buf[16];
|
||||
bool check_valid;
|
||||
char id_hex[sizeof(id_buf) * 2 + 1];
|
||||
char *rootdir = NULL;
|
||||
struct smb_filename *rootdir_fname = NULL;
|
||||
struct smb_filename *tmp_fname = NULL;
|
||||
struct vfs_rename_how rhow = { .flags = 0, };
|
||||
int ret;
|
||||
|
||||
check_valid = lp_parm_bool(SNUM(handle->conn),
|
||||
"streams_depot", "check_valid", true);
|
||||
|
||||
rootdir = stream_rootdir(handle,
|
||||
talloc_tos());
|
||||
if (rootdir == NULL) {
|
||||
@ -223,18 +219,11 @@ static char *stream_dir(vfs_handle_struct *handle,
|
||||
first = hash & 0xff;
|
||||
second = (hash >> 8) & 0xff;
|
||||
|
||||
id_hex = hex_encode_talloc(talloc_tos(), id_buf, sizeof(id_buf));
|
||||
|
||||
if (id_hex == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
hex_encode_buf(id_hex, id_buf, sizeof(id_buf));
|
||||
|
||||
result = talloc_asprintf(talloc_tos(), "%s/%2.2X/%2.2X/%s", rootdir,
|
||||
first, second, id_hex);
|
||||
|
||||
TALLOC_FREE(id_hex);
|
||||
|
||||
if (result == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
@ -254,13 +243,18 @@ static char *stream_dir(vfs_handle_struct *handle,
|
||||
if (SMB_VFS_NEXT_STAT(handle, smb_fname_hash) == 0) {
|
||||
struct smb_filename *smb_fname_new = NULL;
|
||||
char *newname;
|
||||
bool delete_lost;
|
||||
bool check_valid, delete_lost;
|
||||
|
||||
if (!S_ISDIR(smb_fname_hash->st.st_ex_mode)) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
check_valid = lp_parm_bool(SNUM(handle->conn),
|
||||
"streams_depot",
|
||||
"check_valid",
|
||||
true);
|
||||
|
||||
if (!check_valid ||
|
||||
file_is_valid(handle, smb_fname)) {
|
||||
return result;
|
||||
@ -277,9 +271,9 @@ static char *stream_dir(vfs_handle_struct *handle,
|
||||
"delete_lost", false);
|
||||
|
||||
if (delete_lost) {
|
||||
DEBUG(3, ("Someone has recreated a file under an "
|
||||
"existing inode. Removing: %s\n",
|
||||
smb_fname_hash->base_name));
|
||||
DBG_NOTICE("Someone has recreated a file under an "
|
||||
"existing inode. Removing: %s\n",
|
||||
smb_fname_hash->base_name);
|
||||
recursive_rmdir(talloc_tos(), handle->conn,
|
||||
smb_fname_hash);
|
||||
SMB_VFS_NEXT_UNLINKAT(handle,
|
||||
@ -289,10 +283,10 @@ static char *stream_dir(vfs_handle_struct *handle,
|
||||
} else {
|
||||
newname = talloc_asprintf(talloc_tos(), "lost-%lu",
|
||||
random());
|
||||
DEBUG(3, ("Someone has recreated a file under an "
|
||||
"existing inode. Renaming: %s to: %s\n",
|
||||
smb_fname_hash->base_name,
|
||||
newname));
|
||||
DBG_NOTICE("Someone has recreated a file under an "
|
||||
"existing inode. Renaming: %s to: %s\n",
|
||||
smb_fname_hash->base_name,
|
||||
newname);
|
||||
if (newname == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
|
@ -829,12 +829,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
@ -891,13 +885,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_NOTICE("Can't open new file [%s], errno = %d\n",
|
||||
smb_fname_str_dbg(smb_fname), errno);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
@ -1110,15 +1097,6 @@ static uint32_t get_correct_cversion(const struct auth_session_info *session_inf
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DBG_NOTICE("Can't open file [%s]: %s\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
nt_errstr(nt_status));
|
||||
*perr = WERR_ACCESS_DENIED;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
nt_status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
|
@ -176,8 +176,8 @@ static void display_sam_dom_info_2(struct samr_DomGeneralInformation *general)
|
||||
|
||||
static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
|
||||
{
|
||||
printf("Force Logoff:\t%d\n",
|
||||
(int)nt_time_to_unix_abs(&info3->force_logoff_time));
|
||||
printf("Force Logoff:\t%" PRIu64 "\n",
|
||||
(uint64_t)nt_time_to_unix_abs(&info3->force_logoff_time));
|
||||
}
|
||||
|
||||
static void display_sam_dom_info_4(struct samr_DomOEMInformation *oem)
|
||||
|
@ -973,15 +973,10 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
|
||||
|
||||
return status;
|
||||
}
|
||||
/****************************************************************************
|
||||
Function used by reply_rmdir to delete an entire directory
|
||||
tree recursively. Return True on ok, False on fail.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_filename *smb_dname)
|
||||
static NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
|
||||
{
|
||||
struct connection_struct *conn = fsp->conn;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
@ -989,14 +984,7 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
int retval;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
|
||||
|
||||
status = OpenDir(talloc_tos(),
|
||||
conn,
|
||||
smb_dname,
|
||||
NULL,
|
||||
0,
|
||||
&dir_hnd);
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -1005,9 +993,6 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||
struct smb_filename *atname = NULL;
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
char *fullname = NULL;
|
||||
bool do_break = true;
|
||||
int unlink_flags = 0;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
@ -1015,56 +1000,56 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Construct the full name. */
|
||||
fullname = talloc_asprintf(ctx,
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
if (!fullname) {
|
||||
atname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
NULL,
|
||||
dirfsp->fsp_name->twrp,
|
||||
dirfsp->fsp_name->flags);
|
||||
TALLOC_FREE(talloced);
|
||||
dname = NULL;
|
||||
|
||||
if (atname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
break;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
{
|
||||
struct name_compare_entry *veto_list = conn->veto_list;
|
||||
|
||||
/*
|
||||
* Sneaky hack to be able to open veto files
|
||||
* with openat_pathref_fsp
|
||||
*/
|
||||
|
||||
conn->veto_list = NULL;
|
||||
status = openat_pathref_fsp_lcomp(
|
||||
dirfsp,
|
||||
atname,
|
||||
UCF_POSIX_PATHNAMES /* no ci fallback */);
|
||||
conn->veto_list = veto_list;
|
||||
}
|
||||
|
||||
if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(atname);
|
||||
if (NT_STATUS_EQUAL(status,
|
||||
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/* race between readdir and unlink */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir(ctx, conn, smb_dname_full);
|
||||
if (atname->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir_fsp(atname->fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
TALLOC_FREE(atname);
|
||||
break;
|
||||
}
|
||||
unlink_flags = AT_REMOVEDIR;
|
||||
}
|
||||
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname_full->twrp,
|
||||
smb_dname_full->flags,
|
||||
&atname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(atname->fsp)) {
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(atname);
|
||||
continue;
|
||||
}
|
||||
@ -1075,25 +1060,34 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
unlink_flags);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/* Successful iteration. */
|
||||
do_break = false;
|
||||
|
||||
err_break:
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(atname);
|
||||
if (do_break) {
|
||||
TALLOC_FREE(atname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(atname);
|
||||
}
|
||||
|
||||
TALLOC_FREE(dir_hnd);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_filename *smb_dname)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
|
||||
|
||||
status = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = recursive_rmdir_fsp(smb_dname->fsp);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
The internals of the rmdir code - called elsewhere.
|
||||
****************************************************************************/
|
||||
@ -1104,8 +1098,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
struct smb_filename *smb_dname = fsp->fsp_name;
|
||||
struct smb_filename *parent_fname = NULL;
|
||||
struct smb_filename *at_fname = NULL;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
struct files_struct *dirfsp = NULL;
|
||||
int unlink_flags = 0;
|
||||
@ -1179,7 +1171,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the only thing in this directory are
|
||||
* Check to see if the only things in this directory are
|
||||
* files non-visible to the client. If not, fail the delete.
|
||||
*/
|
||||
|
||||
@ -1196,271 +1188,18 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
|
||||
|
||||
dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
char *fullname = NULL;
|
||||
int retval;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
if (IS_VETO_PATH(conn, dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(talloc_tos(),
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
|
||||
if (fullname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
retval = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
/* Could it be an msdfs link ? */
|
||||
if (lp_host_msdfs() &&
|
||||
lp_msdfs_root(SNUM(conn))) {
|
||||
struct smb_filename *smb_atname;
|
||||
smb_atname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_atname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
if (is_msdfs_link(fsp, smb_atname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(smb_atname);
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
TALLOC_FREE(smb_atname);
|
||||
}
|
||||
|
||||
/* Not a DFS link - could it be a dangling symlink ? */
|
||||
retval = SMB_VFS_STAT(conn, smb_dname_full);
|
||||
if (retval == -1 && (errno == ENOENT || errno == ELOOP)) {
|
||||
/*
|
||||
* Dangling symlink.
|
||||
* Allow delete as "delete veto files = yes"
|
||||
*/
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG_DEBUG("got symlink name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Not a symlink, get a pathref. */
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We found a client visible name.
|
||||
* We cannot delete this directory.
|
||||
*/
|
||||
DBG_DEBUG("got name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
status = can_delete_directory_hnd(dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Do a recursive delete. */
|
||||
RewindDir(dir_hnd);
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
char *fullname = NULL;
|
||||
bool do_break = true;
|
||||
int retval;
|
||||
|
||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(ctx,
|
||||
"%s/%s",
|
||||
smb_dname->base_name,
|
||||
dname);
|
||||
|
||||
if (fullname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Todo: use SMB_VFS_STATX() once that's available.
|
||||
*/
|
||||
|
||||
retval = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are only dealing with VETO'ed objects
|
||||
* here. If it's a symlink, just delete the
|
||||
* link without caring what it is pointing
|
||||
* to.
|
||||
*/
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
direntry_fname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags);
|
||||
if (direntry_fname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto err_break;
|
||||
}
|
||||
} else {
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
dirfsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
smb_dname->twrp,
|
||||
smb_dname->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unlink_flags = 0;
|
||||
|
||||
if (smb_dname_full->st.st_ex_mode & S_IFDIR) {
|
||||
status = recursive_rmdir(ctx, conn, smb_dname_full);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto err_break;
|
||||
}
|
||||
unlink_flags = AT_REMOVEDIR;
|
||||
}
|
||||
|
||||
retval = SMB_VFS_UNLINKAT(conn,
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
unlink_flags);
|
||||
if (retval != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto err_break;
|
||||
}
|
||||
|
||||
/* Successful iteration. */
|
||||
do_break = false;
|
||||
|
||||
err_break:
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
if (do_break) {
|
||||
break;
|
||||
}
|
||||
status = recursive_rmdir_fsp(dirfsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* If we get here, we know NT_STATUS_IS_OK(status) */
|
||||
SMB_ASSERT(NT_STATUS_IS_OK(status));
|
||||
|
||||
/* Retry the rmdir */
|
||||
ret = SMB_VFS_UNLINKAT(conn,
|
||||
parent_fname->fsp,
|
||||
|
@ -1222,11 +1222,12 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* ignore tmp directories, see mkdir_internals()
|
||||
* ignore tmp directories, see mkdir_internal()
|
||||
*/
|
||||
if (IS_SMBD_TMPNAME(n, &unlink_flags)) {
|
||||
struct files_struct *dirfsp = dir_hnd->fsp;
|
||||
const char *dirname = dirfsp->fsp_name->base_name;
|
||||
struct smb_filename *atname = NULL;
|
||||
const char *fp = NULL;
|
||||
int ret;
|
||||
|
||||
atname = synthetic_smb_fname(talloc_tos(),
|
||||
@ -1239,17 +1240,9 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
fp = full_path_from_dirfsp_at_basename(atname,
|
||||
dir_hnd->fsp,
|
||||
n);
|
||||
if (fp == NULL) {
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unlink_flags == INT_MAX) {
|
||||
DBG_NOTICE("ignoring %s\n", fp);
|
||||
DBG_NOTICE("ignoring %s/%s\n", dirname, n);
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
@ -1259,18 +1252,23 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
||||
* We remove the stale tmpname
|
||||
* as root and ignore any errors
|
||||
*/
|
||||
DBG_NOTICE("unlink stale %s\n", fp);
|
||||
DBG_NOTICE("unlink stale %s/%s\n", dirname, n);
|
||||
become_root();
|
||||
ret = SMB_VFS_UNLINKAT(conn,
|
||||
dir_hnd->fsp,
|
||||
dirfsp,
|
||||
atname,
|
||||
unlink_flags);
|
||||
unbecome_root();
|
||||
if (ret == 0) {
|
||||
DBG_NOTICE("unlinked stale %s\n", fp);
|
||||
DBG_NOTICE("unlinked stale %s/%s\n",
|
||||
dirname,
|
||||
n);
|
||||
} else {
|
||||
DBG_WARNING("failed to unlink stale %s: %s\n",
|
||||
fp, strerror(errno));
|
||||
DBG_WARNING(
|
||||
"failed to unlink stale %s/%s: %s\n",
|
||||
dirname,
|
||||
n,
|
||||
strerror(errno));
|
||||
}
|
||||
TALLOC_FREE(atname);
|
||||
TALLOC_FREE(talloced);
|
||||
@ -1541,137 +1539,96 @@ bool opens_below_forall(struct connection_struct *conn,
|
||||
Is this directory empty ?
|
||||
*****************************************************************/
|
||||
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
NTSTATUS can_delete_directory_hnd(struct smb_Dir *dir_hnd)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
const char *dname = NULL;
|
||||
char *talloced = NULL;
|
||||
struct connection_struct *conn = fsp->conn;
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
struct files_struct *dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||
struct connection_struct *conn = dirfsp->conn;
|
||||
bool delete_veto = lp_delete_veto_files(SNUM(conn));
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||
struct smb_filename *smb_dname_full = NULL;
|
||||
struct smb_filename *direntry_fname = NULL;
|
||||
char *fullname = NULL;
|
||||
int ret;
|
||||
|
||||
if (ISDOT(dname) || (ISDOTDOT(dname))) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
if (IS_VETO_PATH(conn, dname)) {
|
||||
if (delete_veto && IS_VETO_PATH(conn, dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
continue;
|
||||
}
|
||||
|
||||
fullname = talloc_asprintf(talloc_tos(),
|
||||
"%s/%s",
|
||||
fsp->fsp_name->base_name,
|
||||
dname);
|
||||
if (fullname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
direntry_fname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
NULL,
|
||||
dirfsp->fsp_name->twrp,
|
||||
dirfsp->fsp_name->flags);
|
||||
TALLOC_FREE(talloced);
|
||||
dname = NULL;
|
||||
|
||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
||||
fullname,
|
||||
NULL,
|
||||
NULL,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_dname_full == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
if (direntry_fname == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = SMB_VFS_LSTAT(conn, smb_dname_full);
|
||||
if (ret != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
break;
|
||||
}
|
||||
status = openat_pathref_fsp_lcomp(
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
UCF_POSIX_PATHNAMES /* no ci fallback */);
|
||||
|
||||
if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
|
||||
/* Could it be an msdfs link ? */
|
||||
if (lp_host_msdfs() &&
|
||||
lp_msdfs_root(SNUM(conn))) {
|
||||
struct smb_filename *smb_dname;
|
||||
smb_dname = synthetic_smb_fname(talloc_tos(),
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags);
|
||||
if (smb_dname == NULL) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (is_msdfs_link(fsp, smb_dname)) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(smb_dname);
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
TALLOC_FREE(smb_dname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DBG_DEBUG("Could not open %s: %s\n",
|
||||
direntry_fname->base_name,
|
||||
nt_errstr(status));
|
||||
|
||||
TALLOC_FREE(direntry_fname);
|
||||
|
||||
if (NT_STATUS_EQUAL(status,
|
||||
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/* race between readdir and unlink */
|
||||
continue;
|
||||
}
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISLNK(direntry_fname->st.st_ex_mode)) {
|
||||
int ret;
|
||||
|
||||
if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&
|
||||
is_msdfs_link(dirfsp, direntry_fname))
|
||||
{
|
||||
|
||||
DBG_DEBUG("got msdfs link name %s "
|
||||
"- can't delete directory %s\n",
|
||||
direntry_fname->base_name,
|
||||
fsp_str_dbg(dirfsp));
|
||||
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
|
||||
TALLOC_FREE(direntry_fname);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not a DFS link - could it be a dangling symlink ? */
|
||||
ret = SMB_VFS_STAT(conn, smb_dname_full);
|
||||
ret = SMB_VFS_FSTATAT(conn,
|
||||
dirfsp,
|
||||
direntry_fname,
|
||||
&direntry_fname->st,
|
||||
0 /* 0 means follow symlink */);
|
||||
if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
|
||||
/*
|
||||
* Dangling symlink.
|
||||
* Allow if "delete veto files = yes"
|
||||
*/
|
||||
if (lp_delete_veto_files(SNUM(conn))) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
DBG_DEBUG("got symlink name %s - "
|
||||
"can't delete directory %s\n",
|
||||
dname,
|
||||
fsp_str_dbg(fsp));
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not a symlink, get a pathref. */
|
||||
status = synthetic_pathref(talloc_tos(),
|
||||
fsp,
|
||||
dname,
|
||||
NULL,
|
||||
&smb_dname_full->st,
|
||||
fsp->fsp_name->twrp,
|
||||
fsp->fsp_name->flags,
|
||||
&direntry_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_visible_fsp(direntry_fname->fsp)) {
|
||||
@ -1680,33 +1637,40 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
* Allow if "delete veto files = yes"
|
||||
*/
|
||||
if (lp_delete_veto_files(SNUM(conn))) {
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(fullname);
|
||||
TALLOC_FREE(smb_dname_full);
|
||||
DBG_DEBUG("got name %s - can't delete\n",
|
||||
direntry_fname->base_name);
|
||||
TALLOC_FREE(direntry_fname);
|
||||
|
||||
DBG_DEBUG("got name %s - can't delete\n", dname);
|
||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||
break;
|
||||
}
|
||||
TALLOC_FREE(talloced);
|
||||
TALLOC_FREE(dir_hnd);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (have_file_open_below(fsp)) {
|
||||
if (have_file_open_below(dirfsp)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp)
|
||||
{
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
status = can_delete_directory_hnd(dir_hnd);
|
||||
TALLOC_FREE(dir_hnd);
|
||||
return status;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
struct smb_Dir;
|
||||
struct dptr_struct;
|
||||
|
||||
NTSTATUS can_delete_directory_hnd(struct smb_Dir *dir_hnd);
|
||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp);
|
||||
struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd);
|
||||
uint16_t dptr_attr(struct smbd_server_connection *sconn, int key);
|
||||
|
@ -5423,6 +5423,7 @@ void msg_file_was_renamed(struct messaging_context *msg_ctx,
|
||||
*/
|
||||
|
||||
static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
struct files_struct *dirfsp,
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
struct stream_struct *stream_info = NULL;
|
||||
@ -5475,8 +5476,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DEBUG(10, ("open_streams_for_delete found %d streams\n",
|
||||
num_streams));
|
||||
DBG_DEBUG("open_streams_for_delete found %u streams\n", num_streams);
|
||||
|
||||
if (num_streams == 0) {
|
||||
TALLOC_FREE(frame);
|
||||
@ -5522,7 +5522,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
NULL, /* req */
|
||||
NULL, /* dirfsp */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname_cp, /* fname */
|
||||
DELETE_ACCESS, /* access_mask */
|
||||
(FILE_SHARE_READ | /* share_access */
|
||||
@ -6222,7 +6222,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
|
||||
* We can't open a file with DELETE access if any of the
|
||||
* streams is open without FILE_SHARE_DELETE
|
||||
*/
|
||||
status = open_streams_for_delete(conn, smb_fname);
|
||||
status = open_streams_for_delete(conn, dirfsp, smb_fname);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
|
@ -2181,22 +2181,18 @@ static NTSTATUS smb_q_unix_info2(
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#if defined(HAVE_POSIX_ACLS)
|
||||
/****************************************************************************
|
||||
Utility function to open a fsp for a POSIX handle operation.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
struct files_struct *dirfsp,
|
||||
struct smb_filename *smb_fname,
|
||||
uint32_t access_mask,
|
||||
files_struct **ret_fsp)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint32_t create_disposition = FILE_OPEN;
|
||||
uint32_t share_access = FILE_SHARE_READ|
|
||||
FILE_SHARE_WRITE|
|
||||
FILE_SHARE_DELETE;
|
||||
struct smb2_create_blobs *posx = NULL;
|
||||
|
||||
/*
|
||||
@ -2204,7 +2200,6 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
* but set reasonable defaults.
|
||||
*/
|
||||
uint32_t file_attributes = 0664;
|
||||
uint32_t oplock = NO_OPLOCK;
|
||||
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
|
||||
|
||||
/* File or directory must exist. */
|
||||
@ -2234,31 +2229,34 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||
}
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
NULL, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
access_mask, /* access_mask */
|
||||
share_access, /* share_access */
|
||||
create_disposition,/* create_disposition*/
|
||||
create_options, /* create_options */
|
||||
file_attributes,/* file_attributes */
|
||||
oplock, /* oplock_request */
|
||||
NULL, /* lease */
|
||||
0, /* allocation_size */
|
||||
0, /* private_flags */
|
||||
NULL, /* sd */
|
||||
NULL, /* ea_list */
|
||||
ret_fsp, /* result */
|
||||
NULL, /* pinfo */
|
||||
posx, /* in_context */
|
||||
NULL); /* out_context */
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
access_mask, /* access_mask */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||
FILE_SHARE_DELETE, /* share_access */
|
||||
FILE_OPEN, /* create_disposition*/
|
||||
create_options, /* create_options */
|
||||
file_attributes, /* file_attributes */
|
||||
NO_OPLOCK, /* oplock_request */
|
||||
NULL, /* lease */
|
||||
0, /* allocation_size */
|
||||
0, /* private_flags */
|
||||
NULL, /* sd */
|
||||
NULL, /* ea_list */
|
||||
ret_fsp, /* result */
|
||||
NULL, /* pinfo */
|
||||
posx, /* in_context */
|
||||
NULL); /* out_context */
|
||||
|
||||
done:
|
||||
TALLOC_FREE(posx);
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(HAVE_POSIX_ACLS)
|
||||
|
||||
/****************************************************************************
|
||||
Utility function to count the number of entries in a POSIX acl.
|
||||
****************************************************************************/
|
||||
@ -2388,30 +2386,6 @@ static NTSTATUS smb_q_posix_acl(
|
||||
unsigned int size_needed = 0;
|
||||
NTSTATUS status;
|
||||
bool ok, refuse;
|
||||
bool close_fsp = false;
|
||||
|
||||
/*
|
||||
* Ensure we always operate on a file descriptor, not just
|
||||
* the filename.
|
||||
*/
|
||||
if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
|
||||
uint32_t access_mask = SEC_STD_READ_CONTROL|
|
||||
FILE_READ_ATTRIBUTES|
|
||||
FILE_WRITE_ATTRIBUTES;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
smb_fname,
|
||||
access_mask,
|
||||
&fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
close_fsp = true;
|
||||
}
|
||||
|
||||
SMB_ASSERT(fsp != NULL);
|
||||
|
||||
refuse = refuse_symlink_fsp(fsp);
|
||||
if (refuse) {
|
||||
@ -2509,16 +2483,6 @@ static NTSTATUS smb_q_posix_acl(
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
out:
|
||||
|
||||
if (close_fsp) {
|
||||
/*
|
||||
* Ensure the stat struct in smb_fname is up to
|
||||
* date. Structure copy.
|
||||
*/
|
||||
smb_fname->st = fsp->fsp_name->st;
|
||||
(void)close_file_free(req, &fsp, NORMAL_CLOSE);
|
||||
}
|
||||
|
||||
TALLOC_FREE(file_acl);
|
||||
TALLOC_FREE(def_acl);
|
||||
return status;
|
||||
@ -2762,15 +2726,25 @@ static void call_trans2qpathinfo(
|
||||
&total_data);
|
||||
break;
|
||||
|
||||
case SMB_QUERY_POSIX_ACL:
|
||||
case SMB_QUERY_POSIX_ACL: {
|
||||
struct files_struct *posix_fsp = NULL;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
SEC_STD_READ_CONTROL |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
&posix_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
break;
|
||||
}
|
||||
status = smb_q_posix_acl(
|
||||
conn,
|
||||
req,
|
||||
smb_fname,
|
||||
smb_fname->fsp,
|
||||
ppdata,
|
||||
&total_data);
|
||||
conn, req, smb_fname, posix_fsp, ppdata, &total_data);
|
||||
(void)close_file_free(req, &posix_fsp, NORMAL_CLOSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case SMB_QUERY_FILE_UNIX_LINK:
|
||||
status = smb_q_posix_symlink(conn,
|
||||
@ -3146,6 +3120,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
char **ppdata,
|
||||
int total_data,
|
||||
struct files_struct *dirfsp,
|
||||
struct smb_filename *smb_fname,
|
||||
int *pdata_return_size)
|
||||
{
|
||||
@ -3187,7 +3162,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
req, /* req */
|
||||
NULL, /* dirfsp */
|
||||
dirfsp, /* dirfsp */
|
||||
smb_fname, /* fname */
|
||||
FILE_READ_ATTRIBUTES, /* access_mask */
|
||||
FILE_SHARE_NONE, /* share_access */
|
||||
@ -3300,11 +3275,13 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
||||
wire_open_mode = IVAL(pdata,4);
|
||||
|
||||
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
|
||||
return smb_posix_mkdir(conn, req,
|
||||
ppdata,
|
||||
total_data,
|
||||
smb_fname,
|
||||
pdata_return_size);
|
||||
return smb_posix_mkdir(conn,
|
||||
req,
|
||||
ppdata,
|
||||
total_data,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
pdata_return_size);
|
||||
}
|
||||
|
||||
switch (wire_open_mode & SMB_ACCMODE) {
|
||||
@ -3431,10 +3408,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
||||
create_options |= FILE_DIRECTORY_FILE;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(unsigned int)wire_open_mode,
|
||||
(unsigned int)unixmode ));
|
||||
DBG_DEBUG("file %s, smb_posix_flags = %" PRIu32 ", mode 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
wire_open_mode,
|
||||
(unsigned int)unixmode);
|
||||
|
||||
status = SMB_VFS_CREATE_FILE(
|
||||
conn, /* conn */
|
||||
@ -3994,9 +3971,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
||||
}
|
||||
|
||||
DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC: name = "
|
||||
"%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
"%s size = %jd, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(double)size,
|
||||
(intmax_t)size,
|
||||
(unsigned int)set_owner,
|
||||
(unsigned int)set_grp,
|
||||
(int)raw_unixmode);
|
||||
@ -4044,10 +4021,10 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
|
||||
DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC "
|
||||
"setting mode 0%o for file %s\n",
|
||||
(unsigned int)unixmode,
|
||||
smb_fname_str_dbg(smb_fname)));
|
||||
smb_fname_str_dbg(smb_fname));
|
||||
ret = SMB_VFS_FCHMOD(fsp, unixmode);
|
||||
if (ret != 0) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
@ -4267,7 +4244,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
NTSTATUS status;
|
||||
unsigned int size_needed;
|
||||
unsigned int total_data;
|
||||
bool close_fsp = false;
|
||||
bool refuse;
|
||||
|
||||
if (total_data_in < 0) {
|
||||
@ -4329,32 +4305,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure we always operate on a file descriptor, not just
|
||||
* the filename.
|
||||
*/
|
||||
if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
|
||||
uint32_t access_mask = SEC_STD_WRITE_OWNER|
|
||||
SEC_STD_WRITE_DAC|
|
||||
SEC_STD_READ_CONTROL|
|
||||
FILE_READ_ATTRIBUTES|
|
||||
FILE_WRITE_ATTRIBUTES;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
smb_fname,
|
||||
access_mask,
|
||||
&fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
close_fsp = true;
|
||||
}
|
||||
|
||||
/* Here we know fsp != NULL */
|
||||
SMB_ASSERT(fsp != NULL);
|
||||
|
||||
refuse = refuse_symlink_fsp(fsp);
|
||||
if (refuse) {
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
@ -4404,10 +4354,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
out:
|
||||
|
||||
if (close_fsp) {
|
||||
(void)close_file_free(req, &fsp, NORMAL_CLOSE);
|
||||
}
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
@ -4568,21 +4514,34 @@ static void call_trans2setpathinfo(
|
||||
smb_fname->fsp,
|
||||
smb_fname);
|
||||
break;
|
||||
case SMB_SET_POSIX_ACL:
|
||||
case SMB_SET_POSIX_ACL: {
|
||||
struct files_struct *posix_fsp = NULL;
|
||||
|
||||
status = get_posix_fsp(conn,
|
||||
req,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
SEC_STD_WRITE_OWNER |
|
||||
SEC_STD_WRITE_DAC |
|
||||
SEC_STD_READ_CONTROL |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
&posix_fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = smb_set_posix_acl(
|
||||
conn, req, *ppdata, total_data, NULL, smb_fname);
|
||||
conn, req, *ppdata, total_data, posix_fsp, smb_fname);
|
||||
(void)close_file_free(req, &posix_fsp, NORMAL_CLOSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info_level_handled) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* smb_fname->fsp may be NULL if smb_fname points at a symlink
|
||||
* and we're in POSIX context, so be careful when using fsp
|
||||
* below, it can still be NULL.
|
||||
*/
|
||||
fsp = smb_fname->fsp;
|
||||
if (fsp == NULL) {
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
@ -4702,10 +4661,10 @@ static void call_trans2setfileinfo(
|
||||
*ppdata, 0,
|
||||
max_data_bytes);
|
||||
return;
|
||||
} else {
|
||||
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Original code - this is an open file.
|
||||
|
@ -2474,25 +2474,30 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
|
||||
|
||||
rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
|
||||
|
||||
if (!rc) {
|
||||
data_len = 56;
|
||||
SIVAL(pdata,0,svfs.OptimalTransferSize);
|
||||
SIVAL(pdata,4,svfs.BlockSize);
|
||||
SBIG_UINT(pdata,8,svfs.TotalBlocks);
|
||||
SBIG_UINT(pdata,16,svfs.BlocksAvail);
|
||||
SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
|
||||
SBIG_UINT(pdata,32,svfs.TotalFileNodes);
|
||||
SBIG_UINT(pdata,40,svfs.FreeFileNodes);
|
||||
SBIG_UINT(pdata,48,svfs.FsIdentifier);
|
||||
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
|
||||
#ifdef EOPNOTSUPP
|
||||
} else if (rc == EOPNOTSUPP) {
|
||||
if (rc == EOPNOTSUPP) {
|
||||
return NT_STATUS_INVALID_LEVEL;
|
||||
#endif /* EOPNOTSUPP */
|
||||
} else {
|
||||
DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
|
||||
}
|
||||
#endif
|
||||
if (rc != 0) {
|
||||
DBG_ERR("vfs_statvfs() failed for service "
|
||||
"[%s]\n",
|
||||
lp_servicename(talloc_tos(),
|
||||
lp_sub,
|
||||
SNUM(conn)));
|
||||
return NT_STATUS_DOS(ERRSRV, ERRerror);
|
||||
}
|
||||
|
||||
data_len = 56;
|
||||
PUSH_LE_U32(pdata, 0, svfs.OptimalTransferSize);
|
||||
PUSH_LE_U32(pdata, 4, svfs.BlockSize);
|
||||
PUSH_LE_U64(pdata, 8, svfs.TotalBlocks);
|
||||
PUSH_LE_U64(pdata, 16, svfs.BlocksAvail);
|
||||
PUSH_LE_U64(pdata, 24, svfs.UserBlocksAvail);
|
||||
PUSH_LE_U64(pdata, 32, svfs.TotalFileNodes);
|
||||
PUSH_LE_U64(pdata, 40, svfs.FreeFileNodes);
|
||||
PUSH_LE_U64(pdata, 48, svfs.FsIdentifier);
|
||||
DBG_INFO("SMB_QUERY_POSIX_FS_INFO successful\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5052,11 +5057,10 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
size = IVAL(pdata,0);
|
||||
size |= (((off_t)IVAL(pdata,4)) << 32);
|
||||
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
|
||||
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
|
||||
(double)size));
|
||||
size = (off_t)PULL_LE_U64(pdata, 0);
|
||||
DBG_DEBUG("Set end of file info for file %s to %ju\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
(uintmax_t)size);
|
||||
|
||||
return smb_set_file_size(conn, req,
|
||||
fsp,
|
||||
|
@ -342,8 +342,12 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename
|
||||
fixup_eventlog_record_tdb( &ee );
|
||||
|
||||
if ( opt_debug )
|
||||
printf( "record number [%d], tg [%d] , tw [%d]\n",
|
||||
ee.record_number, (int)ee.time_generated, (int)ee.time_written );
|
||||
printf("record number [%" PRIu32 "], "
|
||||
"tg [%" PRIu64 "] , "
|
||||
"tw [%" PRIu64 "]\n",
|
||||
ee.record_number,
|
||||
(uint64_t)ee.time_generated,
|
||||
(uint64_t)ee.time_written);
|
||||
|
||||
if ( ee.time_generated != 0 ) {
|
||||
|
||||
|
@ -355,8 +355,9 @@ static int account_set_minpwage(struct net_context *c,
|
||||
}
|
||||
|
||||
unix_to_nt_time_abs((NTTIME *)&i1->min_password_age, atoi(argv[0]));
|
||||
d_printf(_("Setting minimum password age to %d seconds\n"),
|
||||
(int)nt_time_to_unix_abs((NTTIME *)&i1->min_password_age));
|
||||
d_printf(_("Setting minimum password age to %" PRIu64 " seconds\n"),
|
||||
(uint64_t)nt_time_to_unix_abs(
|
||||
(NTTIME *)&i1->min_password_age));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
async seqnum
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
#include "librpc/gen_ndr/ndr_winbind_c.h"
|
||||
|
||||
struct wb_seqnum_state {
|
||||
uint32_t seqnum;
|
||||
};
|
||||
|
||||
static void wb_seqnum_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *wb_seqnum_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_domain *domain)
|
||||
{
|
||||
struct tevent_req *req, *subreq;
|
||||
struct wb_seqnum_state *state;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state, struct wb_seqnum_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
subreq = dcerpc_wbint_QuerySequenceNumber_send(
|
||||
state, ev, dom_child_handle(domain), &state->seqnum);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, wb_seqnum_done, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void wb_seqnum_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct wb_seqnum_state *state = tevent_req_data(
|
||||
req, struct wb_seqnum_state);
|
||||
NTSTATUS status, result;
|
||||
|
||||
status = dcerpc_wbint_QuerySequenceNumber_recv(subreq, state, &result);
|
||||
TALLOC_FREE(subreq);
|
||||
if (any_nt_status_not_ok(status, result, &status)) {
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS wb_seqnum_recv(struct tevent_req *req, uint32_t *seqnum)
|
||||
{
|
||||
struct wb_seqnum_state *state = tevent_req_data(
|
||||
req, struct wb_seqnum_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
*seqnum = state->seqnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
async seqnums, update the seqnums in winbindd_cache.c
|
||||
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
#include "librpc/gen_ndr/ndr_winbind_c.h"
|
||||
|
||||
struct wb_seqnums_state {
|
||||
int num_domains;
|
||||
int num_received;
|
||||
|
||||
struct tevent_req **subreqs;
|
||||
struct winbindd_domain **domains;
|
||||
NTSTATUS *statuses;
|
||||
uint32_t *seqnums;
|
||||
};
|
||||
|
||||
static void wb_seqnums_done(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev)
|
||||
{
|
||||
struct tevent_req *req;
|
||||
struct wb_seqnums_state *state;
|
||||
struct winbindd_domain *domain;
|
||||
int i;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state, struct wb_seqnums_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->num_received = 0;
|
||||
state->num_domains = 0;
|
||||
|
||||
for (domain = domain_list(); domain != NULL; domain = domain->next) {
|
||||
state->num_domains += 1;
|
||||
}
|
||||
|
||||
state->subreqs = talloc_array(state, struct tevent_req *,
|
||||
state->num_domains);
|
||||
state->domains = talloc_zero_array(state, struct winbindd_domain *,
|
||||
state->num_domains);
|
||||
state->statuses = talloc_array(state, NTSTATUS, state->num_domains);
|
||||
state->seqnums = talloc_array(state, uint32_t, state->num_domains);
|
||||
|
||||
if ((state->subreqs == NULL) || (state->domains == NULL) ||
|
||||
(state->statuses == NULL) || (state->seqnums == NULL)) {
|
||||
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
for (domain = domain_list(); domain != NULL; domain = domain->next) {
|
||||
state->domains[i] = domain;
|
||||
state->subreqs[i] = wb_seqnum_send(state->subreqs, ev, domain);
|
||||
if (tevent_req_nomem(state->subreqs[i], req)) {
|
||||
/* Don't even start all the other requests */
|
||||
TALLOC_FREE(state->subreqs);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(state->subreqs[i], wb_seqnums_done,
|
||||
req);
|
||||
i += 1;
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
static void wb_seqnums_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct wb_seqnums_state *state = tevent_req_data(
|
||||
req, struct wb_seqnums_state);
|
||||
NTSTATUS status;
|
||||
uint32_t seqnum;
|
||||
int i;
|
||||
|
||||
status = wb_seqnum_recv(subreq, &seqnum);
|
||||
|
||||
for (i=0; i<state->num_domains; i++) {
|
||||
if (subreq == state->subreqs[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < state->num_domains) {
|
||||
/* found one */
|
||||
|
||||
state->subreqs[i] = NULL;
|
||||
state->statuses[i] = status;
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
state->seqnums[i] = seqnum;
|
||||
|
||||
/*
|
||||
* This first assignment might be removed
|
||||
* later
|
||||
*/
|
||||
state->domains[i]->sequence_number = seqnum;
|
||||
|
||||
if (!wcache_store_seqnum(state->domains[i]->name,
|
||||
state->seqnums[i],
|
||||
time(NULL))) {
|
||||
DEBUG(1, ("wcache_store_seqnum failed for "
|
||||
"domain %s\n",
|
||||
state->domains[i]->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TALLOC_FREE(subreq);
|
||||
|
||||
state->num_received += 1;
|
||||
|
||||
if (state->num_received >= state->num_domains) {
|
||||
tevent_req_done(req);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
int *num_domains, struct winbindd_domain ***domains,
|
||||
NTSTATUS **statuses, uint32_t **seqnums)
|
||||
{
|
||||
struct wb_seqnums_state *state = tevent_req_data(
|
||||
req, struct wb_seqnums_state);
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
*num_domains = state->num_domains;
|
||||
*domains = talloc_move(mem_ctx, &state->domains);
|
||||
*statuses = talloc_move(mem_ctx, &state->statuses);
|
||||
*seqnums = talloc_move(mem_ctx, &state->seqnums);
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -338,8 +338,6 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
|
||||
winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
|
||||
{ WINBINDD_GETGROUPS, "GETGROUPS",
|
||||
winbindd_getgroups_send, winbindd_getgroups_recv },
|
||||
{ WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
|
||||
winbindd_show_sequence_send, winbindd_show_sequence_recv },
|
||||
{ WINBINDD_GETGRGID, "GETGRGID",
|
||||
winbindd_getgrgid_send, winbindd_getgrgid_recv },
|
||||
{ WINBINDD_GETGRNAM, "GETGRNAM",
|
||||
|
@ -59,9 +59,11 @@ static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
|
||||
|
||||
expire = nt_time_to_unix(ads->auth.expire_time);
|
||||
|
||||
DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
|
||||
"is now %d)\n", (uint32_t)expire - (uint32_t)now,
|
||||
(uint32_t) expire, (uint32_t) now));
|
||||
DBG_INFO("Current tickets expire in %" PRIu64 " seconds "
|
||||
"(at %" PRIu64 ", time is now %" PRIu64 ")\n",
|
||||
(uint64_t)expire - (uint64_t)now,
|
||||
(uint64_t)expire,
|
||||
(uint64_t)now);
|
||||
|
||||
if ( ads->config.realm && (expire > now)) {
|
||||
return;
|
||||
|
@ -502,8 +502,6 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
|
||||
|
||||
struct winbindd_domain *domain_list(void);
|
||||
struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain);
|
||||
bool set_routing_domain(struct winbindd_domain *domain,
|
||||
struct winbindd_domain *routing_domain);
|
||||
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||
struct info3_text *info3,
|
||||
struct info6_text *info6);
|
||||
@ -742,24 +740,6 @@ struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
|
||||
NTSTATUS winbindd_getgroups_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response);
|
||||
|
||||
struct tevent_req *wb_seqnum_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_domain *domain);
|
||||
NTSTATUS wb_seqnum_recv(struct tevent_req *req, uint32_t *seqnum);
|
||||
|
||||
struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev);
|
||||
NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
||||
int *num_domains, struct winbindd_domain ***domains,
|
||||
NTSTATUS **statuses, uint32_t **seqnums);
|
||||
|
||||
struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_cli_state *cli,
|
||||
struct winbindd_request *request);
|
||||
NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response);
|
||||
|
||||
struct tevent_req *wb_group_members_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
const struct dom_sid *sid,
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
async implementation of WINBINDD_SHOW_SEQUENCE
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
|
||||
struct winbindd_show_sequence_state {
|
||||
bool one_domain;
|
||||
/* One domain */
|
||||
uint32_t seqnum;
|
||||
|
||||
/* All domains */
|
||||
int num_domains;
|
||||
NTSTATUS *statuses;
|
||||
struct winbindd_domain **domains;
|
||||
uint32_t *seqnums;
|
||||
};
|
||||
|
||||
static void winbindd_show_sequence_done_one(struct tevent_req *subreq);
|
||||
static void winbindd_show_sequence_done_all(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct winbindd_cli_state *cli,
|
||||
struct winbindd_request *request)
|
||||
{
|
||||
struct tevent_req *req, *subreq;
|
||||
struct winbindd_show_sequence_state *state;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct winbindd_show_sequence_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->one_domain = false;
|
||||
state->domains = NULL;
|
||||
state->statuses = NULL;
|
||||
state->seqnums = NULL;
|
||||
|
||||
/* Ensure null termination */
|
||||
request->domain_name[sizeof(request->domain_name)-1]='\0';
|
||||
|
||||
DEBUG(3, ("show_sequence %s\n", request->domain_name));
|
||||
|
||||
if (request->domain_name[0] != '\0') {
|
||||
struct winbindd_domain *domain;
|
||||
|
||||
state->one_domain = true;
|
||||
|
||||
domain = find_domain_from_name_noinit(
|
||||
request->domain_name);
|
||||
if (domain == NULL) {
|
||||
tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
subreq = wb_seqnum_send(state, ev, domain);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(
|
||||
subreq, winbindd_show_sequence_done_one, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
subreq = wb_seqnums_send(state, ev);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, winbindd_show_sequence_done_all, req);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void winbindd_show_sequence_done_one(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = wb_seqnum_recv(subreq, &state->seqnum);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
static void winbindd_show_sequence_done_all(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = wb_seqnums_recv(subreq, state, &state->num_domains,
|
||||
&state->domains, &state->statuses,
|
||||
&state->seqnums);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
|
||||
struct winbindd_response *response)
|
||||
{
|
||||
struct winbindd_show_sequence_state *state = tevent_req_data(
|
||||
req, struct winbindd_show_sequence_state);
|
||||
NTSTATUS status;
|
||||
char *extra_data;
|
||||
int i;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (state->one_domain) {
|
||||
response->data.sequence_number = state->seqnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
extra_data = talloc_strdup(response, "");
|
||||
if (extra_data == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i=0; i<state->num_domains; i++) {
|
||||
if (!NT_STATUS_IS_OK(state->statuses[i])
|
||||
|| (state->seqnums[i] == DOM_SEQUENCE_NONE)) {
|
||||
extra_data = talloc_asprintf_append_buffer(
|
||||
extra_data, "%s : DISCONNECTED\n",
|
||||
state->domains[i]->name);
|
||||
} else {
|
||||
extra_data = talloc_asprintf_append_buffer(
|
||||
extra_data, "%s : %d\n",
|
||||
state->domains[i]->name,
|
||||
(int)state->seqnums[i]);
|
||||
}
|
||||
if (extra_data == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
response->extra_data.data = extra_data;
|
||||
response->length += talloc_get_size(extra_data);
|
||||
return NT_STATUS_OK;
|
||||
}
|
@ -302,19 +302,6 @@ static NTSTATUS add_trusted_domain(const char *domain_name,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
bool set_routing_domain(struct winbindd_domain *domain,
|
||||
struct winbindd_domain *routing_domain)
|
||||
{
|
||||
if (domain->routing_domain == NULL) {
|
||||
domain->routing_domain = routing_domain;
|
||||
return true;
|
||||
}
|
||||
if (domain->routing_domain != routing_domain) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||
struct info3_text *info3,
|
||||
struct info6_text *info6)
|
||||
|
@ -208,8 +208,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
||||
wb_lookupusergroups.c
|
||||
wb_getpwsid.c
|
||||
wb_gettoken.c
|
||||
wb_seqnum.c
|
||||
wb_seqnums.c
|
||||
wb_group_members.c
|
||||
wb_alias_members.c
|
||||
wb_getgrsid.c
|
||||
@ -231,7 +229,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
||||
winbindd_getsidaliases.c
|
||||
winbindd_getuserdomgroups.c
|
||||
winbindd_getgroups.c
|
||||
winbindd_show_sequence.c
|
||||
winbindd_getgrgid.c
|
||||
winbindd_getgrnam.c
|
||||
winbindd_getusersids.c
|
||||
|
@ -736,162 +736,6 @@ static bool torture_winbind_struct_list_groups(struct torture_context *torture)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct torture_domain_sequence {
|
||||
const char *netbios_name;
|
||||
uint32_t seq;
|
||||
};
|
||||
|
||||
static bool get_sequence_numbers(struct torture_context *torture,
|
||||
struct torture_domain_sequence **seqs)
|
||||
{
|
||||
struct winbindd_request req;
|
||||
struct winbindd_response rep;
|
||||
const char *extra_data;
|
||||
char line[256];
|
||||
uint32_t count = 0;
|
||||
struct torture_domain_sequence *s = NULL;
|
||||
|
||||
ZERO_STRUCT(req);
|
||||
ZERO_STRUCT(rep);
|
||||
|
||||
DO_STRUCT_REQ_REP(WINBINDD_SHOW_SEQUENCE, &req, &rep);
|
||||
|
||||
extra_data = (char *)rep.extra_data.data;
|
||||
torture_assert(torture, extra_data, "NULL sequence list");
|
||||
|
||||
while (next_token(&extra_data, line, "\n", sizeof(line))) {
|
||||
char *p, *lp;
|
||||
uint32_t seq;
|
||||
|
||||
s = talloc_realloc(torture, s, struct torture_domain_sequence,
|
||||
count + 2);
|
||||
ZERO_STRUCT(s[count+1]);
|
||||
|
||||
lp = line;
|
||||
p = strchr(lp, ' ');
|
||||
torture_assert(torture, p, "invalid line format");
|
||||
*p = 0;
|
||||
s[count].netbios_name = talloc_strdup(s, lp);
|
||||
|
||||
lp = p+1;
|
||||
torture_assert(torture, strncmp(lp, ": ", 2) == 0,
|
||||
"invalid line format");
|
||||
lp += 2;
|
||||
if (strcmp(lp, "DISCONNECTED") == 0) {
|
||||
seq = (uint32_t)-1;
|
||||
} else {
|
||||
seq = (uint32_t)strtol(lp, &p, 10);
|
||||
torture_assert(torture, (*p == '\0'),
|
||||
"invalid line format");
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"sequence number -1 encountered");
|
||||
}
|
||||
s[count].seq = seq;
|
||||
|
||||
count++;
|
||||
}
|
||||
SAFE_FREE(rep.extra_data.data);
|
||||
|
||||
torture_assert(torture, count >= 2, "The list of domain sequence "
|
||||
"numbers should contain 2 entries");
|
||||
|
||||
*seqs = s;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_winbind_struct_show_sequence(struct torture_context *torture)
|
||||
{
|
||||
bool ok;
|
||||
uint32_t i;
|
||||
struct torture_trust_domain *domlist = NULL;
|
||||
struct torture_domain_sequence *s = NULL;
|
||||
|
||||
torture_comment(torture, "Running WINBINDD_SHOW_SEQUENCE (struct based)\n");
|
||||
|
||||
ok = get_sequence_numbers(torture, &s);
|
||||
torture_assert(torture, ok, "failed to get list of sequence numbers");
|
||||
|
||||
ok = get_trusted_domains(torture, &domlist);
|
||||
torture_assert(torture, ok, "failed to get trust list");
|
||||
|
||||
for (i=0; domlist[i].netbios_name; i++) {
|
||||
struct winbindd_request req;
|
||||
struct winbindd_response rep;
|
||||
uint32_t seq;
|
||||
|
||||
torture_assert(torture, s[i].netbios_name,
|
||||
"more domains received in second run");
|
||||
torture_assert_str_equal(torture, domlist[i].netbios_name,
|
||||
s[i].netbios_name,
|
||||
"inconsistent order of domain lists");
|
||||
|
||||
ZERO_STRUCT(req);
|
||||
ZERO_STRUCT(rep);
|
||||
fstrcpy(req.domain_name, domlist[i].netbios_name);
|
||||
|
||||
ok = true;
|
||||
DO_STRUCT_REQ_REP_EXT(WINBINDD_SHOW_SEQUENCE, &req, &rep,
|
||||
NSS_STATUS_SUCCESS,
|
||||
false, ok = false,
|
||||
"WINBINDD_SHOW_SEQUENCE");
|
||||
if (ok == false) {
|
||||
torture_warning(torture,
|
||||
"WINBINDD_SHOW_SEQUENCE on "
|
||||
"domain %s failed\n",
|
||||
req.domain_name);
|
||||
|
||||
/*
|
||||
* Only fail for the first two domain that we
|
||||
* check specially below, otherwise we fail on
|
||||
* trusts generated by the LSA torture test
|
||||
* that do not really exist.
|
||||
*/
|
||||
if (i > 1) {
|
||||
/*
|
||||
* Do not confirm the sequence numbers
|
||||
* below
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
torture_comment(torture,
|
||||
"Full trust list for "
|
||||
"WINBINDD_SHOW_SEQUENCE "
|
||||
"test was:\n");
|
||||
for (i=0; domlist[i].netbios_name; i++) {
|
||||
torture_comment(torture,
|
||||
"%s\n",
|
||||
domlist[i].netbios_name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
seq = rep.data.sequence_number;
|
||||
|
||||
if (i == 0) {
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"BUILTIN domain disconnected");
|
||||
} else if (i == 1) {
|
||||
torture_assert(torture, (seq != (uint32_t)-1),
|
||||
"local domain disconnected");
|
||||
}
|
||||
|
||||
|
||||
if (seq == (uint32_t)-1) {
|
||||
torture_comment(torture, " * %s : DISCONNECTED\n",
|
||||
req.domain_name);
|
||||
} else {
|
||||
torture_comment(torture, " * %s : %d\n",
|
||||
req.domain_name, seq);
|
||||
}
|
||||
torture_assert(torture, (seq >= s[i].seq),
|
||||
"illegal sequence number encountered");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_winbind_struct_setpwent(struct torture_context *torture)
|
||||
{
|
||||
struct winbindd_request req;
|
||||
@ -1174,7 +1018,6 @@ struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx)
|
||||
torture_suite_add_simple_test(suite, "dsgetdcname", torture_winbind_struct_dsgetdcname);
|
||||
torture_suite_add_simple_test(suite, "list_users", torture_winbind_struct_list_users);
|
||||
torture_suite_add_simple_test(suite, "list_groups", torture_winbind_struct_list_groups);
|
||||
torture_suite_add_simple_test(suite, "show_sequence", torture_winbind_struct_show_sequence);
|
||||
torture_suite_add_simple_test(suite, "setpwent", torture_winbind_struct_setpwent);
|
||||
torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent);
|
||||
torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent);
|
||||
|
Loading…
x
Reference in New Issue
Block a user