#include "librpc/gen_ndr/smb3posix.h"
#include "libcli/security/security.h"
-/*
- * SMB2 POSIX create context return details.
- */
-ssize_t smb2_posix_cc_info(
- connection_struct *conn,
- uint32_t reparse_tag,
- const SMB_STRUCT_STAT *psbuf,
- const struct dom_sid *owner,
- const struct dom_sid *group,
- uint8_t *buf,
- size_t buflen)
-{
- size_t owner_sid_size = ndr_size_dom_sid(owner, 0);
- size_t group_sid_size = ndr_size_dom_sid(group, 0);
- size_t b_size = 12;
-
- owner_sid_size = ndr_size_dom_sid(owner, 0);
- if (b_size + owner_sid_size < b_size) {
- return -1;
- }
- b_size += owner_sid_size;
-
- group_sid_size = ndr_size_dom_sid(group, 0);
- if (b_size + group_sid_size < b_size) {
- return -1;
- }
- b_size += group_sid_size;
-
- if (buflen < b_size) {
- return b_size;
- }
-
- /* number of hard links */
- PUSH_LE_U32(buf, 0, psbuf->st_ex_nlink);
-
- /* Reparse tag if FILE_FLAG_REPARSE is set, else zero. */
- PUSH_LE_U32(buf, 4, reparse_tag);
-
- /*
- * Remove type info from mode, leaving only the
- * permissions and setuid/gid bits.
- */
- PUSH_LE_U32(buf,
- 8,
- unix_perms_to_wire(psbuf->st_ex_mode & ~S_IFMT));
-
- buf += 12;
- buflen -= 12;
-
- /* Now add in the owner and group sids. */
- sid_linearize(buf, buflen, owner);
- buf += owner_sid_size;
- buflen -= owner_sid_size;
-
- sid_linearize(buf, buflen, group);
-
- return b_size;
-}
-
-/*
- * SMB2 POSIX info level.
- */
-ssize_t store_smb2_posix_info(
- connection_struct *conn,
- const SMB_STRUCT_STAT *psbuf,
- uint32_t reparse_tag,
- uint32_t dos_attributes,
- uint8_t *buf,
- size_t buflen)
-{
- uint64_t file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
- struct dom_sid owner = global_sid_NULL;
- struct dom_sid group = global_sid_NULL;
- ssize_t cc_len;
-
- if (psbuf->st_ex_uid != (uid_t)-1) {
- uid_to_sid(&owner, psbuf->st_ex_uid);
- }
- if (psbuf->st_ex_gid != (gid_t)-1) {
- gid_to_sid(&group, psbuf->st_ex_gid);
- }
-
- cc_len = smb2_posix_cc_info(
- conn, reparse_tag, psbuf, &owner, &group, NULL, 0);
-
- if (cc_len == -1) {
- return -1;
- }
-
- if (cc_len + 68 < 68) {
- return -1;
- }
-
- if (buflen < cc_len + 68) {
- return cc_len + 68;
- }
-
- /* Timestamps. */
-
- /* Birth (creation) time. */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
- (char *)buf+0,
- psbuf->st_ex_btime);
- /* Access time. */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
- (char *)buf+8,
- psbuf->st_ex_atime);
- /* Last write time. */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
- (char *)buf+16,
- psbuf->st_ex_mtime);
- /* Change time. */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,
- (char *)buf+24,
- psbuf->st_ex_ctime);
-
- /* File size 64 Bit */
- SOFF_T(buf,32, get_file_size_stat(psbuf));
-
- /* Number of bytes used on disk - 64 Bit */
- SOFF_T(buf,40,SMB_VFS_GET_ALLOC_SIZE(conn,NULL,psbuf));
-
- /* DOS attributes */
- if (S_ISREG(psbuf->st_ex_mode)) {
- PUSH_LE_U32(buf, 48, dos_attributes);
- } else if (S_ISDIR(psbuf->st_ex_mode)) {
- PUSH_LE_U32(buf, 48, dos_attributes|FILE_ATTRIBUTE_DIRECTORY);
- } else {
- /*
- * All non-directory or regular files are reported
- * as reparse points. Client may or may not be able
- * to access these.
- */
- PUSH_LE_U32(buf, 48, FILE_ATTRIBUTE_REPARSE_POINT);
- }
-
- /* Add the inode and dev (16 bytes). */
- PUSH_LE_U64(buf, 52, file_id);
- PUSH_LE_U64(buf, 60, psbuf->st_ex_dev);
-
- /*
- * Append a POSIX create context (variable bytes).
- */
- smb2_posix_cc_info(
- conn,
- reparse_tag,
- psbuf,
- &owner,
- &group,
- buf + 68,
- cc_len);
-
- return cc_len + 68;
-}
-
void smb3_file_posix_information_init(
connection_struct *conn,
const struct stat_ex *st,