mirror of
https://github.com/samba-team/samba.git
synced 2025-01-18 06:04:06 +03:00
Compare commits
54 Commits
86cdaf5a2e
...
e0aab377bd
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
e37e4d16e9 | ||
|
02d4f58a2f | ||
|
94c9a99c56 | ||
|
1a089a16c4 | ||
|
0a9adc85e7 | ||
|
0a5da82f75 | ||
|
7b73c574d9 |
@ -1548,12 +1548,33 @@ to show in the result.
|
|||||||
<title>ADS KEYTAB <replaceable>CREATE</replaceable></title>
|
<title>ADS KEYTAB <replaceable>CREATE</replaceable></title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Creates a new keytab file if one doesn't exist with default entries. Default
|
Since Samba 4.21.0, keytab file is created as specified in <smbconfoption
|
||||||
entries are kerberos principals created from the machinename of the
|
name="sync machine password to keytab"/>. The keytab is created only for
|
||||||
client, the UPN (if it exists) and any Windows SPN(s) associated with the
|
<smbconfoption name="kerberos method">secrets only</smbconfoption> and
|
||||||
computer AD account for the client. If a keytab file already exists then only
|
<smbconfoption name="kerberos method">secrets and keytab</smbconfoption>. With
|
||||||
missing kerberos principals from the default entries are added. No changes
|
the smb.conf default values for <smbconfoption name="kerberos method"> secrets
|
||||||
are made to the computer AD account.
|
only</smbconfoption> and <smbconfoption name="sync machine password to keytab"/>
|
||||||
|
(default is empty) the keytab is not generated at all. Keytab with a default
|
||||||
|
name and SPNs synced from AD is created for <smbconfoption name="kerberos
|
||||||
|
method">secrets and keytab</smbconfoption> if <smbconfoption name="sync machine
|
||||||
|
password to keytab"/> is missing.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Till Samba 4.20.0, two more entries were created by default: the machinename of
|
||||||
|
the client (ending with '$') and the UPN (host/domain@REALM). If these two
|
||||||
|
entries are still needed, each must be specified in an own keytab file.
|
||||||
|
Example below will generate three keytab files that contain SPNs synced from
|
||||||
|
AD, host UPN and machine$ SPN:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
<smbconfoption name="sync machine password to keytab">
|
||||||
|
/etc/krb5.keytab0:sync_spns:machine_password,
|
||||||
|
/etc/krb5.keytab1:spns=host/smb.com@SMB.COM:machine_password,
|
||||||
|
/etc/krb5.keytab2:account_name:machine_password
|
||||||
|
</smbconfoption>
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
No changes are made to the computer AD account.
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
|
@ -62,7 +62,10 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>This module is stackable.</para>
|
<para> This module is not fully stackable. It can be combined with other
|
||||||
|
modules, but should be the last module in the <command>vfs objects</command>
|
||||||
|
list. It directly access the files in the OS filesystem.
|
||||||
|
</para>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@
|
|||||||
<arg choice="opt">--remove-uid-mapping uid,sid</arg>
|
<arg choice="opt">--remove-uid-mapping uid,sid</arg>
|
||||||
<arg choice="opt">-s sid</arg>
|
<arg choice="opt">-s sid</arg>
|
||||||
<arg choice="opt">--separator</arg>
|
<arg choice="opt">--separator</arg>
|
||||||
<arg choice="opt">--sequence</arg>
|
|
||||||
<arg choice="opt">--set-auth-user user%password</arg>
|
<arg choice="opt">--set-auth-user user%password</arg>
|
||||||
<arg choice="opt">--set-gid-mapping gid,sid</arg>
|
<arg choice="opt">--set-gid-mapping gid,sid</arg>
|
||||||
<arg choice="opt">--set-uid-mapping uid,sid</arg>
|
<arg choice="opt">--set-uid-mapping uid,sid</arg>
|
||||||
@ -458,13 +457,6 @@
|
|||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>--sequence</term>
|
|
||||||
<listitem><para>This command has been deprecated. Please use
|
|
||||||
the --online-status option instead.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>--set-auth-user <replaceable>username%password</replaceable></term>
|
<term>--set-auth-user <replaceable>username%password</replaceable></term>
|
||||||
<listitem><para>Store username and password used by <citerefentry>
|
<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)) {
|
if (security_token_has_sid(token, sd->owner_sid)) {
|
||||||
switch (implicit_owner_rights) {
|
switch (implicit_owner_rights) {
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||||
granted |= SEC_STD_WRITE_DAC;
|
granted |= (SEC_STD_READ_CONTROL |
|
||||||
FALL_THROUGH;
|
SEC_STD_WRITE_DAC);
|
||||||
|
break;
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||||
granted |= SEC_STD_READ_CONTROL;
|
granted |= SEC_STD_READ_CONTROL;
|
||||||
break;
|
break;
|
||||||
@ -282,8 +283,8 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
|
|||||||
if (am_owner && !have_owner_rights_ace) {
|
if (am_owner && !have_owner_rights_ace) {
|
||||||
switch (implicit_owner_rights) {
|
switch (implicit_owner_rights) {
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||||
granted |= SEC_STD_WRITE_DAC;
|
granted |= (SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC);
|
||||||
FALL_THROUGH;
|
break;
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||||
granted |= SEC_STD_READ_CONTROL;
|
granted |= SEC_STD_READ_CONTROL;
|
||||||
break;
|
break;
|
||||||
@ -436,8 +437,9 @@ static NTSTATUS se_access_check_implicit_owner(const struct security_descriptor
|
|||||||
if (am_owner && !have_owner_rights_ace) {
|
if (am_owner && !have_owner_rights_ace) {
|
||||||
switch (implicit_owner_rights) {
|
switch (implicit_owner_rights) {
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||||
FALL_THROUGH;
|
SEC_STD_READ_CONTROL);
|
||||||
|
break;
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||||
break;
|
break;
|
||||||
@ -596,10 +598,10 @@ NTSTATUS se_file_access_check(const struct security_descriptor *sd,
|
|||||||
access_desired |= SEC_RIGHTS_PRIV_RESTORE;
|
access_desired |= SEC_RIGHTS_PRIV_RESTORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(10,("se_file_access_check: MAX desired = 0x%x "
|
DBG_DEBUG("MAX desired = 0x%0" PRIx32 " mapped to 0x%" PRIx32
|
||||||
"mapped to 0x%x\n",
|
"\n ",
|
||||||
orig_access_desired,
|
orig_access_desired,
|
||||||
access_desired));
|
access_desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = se_access_check_implicit_owner(sd,
|
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)) {
|
security_token_has_sid(token, sd->owner_sid)) {
|
||||||
switch (implicit_owner_rights) {
|
switch (implicit_owner_rights) {
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_AND_WRITE_DAC_RIGHTS:
|
||||||
bits_remaining &= ~SEC_STD_WRITE_DAC;
|
bits_remaining &= ~(SEC_STD_WRITE_DAC |
|
||||||
FALL_THROUGH;
|
SEC_STD_READ_CONTROL);
|
||||||
|
break;
|
||||||
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
case IMPLICIT_OWNER_READ_CONTROL_RIGHTS:
|
||||||
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
bits_remaining &= ~SEC_STD_READ_CONTROL;
|
||||||
break;
|
break;
|
||||||
|
@ -109,26 +109,23 @@ static bool check_integer_range(const struct ace_condition_token *tok)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t pull_integer(uint8_t *data,
|
||||||
static ssize_t pull_integer(TALLOC_CTX *mem_ctx,
|
size_t length,
|
||||||
uint8_t *data, size_t length,
|
|
||||||
struct ace_condition_int *tok)
|
struct ace_condition_int *tok)
|
||||||
{
|
{
|
||||||
ssize_t bytes_used;
|
size_t consumed;
|
||||||
enum ndr_err_code ndr_err;
|
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);
|
ndr_err = ndr_pull_struct_blob_noalloc(
|
||||||
if (ndr == NULL) {
|
data,
|
||||||
return -1;
|
length,
|
||||||
}
|
tok,
|
||||||
ndr_err = ndr_pull_ace_condition_int(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
|
(ndr_pull_flags_fn_t)ndr_pull_ace_condition_int,
|
||||||
|
&consumed);
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
TALLOC_FREE(ndr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bytes_used = ndr->offset;
|
return consumed;
|
||||||
TALLOC_FREE(ndr);
|
|
||||||
return bytes_used;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t push_integer(uint8_t *data, size_t available,
|
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_INT16:
|
||||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||||
consumed = pull_integer(mem_ctx,
|
consumed = pull_integer(el_data,
|
||||||
el_data,
|
|
||||||
available,
|
available,
|
||||||
&el->data.int64);
|
&el->data.int64);
|
||||||
ok = check_integer_range(el);
|
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.
|
* zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
|
||||||
*/
|
*/
|
||||||
ssize_t i;
|
size_t i;
|
||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
return -1;
|
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_INT16:
|
||||||
case CONDITIONAL_ACE_TOKEN_INT32:
|
case CONDITIONAL_ACE_TOKEN_INT32:
|
||||||
case CONDITIONAL_ACE_TOKEN_INT64:
|
case CONDITIONAL_ACE_TOKEN_INT64:
|
||||||
consumed = pull_integer(program,
|
consumed = pull_integer(tok_data,
|
||||||
tok_data,
|
|
||||||
available,
|
available,
|
||||||
&tok->data.int64);
|
&tok->data.int64);
|
||||||
ok = check_integer_range(tok);
|
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)
|
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) {
|
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 type: SEC_ACE_OBJECT_TYPE_PRESENT\n");
|
||||||
printf("Object GUID: %s\n", str);
|
printf("Object GUID: %s\n",
|
||||||
talloc_free(str);
|
GUID_buf_string(&object->type.type, &buf));
|
||||||
}
|
}
|
||||||
if (object->flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
|
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 type: SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT\n");
|
||||||
printf("Object GUID: %s\n", str);
|
printf("Object GUID: %s\n",
|
||||||
talloc_free(str);
|
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;
|
uint32_t i;
|
||||||
|
|
||||||
printf("\tACL\tNum ACEs:\t%u\trevision:\t%x\n",
|
printf("\tACL\tNum ACEs:\t%" PRIu32 "\trevision:\t%x\n",
|
||||||
sec_acl->num_aces, sec_acl->revision);
|
sec_acl->num_aces,
|
||||||
|
sec_acl->revision);
|
||||||
printf("\t---\n");
|
printf("\t---\n");
|
||||||
|
|
||||||
if (sec_acl->size != 0 && sec_acl->num_aces != 0) {
|
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) {
|
if (idx < 0) {
|
||||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||||
} else if (idx > acl->num_aces) {
|
}
|
||||||
|
if (idx > acl->num_aces) {
|
||||||
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
|
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)
|
struct security_token *security_token_duplicate(TALLOC_CTX *mem_ctx, const struct security_token *src)
|
||||||
{
|
{
|
||||||
TALLOC_CTX *frame = NULL;
|
|
||||||
struct security_token *dst = NULL;
|
struct security_token *dst = NULL;
|
||||||
DATA_BLOB blob;
|
|
||||||
enum ndr_err_code ndr_err;
|
enum ndr_err_code ndr_err;
|
||||||
|
|
||||||
if (src == NULL) {
|
if (src == NULL) {
|
||||||
return 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);
|
dst = talloc_zero(mem_ctx, struct security_token);
|
||||||
if (dst == NULL) {
|
if (dst == NULL) {
|
||||||
DBG_ERR("talloc failed\n");
|
DBG_ERR("talloc failed\n");
|
||||||
TALLOC_FREE(frame);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ndr_err = ndr_pull_struct_blob(
|
ndr_err = ndr_deepcopy_struct(security_token, src, dst, dst);
|
||||||
&blob,
|
|
||||||
dst,
|
|
||||||
dst,
|
|
||||||
(ndr_pull_flags_fn_t)ndr_pull_security_token);
|
|
||||||
|
|
||||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
DBG_ERR("Failed to duplicate security_token ndr_pull_security_token "
|
DBG_ERR("Failed to duplicate security_token: %s\n",
|
||||||
"failed: %s\n",
|
|
||||||
ndr_errstr(ndr_err));
|
ndr_errstr(ndr_err));
|
||||||
TALLOC_FREE(dst);
|
TALLOC_FREE(dst);
|
||||||
TALLOC_FREE(frame);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TALLOC_FREE(frame);
|
|
||||||
return dst;
|
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)
|
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) {
|
*dst = (struct dom_sid) {
|
||||||
.sid_rev_num = src->sid_rev_num,
|
.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));
|
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];
|
dst->sub_auths[i] = src->sub_auths[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,24 +36,6 @@ testfail()
|
|||||||
fi
|
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"
|
KRB5CCNAME_PATH="$PREFIX/test_wbinfo_krb5ccache"
|
||||||
rm -f $KRB5CCNAME_PATH
|
rm -f $KRB5CCNAME_PATH
|
||||||
|
|
||||||
@ -218,9 +200,6 @@ else
|
|||||||
failed=$(expr $failed + 1)
|
failed=$(expr $failed + 1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# this does not work
|
|
||||||
knownfail "wbinfo --sequence against $TARGET" $wbinfo --sequence
|
|
||||||
|
|
||||||
# this is stubbed out now
|
# this is stubbed out now
|
||||||
testit "wbinfo -D against $TARGET" $wbinfo -D $DOMAIN || failed=$(expr $failed + 1)
|
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;
|
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 */
|
/* show sequence numbers */
|
||||||
static bool wbinfo_show_onlinestatus(const char *domain)
|
static bool wbinfo_show_onlinestatus(const char *domain)
|
||||||
{
|
{
|
||||||
@ -2295,7 +2287,6 @@ enum {
|
|||||||
OPT_SET_AUTH_USER = 1000,
|
OPT_SET_AUTH_USER = 1000,
|
||||||
OPT_GET_AUTH_USER,
|
OPT_GET_AUTH_USER,
|
||||||
OPT_DOMAIN_NAME,
|
OPT_DOMAIN_NAME,
|
||||||
OPT_SEQUENCE,
|
|
||||||
OPT_GETDCNAME,
|
OPT_GETDCNAME,
|
||||||
OPT_DSGETDCNAME,
|
OPT_DSGETDCNAME,
|
||||||
OPT_DC_INFO,
|
OPT_DC_INFO,
|
||||||
@ -2581,12 +2572,6 @@ int main(int argc, const char **argv, char **envp)
|
|||||||
.val = OPT_LIST_OWN_DOMAIN,
|
.val = OPT_LIST_OWN_DOMAIN,
|
||||||
.descrip = "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",
|
.longName = "online-status",
|
||||||
.argInfo = POPT_ARG_NONE,
|
.argInfo = POPT_ARG_NONE,
|
||||||
@ -3099,13 +3084,6 @@ int main(int argc, const char **argv, char **envp)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case OPT_ONLINESTATUS:
|
||||||
if (!wbinfo_show_onlinestatus(opt_domain_name)) {
|
if (!wbinfo_show_onlinestatus(opt_domain_name)) {
|
||||||
d_fprintf(stderr,
|
d_fprintf(stderr,
|
||||||
|
@ -63,8 +63,9 @@ typedef char fstring[FSTRING_LEN];
|
|||||||
* 31: added "client_name" to the request
|
* 31: added "client_name" to the request
|
||||||
* 32: added "traceid" to the request
|
* 32: added "traceid" to the request
|
||||||
* removed WINBINDD_INIT_CONNECTION
|
* 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.
|
/* 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
|
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_DSGETDCNAME, /* Issue a DsGetDCName Request */
|
||||||
WINBINDD_DC_INFO, /* Which DC are we connected to? */
|
WINBINDD_DC_INFO, /* Which DC are we connected to? */
|
||||||
|
|
||||||
WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */
|
|
||||||
|
|
||||||
/* WINS commands */
|
/* WINS commands */
|
||||||
|
|
||||||
WINBINDD_WINS_BYIP,
|
WINBINDD_WINS_BYIP,
|
||||||
|
@ -2783,6 +2783,9 @@ sub provision($$)
|
|||||||
my $recycle_shrdir="$shrdir/recycle";
|
my $recycle_shrdir="$shrdir/recycle";
|
||||||
push(@dirs,$recycle_shrdir);
|
push(@dirs,$recycle_shrdir);
|
||||||
|
|
||||||
|
my $recycle_shrdir2="$shrdir/recycle2";
|
||||||
|
push(@dirs,$recycle_shrdir2);
|
||||||
|
|
||||||
my $fakedircreatetimes_shrdir="$shrdir/fakedircreatetimes";
|
my $fakedircreatetimes_shrdir="$shrdir/fakedircreatetimes";
|
||||||
push(@dirs,$fakedircreatetimes_shrdir);
|
push(@dirs,$fakedircreatetimes_shrdir);
|
||||||
|
|
||||||
@ -3718,6 +3721,15 @@ sub provision($$)
|
|||||||
recycle : exclude = *.tmp
|
recycle : exclude = *.tmp
|
||||||
recycle : directory_mode = 755
|
recycle : directory_mode = 755
|
||||||
|
|
||||||
|
[recycle2]
|
||||||
|
copy = tmp
|
||||||
|
path = $recycle_shrdir2
|
||||||
|
vfs objects = recycle crossrename
|
||||||
|
recycle : repository = .trash
|
||||||
|
recycle : exclude = *.tmp
|
||||||
|
recycle : directory_mode = 755
|
||||||
|
wide links = yes
|
||||||
|
|
||||||
[fakedircreatetimes]
|
[fakedircreatetimes]
|
||||||
copy = tmp
|
copy = tmp
|
||||||
path = $fakedircreatetimes_shrdir
|
path = $fakedircreatetimes_shrdir
|
||||||
|
@ -2584,11 +2584,8 @@ static struct adouble *ad_get_internal(TALLOC_CTX *ctx,
|
|||||||
int mode;
|
int mode;
|
||||||
|
|
||||||
if (fsp != NULL) {
|
if (fsp != NULL) {
|
||||||
if (fsp_is_alternate_stream(fsp)) {
|
struct files_struct *meta_fsp = metadata_fsp(fsp);
|
||||||
smb_fname = fsp->base_fsp->fsp_name;
|
smb_fname = meta_fsp->fsp_name;
|
||||||
} else {
|
|
||||||
smb_fname = fsp->fsp_name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(10, ("ad_get(%s) called for %s\n",
|
DEBUG(10, ("ad_get(%s) called for %s\n",
|
||||||
|
@ -274,23 +274,20 @@ static int connect_acl_tdb(struct vfs_handle_struct *handle,
|
|||||||
|
|
||||||
if (config->ignore_system_acls) {
|
if (config->ignore_system_acls) {
|
||||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||||
char *create_mask_str = NULL;
|
|
||||||
|
|
||||||
if ((create_mask & 0666) != 0666) {
|
if ((create_mask & 0666) != 0666) {
|
||||||
|
char create_mask_str[16];
|
||||||
|
|
||||||
create_mask |= 0666;
|
create_mask |= 0666;
|
||||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
snprintf(create_mask_str,
|
||||||
|
sizeof(create_mask_str),
|
||||||
|
"0%o",
|
||||||
create_mask);
|
create_mask);
|
||||||
if (create_mask_str == NULL) {
|
|
||||||
DBG_ERR("talloc_asprintf failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||||
|
|
||||||
lp_do_parameter (SNUM(handle->conn),
|
lp_do_parameter (SNUM(handle->conn),
|
||||||
"create mask", create_mask_str);
|
"create mask", create_mask_str);
|
||||||
|
|
||||||
TALLOC_FREE(create_mask_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
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) {
|
if (config->ignore_system_acls) {
|
||||||
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
mode_t create_mask = lp_create_mask(SNUM(handle->conn));
|
||||||
char *create_mask_str = NULL;
|
|
||||||
|
|
||||||
if ((create_mask & 0666) != 0666) {
|
if ((create_mask & 0666) != 0666) {
|
||||||
|
char create_mask_str[16];
|
||||||
|
|
||||||
create_mask |= 0666;
|
create_mask |= 0666;
|
||||||
create_mask_str = talloc_asprintf(handle, "0%o",
|
snprintf(create_mask_str,
|
||||||
|
sizeof(create_mask_str),
|
||||||
|
"0%o",
|
||||||
create_mask);
|
create_mask);
|
||||||
if (create_mask_str == NULL) {
|
|
||||||
DBG_ERR("talloc_asprintf failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
|
||||||
|
|
||||||
lp_do_parameter(SNUM(handle->conn),
|
lp_do_parameter(SNUM(handle->conn),
|
||||||
"create mask", create_mask_str);
|
"create mask",
|
||||||
|
create_mask_str);
|
||||||
TALLOC_FREE(create_mask_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_NOTICE("setting 'directory mask = 0777', "
|
DBG_NOTICE("setting 'directory mask = 0777', "
|
||||||
|
@ -54,10 +54,12 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle,
|
|||||||
struct files_struct *dstfsp,
|
struct files_struct *dstfsp,
|
||||||
const struct smb_filename *dest)
|
const struct smb_filename *dest)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status = NT_STATUS_OK;
|
||||||
struct smb_filename *full_fname_src = NULL;
|
|
||||||
struct smb_filename *full_fname_dst = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
off_t off;
|
||||||
|
int ifd = -1;
|
||||||
|
int ofd = -1;
|
||||||
|
struct timespec ts[2];
|
||||||
|
|
||||||
if (!VALID_STAT(source->st)) {
|
if (!VALID_STAT(source->st)) {
|
||||||
status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
@ -79,64 +81,105 @@ static NTSTATUS copy_reg(vfs_handle_struct *handle,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
|
|
||||||
srcfsp,
|
|
||||||
source);
|
|
||||||
if (full_fname_src == NULL) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
full_fname_dst = full_path_from_dirfsp_atname(talloc_tos(),
|
|
||||||
dstfsp,
|
|
||||||
dest);
|
|
||||||
if (full_fname_dst == NULL) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = SMB_VFS_NEXT_UNLINKAT(handle,
|
ret = SMB_VFS_NEXT_UNLINKAT(handle,
|
||||||
dstfsp,
|
dstfsp,
|
||||||
dest,
|
dest,
|
||||||
0);
|
0);
|
||||||
if (ret == -1) {
|
if (ret == -1 && errno != ENOENT) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifd = openat(fsp_get_pathref_fd(srcfsp),
|
||||||
|
source->base_name,
|
||||||
|
O_RDONLY,
|
||||||
|
0);
|
||||||
|
if (ifd < 0) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofd = openat(fsp_get_pathref_fd(dstfsp),
|
||||||
|
dest->base_name,
|
||||||
|
O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW,
|
||||||
|
0600);
|
||||||
|
if (ofd < 0) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
off = transfer_file(ifd, ofd, source->st.st_ex_size);
|
||||||
|
if (off == -1) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fchown(ofd, source->st.st_ex_uid, source->st.st_ex_gid);
|
||||||
|
if (ret == -1 && errno != EPERM) {
|
||||||
status = map_nt_error_from_unix(errno);
|
status = map_nt_error_from_unix(errno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy_internals() takes attribute values from the NTrename call.
|
* fchown turns off set[ug]id bits for non-root,
|
||||||
*
|
* so do the chmod last.
|
||||||
* From MS-CIFS:
|
|
||||||
*
|
|
||||||
* "If the attribute is 0x0000, then only normal files are renamed.
|
|
||||||
* If the system file or hidden attributes are specified, then the
|
|
||||||
* rename is inclusive of both special types."
|
|
||||||
*/
|
*/
|
||||||
status = copy_internals(talloc_tos(),
|
ret = fchmod(ofd, source->st.st_ex_mode & 07777);
|
||||||
handle->conn,
|
if (ret == -1 && errno != EPERM) {
|
||||||
NULL,
|
|
||||||
srcfsp, /* src_dirfsp */
|
|
||||||
full_fname_src,
|
|
||||||
dstfsp, /* dst_dirfsp */
|
|
||||||
full_fname_dst,
|
|
||||||
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = SMB_VFS_NEXT_UNLINKAT(handle,
|
|
||||||
srcfsp,
|
|
||||||
source,
|
|
||||||
0);
|
|
||||||
if (ret == -1) {
|
|
||||||
status = map_nt_error_from_unix(errno);
|
status = map_nt_error_from_unix(errno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
/* Try to copy the old file's modtime and access time. */
|
||||||
|
ts[0] = source->st.st_ex_atime;
|
||||||
|
ts[1] = source->st.st_ex_mtime;
|
||||||
|
ret = futimens(ofd, ts);
|
||||||
|
if (ret == -1) {
|
||||||
|
DBG_DEBUG("Updating the time stamp on destinaton '%s' failed "
|
||||||
|
"with '%s'. Rename operation can continue.\n",
|
||||||
|
dest->base_name,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = close(ifd);
|
||||||
|
if (ret == -1) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ifd = -1;
|
||||||
|
|
||||||
|
ret = close(ofd);
|
||||||
|
if (ret == -1) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ofd = -1;
|
||||||
|
|
||||||
|
ret = SMB_VFS_NEXT_UNLINKAT(handle, srcfsp, source, 0);
|
||||||
|
if (ret == -1) {
|
||||||
|
status = map_nt_error_from_unix(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ifd != -1) {
|
||||||
|
ret = close(ifd);
|
||||||
|
if (ret == -1) {
|
||||||
|
DBG_DEBUG("Failed to close %s (%d): %s.\n",
|
||||||
|
source->base_name,
|
||||||
|
ifd,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ofd != -1) {
|
||||||
|
ret = close(ofd);
|
||||||
|
if (ret == -1) {
|
||||||
|
DBG_DEBUG("Failed to close %s (%d): %s.\n",
|
||||||
|
dest->base_name,
|
||||||
|
ofd,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TALLOC_FREE(full_fname_src);
|
|
||||||
TALLOC_FREE(full_fname_dst);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +213,7 @@ static int crossrename_renameat(vfs_handle_struct *handle,
|
|||||||
smb_fname_src,
|
smb_fname_src,
|
||||||
dstfsp,
|
dstfsp,
|
||||||
smb_fname_dst);
|
smb_fname_dst);
|
||||||
|
result = 0;
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
errno = map_errno_from_nt_status(status);
|
errno = map_errno_from_nt_status(status);
|
||||||
result = -1;
|
result = -1;
|
||||||
|
@ -829,12 +829,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
|||||||
goto error_exit;
|
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(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
NULL, /* req */
|
NULL, /* req */
|
||||||
@ -891,13 +885,6 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
|
|||||||
goto error_exit;
|
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(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
NULL, /* req */
|
NULL, /* req */
|
||||||
@ -1110,15 +1097,6 @@ static uint32_t get_correct_cversion(const struct auth_session_info *session_inf
|
|||||||
goto error_exit;
|
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(
|
nt_status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
NULL, /* req */
|
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)
|
static void display_sam_dom_info_3(struct samr_DomInfo3 *info3)
|
||||||
{
|
{
|
||||||
printf("Force Logoff:\t%d\n",
|
printf("Force Logoff:\t%" PRIu64 "\n",
|
||||||
(int)nt_time_to_unix_abs(&info3->force_logoff_time));
|
(uint64_t)nt_time_to_unix_abs(&info3->force_logoff_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_sam_dom_info_4(struct samr_DomOEMInformation *oem)
|
static void display_sam_dom_info_4(struct samr_DomOEMInformation *oem)
|
||||||
|
@ -29,7 +29,8 @@ export SAMBA_DEPRECATED_SUPPRESS
|
|||||||
|
|
||||||
# Define the test environment/filenames.
|
# Define the test environment/filenames.
|
||||||
#
|
#
|
||||||
share_test_dir="$LOCAL_PATH"
|
share_test_dir="$LOCAL_PATH/recycle"
|
||||||
|
share_test_dir2="$LOCAL_PATH/recycle2"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Cleanup function.
|
# Cleanup function.
|
||||||
@ -43,6 +44,13 @@ do_cleanup()
|
|||||||
rm -f testfile2.tmp
|
rm -f testfile2.tmp
|
||||||
rm -rf .trash
|
rm -rf .trash
|
||||||
)
|
)
|
||||||
|
(
|
||||||
|
#subshell.
|
||||||
|
cd "$share_test_dir2" || return
|
||||||
|
rm -f testfile3
|
||||||
|
rm -f testfile4.tmp
|
||||||
|
rm -rf .trash
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -50,6 +58,25 @@ do_cleanup()
|
|||||||
#
|
#
|
||||||
do_cleanup
|
do_cleanup
|
||||||
|
|
||||||
|
# Setup .trash on a different filesystem to test crossrename
|
||||||
|
# /tmp or /dev/shm should provide tmpfs
|
||||||
|
#
|
||||||
|
for T in /tmp /dev/shm
|
||||||
|
do
|
||||||
|
if df --portability --print-type $T 2>/dev/null | grep -q tmpfs; then
|
||||||
|
TRASHDIR=$T
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z $TRASHDIR ]; then
|
||||||
|
echo "No tmpfs filesystem found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TRASHDIR=$(mktemp -d /$TRASHDIR/.trash_XXXXXX)
|
||||||
|
chmod 0755 $TRASHDIR
|
||||||
|
ln -s $TRASHDIR $share_test_dir2/.trash
|
||||||
|
|
||||||
test_recycle()
|
test_recycle()
|
||||||
{
|
{
|
||||||
@ -90,12 +117,61 @@ quit
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_recycle_crossrename()
|
||||||
|
{
|
||||||
|
tmpfile=$PREFIX/smbclient_interactive_prompt_commands
|
||||||
|
echo "
|
||||||
|
put $tmpfile testfile3
|
||||||
|
put $tmpfile testfile4.tmp
|
||||||
|
del testfile3
|
||||||
|
del testfile4.tmp
|
||||||
|
quit
|
||||||
|
" > $tmpfile
|
||||||
|
cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT -U$USERNAME%$PASSWORD //$SERVER/recycle2 -I$SERVER_IP $ADDARGS < $tmpfile 2>&1'
|
||||||
|
eval echo "$cmd"
|
||||||
|
out=$(eval "$cmd")
|
||||||
|
ret=$?
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
|
||||||
|
if [ $ret != 0 ]; then
|
||||||
|
printf "%s\n" "$out"
|
||||||
|
printf "failed recycle smbclient run with error %s\n" "$ret"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -e "$share_test_dir2/.trash/testfile3" || {
|
||||||
|
printf ".trash/testfile3 expected to exist but does NOT exist\n"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
test -e "$share_test_dir2/.trash/testfile4.tmp" && {
|
||||||
|
printf ".trash/testfile4.tmp not expected to exist but DOES exist\n"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
deviceid1=`stat -c '%d' "$share_test_dir2/"`
|
||||||
|
deviceid2=`stat -c '%d' "$share_test_dir2/.trash/"`
|
||||||
|
test "$deviceid1=" != "$deviceid2" || {
|
||||||
|
printf ".trash/ should be on a different filesystem!\n"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
perm_want=755
|
||||||
|
perm_is=`stat -c '%a' "$share_test_dir2/.trash/"`
|
||||||
|
test "$perm_is" = "$perm_want" || {
|
||||||
|
printf ".trash/ permission should be $perm_want but is $perm_is\n"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG)
|
panic_count_0=$(grep -c PANIC $SMBD_TEST_LOG)
|
||||||
|
|
||||||
testit "recycle" \
|
testit "recycle" \
|
||||||
test_recycle ||
|
test_recycle ||
|
||||||
failed=$((failed + 1))
|
failed=$((failed + 1))
|
||||||
|
|
||||||
|
testit "recycle_crossrename" \
|
||||||
|
test_recycle_crossrename ||
|
||||||
|
failed=$((failed + 1))
|
||||||
|
|
||||||
panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG)
|
panic_count_1=$(grep -c PANIC $SMBD_TEST_LOG)
|
||||||
|
|
||||||
testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1)
|
testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $failed + 1)
|
||||||
@ -103,5 +179,7 @@ testit "check_panic" test $panic_count_0 -eq $panic_count_1 || failed=$(expr $fa
|
|||||||
#
|
#
|
||||||
# Cleanup.
|
# Cleanup.
|
||||||
do_cleanup
|
do_cleanup
|
||||||
|
# Cleanup above only deletes a symlink, delete also /tmp/.trash_XXXXXX dir
|
||||||
|
rm -rf "$TRASHDIR"
|
||||||
|
|
||||||
testok "$0" "$failed"
|
testok "$0" "$failed"
|
||||||
|
@ -784,7 +784,7 @@ for env in ["fileserver"]:
|
|||||||
plantestsuite("samba3.blackbox.force_create_mode", env, [os.path.join(samba3srcdir, "script/tests/test_force_create_mode.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', env, smbclient3])
|
plantestsuite("samba3.blackbox.force_create_mode", env, [os.path.join(samba3srcdir, "script/tests/test_force_create_mode.sh"), '$SERVER', '$DOMAIN', '$USERNAME', '$PASSWORD', '$PREFIX', env, smbclient3])
|
||||||
plantestsuite("samba3.blackbox.dropbox", env, [os.path.join(samba3srcdir, "script/tests/test_dropbox.sh"), '$SERVER', '$DOMAIN', 'gooduser', '$PASSWORD', '$PREFIX', env, smbclient3])
|
plantestsuite("samba3.blackbox.dropbox", env, [os.path.join(samba3srcdir, "script/tests/test_dropbox.sh"), '$SERVER', '$DOMAIN', 'gooduser', '$PASSWORD', '$PREFIX', env, smbclient3])
|
||||||
plantestsuite("samba3.blackbox.offline", env, [os.path.join(samba3srcdir, "script/tests/test_offline.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/offline', smbclient3])
|
plantestsuite("samba3.blackbox.offline", env, [os.path.join(samba3srcdir, "script/tests/test_offline.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/offline', smbclient3])
|
||||||
plantestsuite("samba3.blackbox.recycle", env, [os.path.join(samba3srcdir, "script/tests/test_recycle.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/recycle', '$PREFIX', smbclient3])
|
plantestsuite("samba3.blackbox.recycle", env, [os.path.join(samba3srcdir, "script/tests/test_recycle.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH', '$PREFIX', smbclient3])
|
||||||
plantestsuite("samba3.blackbox.fakedircreatetimes", env, [os.path.join(samba3srcdir, "script/tests/test_fakedircreatetimes.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/fakedircreatetimes', '$PREFIX', smbclient3])
|
plantestsuite("samba3.blackbox.fakedircreatetimes", env, [os.path.join(samba3srcdir, "script/tests/test_fakedircreatetimes.sh"), '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/fakedircreatetimes', '$PREFIX', smbclient3])
|
||||||
plantestsuite("samba3.blackbox.shadow_copy2.NT1", env + "_smb1_done", [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'NT1'])
|
plantestsuite("samba3.blackbox.shadow_copy2.NT1", env + "_smb1_done", [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'NT1'])
|
||||||
plantestsuite("samba3.blackbox.shadow_copy2.SMB3", env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'SMB3'])
|
plantestsuite("samba3.blackbox.shadow_copy2.SMB3", env, [os.path.join(samba3srcdir, "script/tests/test_shadow_copy.sh"), '$SERVER', '$SERVER_IP', '$DOMAIN', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/shadow', smbclient3, '-m', 'SMB3'])
|
||||||
|
@ -973,15 +973,10 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
|
|||||||
|
|
||||||
return status;
|
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,
|
static NTSTATUS recursive_rmdir_fsp(struct files_struct *fsp)
|
||||||
connection_struct *conn,
|
|
||||||
struct smb_filename *smb_dname)
|
|
||||||
{
|
{
|
||||||
|
struct connection_struct *conn = fsp->conn;
|
||||||
const char *dname = NULL;
|
const char *dname = NULL;
|
||||||
char *talloced = NULL;
|
char *talloced = NULL;
|
||||||
struct smb_Dir *dir_hnd = NULL;
|
struct smb_Dir *dir_hnd = NULL;
|
||||||
@ -989,14 +984,7 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
|||||||
int retval;
|
int retval;
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
NTSTATUS status = NT_STATUS_OK;
|
||||||
|
|
||||||
SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
|
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
||||||
|
|
||||||
status = OpenDir(talloc_tos(),
|
|
||||||
conn,
|
|
||||||
smb_dname,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&dir_hnd);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -1005,9 +993,6 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
|||||||
|
|
||||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||||
struct smb_filename *atname = NULL;
|
struct smb_filename *atname = NULL;
|
||||||
struct smb_filename *smb_dname_full = NULL;
|
|
||||||
char *fullname = NULL;
|
|
||||||
bool do_break = true;
|
|
||||||
int unlink_flags = 0;
|
int unlink_flags = 0;
|
||||||
|
|
||||||
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
if (ISDOT(dname) || ISDOTDOT(dname)) {
|
||||||
@ -1015,56 +1000,56 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the full name. */
|
atname = synthetic_smb_fname(talloc_tos(),
|
||||||
fullname = talloc_asprintf(ctx,
|
dname,
|
||||||
"%s/%s",
|
|
||||||
smb_dname->base_name,
|
|
||||||
dname);
|
|
||||||
if (!fullname) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
goto err_break;
|
|
||||||
}
|
|
||||||
|
|
||||||
smb_dname_full = synthetic_smb_fname(talloc_tos(),
|
|
||||||
fullname,
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
smb_dname->twrp,
|
dirfsp->fsp_name->twrp,
|
||||||
smb_dname->flags);
|
dirfsp->fsp_name->flags);
|
||||||
if (smb_dname_full == NULL) {
|
TALLOC_FREE(talloced);
|
||||||
|
dname = NULL;
|
||||||
|
|
||||||
|
if (atname == NULL) {
|
||||||
status = NT_STATUS_NO_MEMORY;
|
status = NT_STATUS_NO_MEMORY;
|
||||||
goto err_break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
|
{
|
||||||
status = map_nt_error_from_unix(errno);
|
struct name_compare_entry *veto_list = conn->veto_list;
|
||||||
goto err_break;
|
|
||||||
|
/*
|
||||||
|
* 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_dname_full->st.st_ex_mode & S_IFDIR) {
|
|
||||||
status = recursive_rmdir(ctx, conn, smb_dname_full);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
goto err_break;
|
TALLOC_FREE(atname);
|
||||||
|
if (NT_STATUS_EQUAL(status,
|
||||||
|
NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||||
|
/* race between readdir and unlink */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atname->st.st_ex_mode & S_IFDIR) {
|
||||||
|
status = recursive_rmdir_fsp(atname->fsp);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
TALLOC_FREE(atname);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
unlink_flags = AT_REMOVEDIR;
|
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)) {
|
if (!is_visible_fsp(atname->fsp)) {
|
||||||
TALLOC_FREE(smb_dname_full);
|
|
||||||
TALLOC_FREE(fullname);
|
|
||||||
TALLOC_FREE(talloced);
|
|
||||||
TALLOC_FREE(atname);
|
TALLOC_FREE(atname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1075,25 +1060,34 @@ NTSTATUS recursive_rmdir(TALLOC_CTX *ctx,
|
|||||||
unlink_flags);
|
unlink_flags);
|
||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
status = map_nt_error_from_unix(errno);
|
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);
|
TALLOC_FREE(atname);
|
||||||
if (do_break) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TALLOC_FREE(atname);
|
||||||
}
|
}
|
||||||
|
|
||||||
TALLOC_FREE(dir_hnd);
|
TALLOC_FREE(dir_hnd);
|
||||||
return status;
|
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.
|
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 *smb_dname = fsp->fsp_name;
|
||||||
struct smb_filename *parent_fname = NULL;
|
struct smb_filename *parent_fname = NULL;
|
||||||
struct smb_filename *at_fname = NULL;
|
struct smb_filename *at_fname = NULL;
|
||||||
const char *dname = NULL;
|
|
||||||
char *talloced = NULL;
|
|
||||||
struct smb_Dir *dir_hnd = NULL;
|
struct smb_Dir *dir_hnd = NULL;
|
||||||
struct files_struct *dirfsp = NULL;
|
struct files_struct *dirfsp = NULL;
|
||||||
int unlink_flags = 0;
|
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.
|
* 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);
|
dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||||
|
|
||||||
while ((dname = ReadDirName(dir_hnd, &talloced)) != NULL) {
|
status = can_delete_directory_hnd(dir_hnd);
|
||||||
struct smb_filename *smb_dname_full = NULL;
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
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;
|
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not a symlink, get a pathref. */
|
status = recursive_rmdir_fsp(dirfsp);
|
||||||
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)) {
|
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 = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
goto err;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we get here, we know NT_STATUS_IS_OK(status) */
|
|
||||||
SMB_ASSERT(NT_STATUS_IS_OK(status));
|
|
||||||
|
|
||||||
/* Retry the rmdir */
|
/* Retry the rmdir */
|
||||||
ret = SMB_VFS_UNLINKAT(conn,
|
ret = SMB_VFS_UNLINKAT(conn,
|
||||||
parent_fname->fsp,
|
parent_fname->fsp,
|
||||||
|
@ -1222,11 +1222,12 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* ignore tmp directories, see mkdir_internals()
|
* ignore tmp directories, see mkdir_internal()
|
||||||
*/
|
*/
|
||||||
if (IS_SMBD_TMPNAME(n, &unlink_flags)) {
|
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;
|
struct smb_filename *atname = NULL;
|
||||||
const char *fp = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
atname = synthetic_smb_fname(talloc_tos(),
|
atname = synthetic_smb_fname(talloc_tos(),
|
||||||
@ -1239,17 +1240,9 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
|||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
continue;
|
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) {
|
if (unlink_flags == INT_MAX) {
|
||||||
DBG_NOTICE("ignoring %s\n", fp);
|
DBG_NOTICE("ignoring %s/%s\n", dirname, n);
|
||||||
TALLOC_FREE(atname);
|
TALLOC_FREE(atname);
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
continue;
|
continue;
|
||||||
@ -1259,18 +1252,23 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, char **ptalloced)
|
|||||||
* We remove the stale tmpname
|
* We remove the stale tmpname
|
||||||
* as root and ignore any errors
|
* as root and ignore any errors
|
||||||
*/
|
*/
|
||||||
DBG_NOTICE("unlink stale %s\n", fp);
|
DBG_NOTICE("unlink stale %s/%s\n", dirname, n);
|
||||||
become_root();
|
become_root();
|
||||||
ret = SMB_VFS_UNLINKAT(conn,
|
ret = SMB_VFS_UNLINKAT(conn,
|
||||||
dir_hnd->fsp,
|
dirfsp,
|
||||||
atname,
|
atname,
|
||||||
unlink_flags);
|
unlink_flags);
|
||||||
unbecome_root();
|
unbecome_root();
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
DBG_NOTICE("unlinked stale %s\n", fp);
|
DBG_NOTICE("unlinked stale %s/%s\n",
|
||||||
|
dirname,
|
||||||
|
n);
|
||||||
} else {
|
} else {
|
||||||
DBG_WARNING("failed to unlink stale %s: %s\n",
|
DBG_WARNING(
|
||||||
fp, strerror(errno));
|
"failed to unlink stale %s/%s: %s\n",
|
||||||
|
dirname,
|
||||||
|
n,
|
||||||
|
strerror(errno));
|
||||||
}
|
}
|
||||||
TALLOC_FREE(atname);
|
TALLOC_FREE(atname);
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
@ -1541,137 +1539,96 @@ bool opens_below_forall(struct connection_struct *conn,
|
|||||||
Is this directory empty ?
|
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;
|
NTSTATUS status = NT_STATUS_OK;
|
||||||
const char *dname = NULL;
|
const char *dname = NULL;
|
||||||
char *talloced = NULL;
|
char *talloced = NULL;
|
||||||
struct connection_struct *conn = fsp->conn;
|
struct files_struct *dirfsp = dir_hnd_fetch_fsp(dir_hnd);
|
||||||
struct smb_Dir *dir_hnd = NULL;
|
struct connection_struct *conn = dirfsp->conn;
|
||||||
|
bool delete_veto = lp_delete_veto_files(SNUM(conn));
|
||||||
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
while ((dname = ReadDirName(dir_hnd, &talloced))) {
|
||||||
struct smb_filename *smb_dname_full = NULL;
|
|
||||||
struct smb_filename *direntry_fname = NULL;
|
struct smb_filename *direntry_fname = NULL;
|
||||||
char *fullname = NULL;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (ISDOT(dname) || (ISDOTDOT(dname))) {
|
if (ISDOT(dname) || (ISDOTDOT(dname))) {
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (IS_VETO_PATH(conn, dname)) {
|
if (delete_veto && IS_VETO_PATH(conn, dname)) {
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullname = talloc_asprintf(talloc_tos(),
|
direntry_fname = synthetic_smb_fname(talloc_tos(),
|
||||||
"%s/%s",
|
|
||||||
fsp->fsp_name->base_name,
|
|
||||||
dname);
|
|
||||||
if (fullname == NULL) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
dname,
|
||||||
NULL,
|
NULL,
|
||||||
&smb_dname_full->st,
|
NULL,
|
||||||
fsp->fsp_name->twrp,
|
dirfsp->fsp_name->twrp,
|
||||||
fsp->fsp_name->flags);
|
dirfsp->fsp_name->flags);
|
||||||
if (smb_dname == NULL) {
|
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(talloced);
|
||||||
TALLOC_FREE(fullname);
|
dname = NULL;
|
||||||
TALLOC_FREE(smb_dname_full);
|
|
||||||
|
if (direntry_fname == NULL) {
|
||||||
status = NT_STATUS_NO_MEMORY;
|
status = NT_STATUS_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_msdfs_link(fsp, smb_dname)) {
|
|
||||||
TALLOC_FREE(talloced);
|
status = openat_pathref_fsp_lcomp(
|
||||||
TALLOC_FREE(fullname);
|
dirfsp,
|
||||||
TALLOC_FREE(smb_dname_full);
|
direntry_fname,
|
||||||
TALLOC_FREE(smb_dname);
|
UCF_POSIX_PATHNAMES /* no ci fallback */);
|
||||||
DBG_DEBUG("got msdfs link name %s "
|
|
||||||
"- can't delete directory %s\n",
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
dname,
|
DBG_DEBUG("Could not open %s: %s\n",
|
||||||
fsp_str_dbg(fsp));
|
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;
|
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TALLOC_FREE(smb_dname);
|
|
||||||
|
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 ? */
|
/* 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)) {
|
if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
|
||||||
/*
|
/*
|
||||||
* Dangling symlink.
|
* Dangling symlink.
|
||||||
* Allow if "delete veto files = yes"
|
* Allow if "delete veto files = yes"
|
||||||
*/
|
*/
|
||||||
if (lp_delete_veto_files(SNUM(conn))) {
|
if (lp_delete_veto_files(SNUM(conn))) {
|
||||||
TALLOC_FREE(talloced);
|
TALLOC_FREE(direntry_fname);
|
||||||
TALLOC_FREE(fullname);
|
|
||||||
TALLOC_FREE(smb_dname_full);
|
|
||||||
continue;
|
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)) {
|
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"
|
* Allow if "delete veto files = yes"
|
||||||
*/
|
*/
|
||||||
if (lp_delete_veto_files(SNUM(conn))) {
|
if (lp_delete_veto_files(SNUM(conn))) {
|
||||||
TALLOC_FREE(talloced);
|
|
||||||
TALLOC_FREE(fullname);
|
|
||||||
TALLOC_FREE(smb_dname_full);
|
|
||||||
TALLOC_FREE(direntry_fname);
|
TALLOC_FREE(direntry_fname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TALLOC_FREE(talloced);
|
DBG_DEBUG("got name %s - can't delete\n",
|
||||||
TALLOC_FREE(fullname);
|
direntry_fname->base_name);
|
||||||
TALLOC_FREE(smb_dname_full);
|
|
||||||
TALLOC_FREE(direntry_fname);
|
TALLOC_FREE(direntry_fname);
|
||||||
|
|
||||||
DBG_DEBUG("got name %s - can't delete\n", dname);
|
|
||||||
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TALLOC_FREE(talloced);
|
|
||||||
TALLOC_FREE(dir_hnd);
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_file_open_below(fsp)) {
|
if (have_file_open_below(dirfsp)) {
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
return NT_STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
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 smb_Dir;
|
||||||
struct dptr_struct;
|
struct dptr_struct;
|
||||||
|
|
||||||
|
NTSTATUS can_delete_directory_hnd(struct smb_Dir *dir_hnd);
|
||||||
NTSTATUS can_delete_directory_fsp(files_struct *fsp);
|
NTSTATUS can_delete_directory_fsp(files_struct *fsp);
|
||||||
struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd);
|
struct files_struct *dir_hnd_fetch_fsp(struct smb_Dir *dir_hnd);
|
||||||
uint16_t dptr_attr(struct smbd_server_connection *sconn, int key);
|
uint16_t dptr_attr(struct smbd_server_connection *sconn, int key);
|
||||||
|
@ -4749,7 +4749,7 @@ mkdir_first:
|
|||||||
&rhow);
|
&rhow);
|
||||||
if (ret == -1 && errno == EINVAL) {
|
if (ret == -1 && errno == EINVAL) {
|
||||||
/*
|
/*
|
||||||
* This is the strategie we use without having
|
* This is the strategy we use without having
|
||||||
* renameat2(RENAME_NOREPLACE):
|
* renameat2(RENAME_NOREPLACE):
|
||||||
*
|
*
|
||||||
* renameat() is able to replace a directory if the source is
|
* renameat() is able to replace a directory if the source is
|
||||||
@ -5423,6 +5423,7 @@ void msg_file_was_renamed(struct messaging_context *msg_ctx,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
||||||
|
struct files_struct *dirfsp,
|
||||||
const struct smb_filename *smb_fname)
|
const struct smb_filename *smb_fname)
|
||||||
{
|
{
|
||||||
struct stream_struct *stream_info = NULL;
|
struct stream_struct *stream_info = NULL;
|
||||||
@ -5475,8 +5476,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(10, ("open_streams_for_delete found %d streams\n",
|
DBG_DEBUG("open_streams_for_delete found %u streams\n", num_streams);
|
||||||
num_streams));
|
|
||||||
|
|
||||||
if (num_streams == 0) {
|
if (num_streams == 0) {
|
||||||
TALLOC_FREE(frame);
|
TALLOC_FREE(frame);
|
||||||
@ -5522,7 +5522,7 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn,
|
|||||||
status = SMB_VFS_CREATE_FILE(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
NULL, /* req */
|
NULL, /* req */
|
||||||
NULL, /* dirfsp */
|
dirfsp, /* dirfsp */
|
||||||
smb_fname_cp, /* fname */
|
smb_fname_cp, /* fname */
|
||||||
DELETE_ACCESS, /* access_mask */
|
DELETE_ACCESS, /* access_mask */
|
||||||
(FILE_SHARE_READ | /* share_access */
|
(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
|
* We can't open a file with DELETE access if any of the
|
||||||
* streams is open without FILE_SHARE_DELETE
|
* 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)) {
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -2181,22 +2181,18 @@ static NTSTATUS smb_q_unix_info2(
|
|||||||
return NT_STATUS_OK;
|
return NT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_POSIX_ACLS)
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Utility function to open a fsp for a POSIX handle operation.
|
Utility function to open a fsp for a POSIX handle operation.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static NTSTATUS get_posix_fsp(connection_struct *conn,
|
static NTSTATUS get_posix_fsp(connection_struct *conn,
|
||||||
struct smb_request *req,
|
struct smb_request *req,
|
||||||
|
struct files_struct *dirfsp,
|
||||||
struct smb_filename *smb_fname,
|
struct smb_filename *smb_fname,
|
||||||
uint32_t access_mask,
|
uint32_t access_mask,
|
||||||
files_struct **ret_fsp)
|
files_struct **ret_fsp)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
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;
|
struct smb2_create_blobs *posx = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2204,7 +2200,6 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
|||||||
* but set reasonable defaults.
|
* but set reasonable defaults.
|
||||||
*/
|
*/
|
||||||
uint32_t file_attributes = 0664;
|
uint32_t file_attributes = 0664;
|
||||||
uint32_t oplock = NO_OPLOCK;
|
|
||||||
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
|
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
|
||||||
|
|
||||||
/* File or directory must exist. */
|
/* File or directory must exist. */
|
||||||
@ -2236,14 +2231,15 @@ static NTSTATUS get_posix_fsp(connection_struct *conn,
|
|||||||
status = SMB_VFS_CREATE_FILE(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
req, /* req */
|
req, /* req */
|
||||||
NULL, /* dirfsp */
|
dirfsp, /* dirfsp */
|
||||||
smb_fname, /* fname */
|
smb_fname, /* fname */
|
||||||
access_mask, /* access_mask */
|
access_mask, /* access_mask */
|
||||||
share_access, /* share_access */
|
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||||
create_disposition,/* create_disposition*/
|
FILE_SHARE_DELETE, /* share_access */
|
||||||
|
FILE_OPEN, /* create_disposition*/
|
||||||
create_options, /* create_options */
|
create_options, /* create_options */
|
||||||
file_attributes, /* file_attributes */
|
file_attributes, /* file_attributes */
|
||||||
oplock, /* oplock_request */
|
NO_OPLOCK, /* oplock_request */
|
||||||
NULL, /* lease */
|
NULL, /* lease */
|
||||||
0, /* allocation_size */
|
0, /* allocation_size */
|
||||||
0, /* private_flags */
|
0, /* private_flags */
|
||||||
@ -2259,6 +2255,8 @@ done:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_POSIX_ACLS)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Utility function to count the number of entries in a POSIX acl.
|
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;
|
unsigned int size_needed = 0;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
bool ok, refuse;
|
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);
|
refuse = refuse_symlink_fsp(fsp);
|
||||||
if (refuse) {
|
if (refuse) {
|
||||||
@ -2509,16 +2483,6 @@ static NTSTATUS smb_q_posix_acl(
|
|||||||
status = NT_STATUS_OK;
|
status = NT_STATUS_OK;
|
||||||
|
|
||||||
out:
|
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(file_acl);
|
||||||
TALLOC_FREE(def_acl);
|
TALLOC_FREE(def_acl);
|
||||||
return status;
|
return status;
|
||||||
@ -2762,15 +2726,25 @@ static void call_trans2qpathinfo(
|
|||||||
&total_data);
|
&total_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SMB_QUERY_POSIX_ACL:
|
case SMB_QUERY_POSIX_ACL: {
|
||||||
status = smb_q_posix_acl(
|
struct files_struct *posix_fsp = NULL;
|
||||||
conn,
|
|
||||||
|
status = get_posix_fsp(conn,
|
||||||
req,
|
req,
|
||||||
|
dirfsp,
|
||||||
smb_fname,
|
smb_fname,
|
||||||
smb_fname->fsp,
|
SEC_STD_READ_CONTROL |
|
||||||
ppdata,
|
FILE_READ_ATTRIBUTES |
|
||||||
&total_data);
|
FILE_WRITE_ATTRIBUTES,
|
||||||
|
&posix_fsp);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
status = smb_q_posix_acl(
|
||||||
|
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:
|
case SMB_QUERY_FILE_UNIX_LINK:
|
||||||
status = smb_q_posix_symlink(conn,
|
status = smb_q_posix_symlink(conn,
|
||||||
@ -3146,6 +3120,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
|||||||
struct smb_request *req,
|
struct smb_request *req,
|
||||||
char **ppdata,
|
char **ppdata,
|
||||||
int total_data,
|
int total_data,
|
||||||
|
struct files_struct *dirfsp,
|
||||||
struct smb_filename *smb_fname,
|
struct smb_filename *smb_fname,
|
||||||
int *pdata_return_size)
|
int *pdata_return_size)
|
||||||
{
|
{
|
||||||
@ -3187,7 +3162,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
|||||||
status = SMB_VFS_CREATE_FILE(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
req, /* req */
|
req, /* req */
|
||||||
NULL, /* dirfsp */
|
dirfsp, /* dirfsp */
|
||||||
smb_fname, /* fname */
|
smb_fname, /* fname */
|
||||||
FILE_READ_ATTRIBUTES, /* access_mask */
|
FILE_READ_ATTRIBUTES, /* access_mask */
|
||||||
FILE_SHARE_NONE, /* share_access */
|
FILE_SHARE_NONE, /* share_access */
|
||||||
@ -3300,9 +3275,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
|||||||
wire_open_mode = IVAL(pdata,4);
|
wire_open_mode = IVAL(pdata,4);
|
||||||
|
|
||||||
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
|
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
|
||||||
return smb_posix_mkdir(conn, req,
|
return smb_posix_mkdir(conn,
|
||||||
|
req,
|
||||||
ppdata,
|
ppdata,
|
||||||
total_data,
|
total_data,
|
||||||
|
dirfsp,
|
||||||
smb_fname,
|
smb_fname,
|
||||||
pdata_return_size);
|
pdata_return_size);
|
||||||
}
|
}
|
||||||
@ -3431,10 +3408,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
|
|||||||
create_options |= FILE_DIRECTORY_FILE;
|
create_options |= FILE_DIRECTORY_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
|
DBG_DEBUG("file %s, smb_posix_flags = %" PRIu32 ", mode 0%o\n",
|
||||||
smb_fname_str_dbg(smb_fname),
|
smb_fname_str_dbg(smb_fname),
|
||||||
(unsigned int)wire_open_mode,
|
wire_open_mode,
|
||||||
(unsigned int)unixmode ));
|
(unsigned int)unixmode);
|
||||||
|
|
||||||
status = SMB_VFS_CREATE_FILE(
|
status = SMB_VFS_CREATE_FILE(
|
||||||
conn, /* conn */
|
conn, /* conn */
|
||||||
@ -3994,9 +3971,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DBG_DEBUG("SMB_SET_FILE_UNIX_BASIC: name = "
|
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),
|
smb_fname_str_dbg(smb_fname),
|
||||||
(double)size,
|
(intmax_t)size,
|
||||||
(unsigned int)set_owner,
|
(unsigned int)set_owner,
|
||||||
(unsigned int)set_grp,
|
(unsigned int)set_grp,
|
||||||
(int)raw_unixmode);
|
(int)raw_unixmode);
|
||||||
@ -4044,10 +4021,10 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
|
|||||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
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",
|
"setting mode 0%o for file %s\n",
|
||||||
(unsigned int)unixmode,
|
(unsigned int)unixmode,
|
||||||
smb_fname_str_dbg(smb_fname)));
|
smb_fname_str_dbg(smb_fname));
|
||||||
ret = SMB_VFS_FCHMOD(fsp, unixmode);
|
ret = SMB_VFS_FCHMOD(fsp, unixmode);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return map_nt_error_from_unix(errno);
|
return map_nt_error_from_unix(errno);
|
||||||
@ -4267,7 +4244,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
unsigned int size_needed;
|
unsigned int size_needed;
|
||||||
unsigned int total_data;
|
unsigned int total_data;
|
||||||
bool close_fsp = false;
|
|
||||||
bool refuse;
|
bool refuse;
|
||||||
|
|
||||||
if (total_data_in < 0) {
|
if (total_data_in < 0) {
|
||||||
@ -4329,32 +4305,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
|||||||
goto out;
|
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);
|
refuse = refuse_symlink_fsp(fsp);
|
||||||
if (refuse) {
|
if (refuse) {
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
status = NT_STATUS_ACCESS_DENIED;
|
||||||
@ -4404,10 +4354,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
|
|||||||
status = NT_STATUS_OK;
|
status = NT_STATUS_OK;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
if (close_fsp) {
|
|
||||||
(void)close_file_free(req, &fsp, NORMAL_CLOSE);
|
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -4568,21 +4514,34 @@ static void call_trans2setpathinfo(
|
|||||||
smb_fname->fsp,
|
smb_fname->fsp,
|
||||||
smb_fname);
|
smb_fname);
|
||||||
break;
|
break;
|
||||||
case SMB_SET_POSIX_ACL:
|
case SMB_SET_POSIX_ACL: {
|
||||||
status = smb_set_posix_acl(
|
struct files_struct *posix_fsp = NULL;
|
||||||
conn, req, *ppdata, total_data, NULL, smb_fname);
|
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = smb_set_posix_acl(
|
||||||
|
conn, req, *ppdata, total_data, posix_fsp, smb_fname);
|
||||||
|
(void)close_file_free(req, &posix_fsp, NORMAL_CLOSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (info_level_handled) {
|
if (info_level_handled) {
|
||||||
goto done;
|
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;
|
fsp = smb_fname->fsp;
|
||||||
if (fsp == NULL) {
|
if (fsp == NULL) {
|
||||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
@ -4702,10 +4661,10 @@ static void call_trans2setfileinfo(
|
|||||||
*ppdata, 0,
|
*ppdata, 0,
|
||||||
max_data_bytes);
|
max_data_bytes);
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Original code - this is an open file.
|
* Original code - this is an open file.
|
||||||
|
@ -5052,11 +5052,10 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
|
|||||||
return NT_STATUS_INVALID_PARAMETER;
|
return NT_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = IVAL(pdata,0);
|
size = (off_t)PULL_LE_U64(pdata, 0);
|
||||||
size |= (((off_t)IVAL(pdata,4)) << 32);
|
DBG_DEBUG("Set end of file info for file %s to %ju\n",
|
||||||
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
|
smb_fname_str_dbg(smb_fname),
|
||||||
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
|
(uintmax_t)size);
|
||||||
(double)size));
|
|
||||||
|
|
||||||
return smb_set_file_size(conn, req,
|
return smb_set_file_size(conn, req,
|
||||||
fsp,
|
fsp,
|
||||||
|
@ -342,8 +342,12 @@ static int DoWriteCommand( int argc, char **argv, bool debugflag, char *exename
|
|||||||
fixup_eventlog_record_tdb( &ee );
|
fixup_eventlog_record_tdb( &ee );
|
||||||
|
|
||||||
if ( opt_debug )
|
if ( opt_debug )
|
||||||
printf( "record number [%d], tg [%d] , tw [%d]\n",
|
printf("record number [%" PRIu32 "], "
|
||||||
ee.record_number, (int)ee.time_generated, (int)ee.time_written );
|
"tg [%" PRIu64 "] , "
|
||||||
|
"tw [%" PRIu64 "]\n",
|
||||||
|
ee.record_number,
|
||||||
|
(uint64_t)ee.time_generated,
|
||||||
|
(uint64_t)ee.time_written);
|
||||||
|
|
||||||
if ( ee.time_generated != 0 ) {
|
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]));
|
unix_to_nt_time_abs((NTTIME *)&i1->min_password_age, atoi(argv[0]));
|
||||||
d_printf(_("Setting minimum password age to %d seconds\n"),
|
d_printf(_("Setting minimum password age to %" PRIu64 " seconds\n"),
|
||||||
(int)nt_time_to_unix_abs((NTTIME *)&i1->min_password_age));
|
(uint64_t)nt_time_to_unix_abs(
|
||||||
|
(NTTIME *)&i1->min_password_age));
|
||||||
|
|
||||||
return 1;
|
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_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
|
||||||
{ WINBINDD_GETGROUPS, "GETGROUPS",
|
{ WINBINDD_GETGROUPS, "GETGROUPS",
|
||||||
winbindd_getgroups_send, winbindd_getgroups_recv },
|
winbindd_getgroups_send, winbindd_getgroups_recv },
|
||||||
{ WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
|
|
||||||
winbindd_show_sequence_send, winbindd_show_sequence_recv },
|
|
||||||
{ WINBINDD_GETGRGID, "GETGRGID",
|
{ WINBINDD_GETGRGID, "GETGRGID",
|
||||||
winbindd_getgrgid_send, winbindd_getgrgid_recv },
|
winbindd_getgrgid_send, winbindd_getgrgid_recv },
|
||||||
{ WINBINDD_GETGRNAM, "GETGRNAM",
|
{ 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);
|
expire = nt_time_to_unix(ads->auth.expire_time);
|
||||||
|
|
||||||
DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
|
DBG_INFO("Current tickets expire in %" PRIu64 " seconds "
|
||||||
"is now %d)\n", (uint32_t)expire - (uint32_t)now,
|
"(at %" PRIu64 ", time is now %" PRIu64 ")\n",
|
||||||
(uint32_t) expire, (uint32_t) now));
|
(uint64_t)expire - (uint64_t)now,
|
||||||
|
(uint64_t)expire,
|
||||||
|
(uint64_t)now);
|
||||||
|
|
||||||
if ( ads->config.realm && (expire > now)) {
|
if ( ads->config.realm && (expire > now)) {
|
||||||
return;
|
return;
|
||||||
|
@ -502,8 +502,6 @@ NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain,
|
|||||||
|
|
||||||
struct winbindd_domain *domain_list(void);
|
struct winbindd_domain *domain_list(void);
|
||||||
struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain);
|
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,
|
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||||
struct info3_text *info3,
|
struct info3_text *info3,
|
||||||
struct info6_text *info6);
|
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,
|
NTSTATUS winbindd_getgroups_recv(struct tevent_req *req,
|
||||||
struct winbindd_response *response);
|
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_req *wb_group_members_send(TALLOC_CTX *mem_ctx,
|
||||||
struct tevent_context *ev,
|
struct tevent_context *ev,
|
||||||
const struct dom_sid *sid,
|
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;
|
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,
|
bool add_trusted_domain_from_auth(uint16_t validation_level,
|
||||||
struct info3_text *info3,
|
struct info3_text *info3,
|
||||||
struct info6_text *info6)
|
struct info6_text *info6)
|
||||||
|
@ -208,8 +208,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
|||||||
wb_lookupusergroups.c
|
wb_lookupusergroups.c
|
||||||
wb_getpwsid.c
|
wb_getpwsid.c
|
||||||
wb_gettoken.c
|
wb_gettoken.c
|
||||||
wb_seqnum.c
|
|
||||||
wb_seqnums.c
|
|
||||||
wb_group_members.c
|
wb_group_members.c
|
||||||
wb_alias_members.c
|
wb_alias_members.c
|
||||||
wb_getgrsid.c
|
wb_getgrsid.c
|
||||||
@ -231,7 +229,6 @@ bld.SAMBA3_SUBSYSTEM('winbindd-lib',
|
|||||||
winbindd_getsidaliases.c
|
winbindd_getsidaliases.c
|
||||||
winbindd_getuserdomgroups.c
|
winbindd_getuserdomgroups.c
|
||||||
winbindd_getgroups.c
|
winbindd_getgroups.c
|
||||||
winbindd_show_sequence.c
|
|
||||||
winbindd_getgrgid.c
|
winbindd_getgrgid.c
|
||||||
winbindd_getgrnam.c
|
winbindd_getgrnam.c
|
||||||
winbindd_getusersids.c
|
winbindd_getusersids.c
|
||||||
|
@ -736,162 +736,6 @@ static bool torture_winbind_struct_list_groups(struct torture_context *torture)
|
|||||||
return true;
|
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)
|
static bool torture_winbind_struct_setpwent(struct torture_context *torture)
|
||||||
{
|
{
|
||||||
struct winbindd_request req;
|
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, "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_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, "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, "setpwent", torture_winbind_struct_setpwent);
|
||||||
torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent);
|
torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent);
|
||||||
torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent);
|
torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user