diff options
104 files changed, 2301 insertions, 1279 deletions
diff --git a/.gitignore b/.gitignore index 45164d2985..5d18b2d6f9 100644 --- a/.gitignore +++ b/.gitignore @@ -232,7 +232,7 @@ source4/lib/tdb/bin/tdbbackup source4/lib/tdb/bin/tdbdump source4/lib/tdb/bin/tdbtool source4/lib/tdb/bin/tdbtorture -source4/lib/tdr/tdr_proto.h +lib/tdr/tdr_proto.h lib/util/apidocs lib/util/asn1_proto.h lib/util/pidfile.h @@ -316,6 +316,8 @@ librpc/gen_ndr/cli_drsblobs.h librpc/gen_ndr/srv_drsblobs.c librpc/gen_ndr/srv_drsblobs.h source3/setup +librpc/gen_ndr/cli_dcerpc.[ch] +librpc/gen_ndr/srv_dcerpc.[ch] librpc/gen_ndr/*wzcsvc* librpc/gen_ndr/*w32time* librpc/gen_ndr/*wmi* diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 066f718999..fe8d541de8 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -14,6 +14,9 @@ Authentication Changes: o Changed the way smbd handles untrusted domain names given during user authentication +net Command Changes: +o parameter syntax made more consistent + Authentication Changes ====================== @@ -32,6 +35,38 @@ on smbd to always pass through bogus names to the DC for verification. A new parameter "map untrusted to domain" can be enabled to revert to the legacy behavior. +net Command Changes +=================== + +The net command now accepts the common command line parameters most other Samba +command line utilities use, with a couple of remaining differences: + +-l still gives long output for net commands supporting the --long flag. This was +more useful than the common --log-base parameter. + +-i still tells net to read data from stdin (like --stdin) instead of toggling +the common --scope flag. + +-S still tells net the server to connect to (like --server) instead of +negotiating the common --signing flag. As -S is probably used by most scripts +doing net rpc commands, this would have been a high-impact change for little +gain. + +This change was mainly done to unify the authentification options. Here, one +flag changed it's meaning and one useful flag was added. + +-N used to be the short version of --ntname. It now matches the Samba default of +--no-pass. Use this to stop net from prompting for a password if you want +anonymous authentication. + +-A --authentication-file now takes an authentication file with the username and +password you want net to use, avoiding a password prompt as with plain -U user +or having to give a password on the command line as in -U user%pass. + +Last but not least net now always falls back to your local unix username if no +-U is specified and a username is needed. net rpc commands will now prompt for a +password unless one is specified using either -U user%pass or -A auth_file. + ###################################################################### Reporting bugs & Development Discussion ####################################### diff --git a/docs-xml/Samba3-HOWTO/index.xml b/docs-xml/Samba3-HOWTO/index.xml index 87b07951c7..8321714867 100644 --- a/docs-xml/Samba3-HOWTO/index.xml +++ b/docs-xml/Samba3-HOWTO/index.xml @@ -3,7 +3,7 @@ <book id="Samba-HOWTO-Collection" xmlns:xi="http://www.w3.org/2003/XInclude"> -<title>The Official Samba 3.2.x HOWTO and Reference Guide</title> +<title>The Official Samba 3.5.x HOWTO and Reference Guide</title> <bookinfo> <authorgroup> diff --git a/docs-xml/manpages-3/idmap_rid.8.xml b/docs-xml/manpages-3/idmap_rid.8.xml index 5449797441..55aed62f85 100644 --- a/docs-xml/manpages-3/idmap_rid.8.xml +++ b/docs-xml/manpages-3/idmap_rid.8.xml @@ -66,7 +66,7 @@ </programlisting> </para> <para> - Correspondingly, the formula for calculationg the RID for a + Correspondingly, the formula for calculating the RID for a given Unix ID is this: <programlisting> RID = ID + BASE_RID - LOW_RANGE_ID. diff --git a/docs-xml/manpages-3/smbclient.1.xml b/docs-xml/manpages-3/smbclient.1.xml index 7785d2c093..9840414e44 100644 --- a/docs-xml/manpages-3/smbclient.1.xml +++ b/docs-xml/manpages-3/smbclient.1.xml @@ -916,6 +916,14 @@ </varlistentry> <varlistentry> + <term>readlink symlinkname</term> + <listitem><para>This command depends on the server supporting the CIFS + UNIX extensions and will fail if the server does not. Print + the value of the symlink "symlinkname". + </para></listitem> + </varlistentry> + + <varlistentry> <term>rd <directory name></term> <listitem><para>See the rmdir command. </para></listitem> </varlistentry> diff --git a/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml new file mode 100644 index 0000000000..bcf65e6eb6 --- /dev/null +++ b/docs-xml/smbdotconf/security/mapuntrustedtodomain.xml @@ -0,0 +1,33 @@ +<samba:parameter name="map untrusted to domain" + context="G" + type="boolean" + advanced="1" + developer="1" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> + <para> + If a client connects to smbd using an untrusted domain name, such as + BOGUS\user, smbd replaces the BOGUS domain with it's SAM name before + attempting to authenticate that user. In the case where smbd is acting as + a PDC this will be DOMAIN\user. In the case where smbd is acting as a + domain member server or a standalone server this will be WORKSTATION\user. + </para> + + <para> + In previous versions of Samba (pre 3.4), if smbd was acting as a domain + member server, the BOGUS domain name would instead be replaced by the + primary domain which smbd was a member of. In this case authentication + would be deferred off to a DC using the credentials DOMAIN\user. + </para> + + <para> + When this parameter is set to <constant>yes</constant> smbd provides the + legacy behavior of mapping untrusted domain names to the primary domain. + When smbd is not acting as a domain member server, this parameter has no + effect. + </para> + +</description> + +<value type="default">no</value> +</samba:parameter> diff --git a/docs-xml/smbdotconf/security/passdbbackend.xml b/docs-xml/smbdotconf/security/passdbbackend.xml index 487d8b8a9d..b761f970c0 100644 --- a/docs-xml/smbdotconf/security/passdbbackend.xml +++ b/docs-xml/smbdotconf/security/passdbbackend.xml @@ -16,8 +16,10 @@ <para>Available backends can include: <itemizedlist> <listitem> - <para><command moreinfo="none">smbpasswd</command> - The default smbpasswd - backend. Takes a path to the smbpasswd file as an optional argument. + <para><command moreinfo="none">smbpasswd</command> - The old plaintext passdb + backend. Some Samba features will not work if this passdb + backend is used. Takes a path to the smbpasswd file as an + optional argument. </para> </listitem> @@ -60,5 +62,5 @@ passdb backend = ldapsam:"ldap://ldap-1.example.com ldap-2.example.com" </programlisting> </description> -<value type="default">smbpasswd</value> +<value type="default">tdbsam</value> </samba:parameter> diff --git a/lib/tdb/tools/tdbtool.c b/lib/tdb/tools/tdbtool.c index 3220e47b13..c0814e11de 100644 --- a/lib/tdb/tools/tdbtool.c +++ b/lib/tdb/tools/tdbtool.c @@ -401,8 +401,8 @@ static void speed_tdb(const char *tlimit) do { long int r = random(); TDB_DATA key, dbuf; - key.dptr = "store test"; - key.dsize = strlen(key.dptr); + key.dptr = (unsigned char *)"store test"; + key.dsize = strlen((char *)key.dptr); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_store(tdb, key, dbuf, TDB_REPLACE); @@ -417,8 +417,8 @@ static void speed_tdb(const char *tlimit) do { long int r = random(); TDB_DATA key, dbuf; - key.dptr = "store test"; - key.dsize = strlen(key.dptr); + key.dptr = (unsigned char *)"store test"; + key.dsize = strlen((char *)key.dptr); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_fetch(tdb, key); @@ -433,8 +433,8 @@ static void speed_tdb(const char *tlimit) do { long int r = random(); TDB_DATA key, dbuf; - key.dptr = "transaction test"; - key.dsize = strlen(key.dptr); + key.dptr = (unsigned char *)"transaction test"; + key.dsize = strlen((char *)key.dptr); dbuf.dptr = (unsigned char *)&r; dbuf.dsize = sizeof(r); tdb_transaction_start(tdb); diff --git a/librpc/gen_ndr/security.h b/librpc/gen_ndr/security.h index f90dd413a8..16635f0bb8 100644 --- a/librpc/gen_ndr/security.h +++ b/librpc/gen_ndr/security.h @@ -126,6 +126,7 @@ #define DOMAIN_RID_GUEST ( 501 ) #define DOMAIN_RID_ADMINS ( 512 ) #define DOMAIN_RID_USERS ( 513 ) +#define DOMAIN_RID_KRBTGT ( 514 ) #define DOMAIN_RID_DOMAIN_MEMBERS ( 515 ) #define DOMAIN_RID_DCS ( 516 ) #define DOMAIN_RID_CERT_ADMINS ( 517 ) diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index 825ce96d71..9e47ff45fc 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -226,6 +226,7 @@ interface security const int DOMAIN_RID_GUEST = 501; const int DOMAIN_RID_ADMINS = 512; const int DOMAIN_RID_USERS = 513; + const int DOMAIN_RID_KRBTGT = 514; const int DOMAIN_RID_DOMAIN_MEMBERS = 515; const int DOMAIN_RID_DCS = 516; const int DOMAIN_RID_CERT_ADMINS = 517; diff --git a/source3/Makefile.in b/source3/Makefile.in index 1120092f90..2b30b4a5bd 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -359,7 +359,8 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \ CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \ ../lib/crypto/hmacmd5.o ../lib/crypto/arcfour.o \ - ../lib/crypto/md4.o + ../lib/crypto/md4.o \ + ../lib/crypto/sha256.o ../lib/crypto/hmacsha256.o LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o \ @@ -750,7 +751,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/dnsregister.o smbd/globals.o \ smbd/smb2_server.o smbd/smb2_negprot.o \ smbd/smb2_sesssetup.o smbd/smb2_tcon.o \ - smbd/smb2_keepalive.o \ + smbd/smb2_keepalive.o smbd/smb2_signing.o \ $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ diff --git a/source3/client/client.c b/source3/client/client.c index 59e5c1ad72..2edeb1ae2b 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2725,7 +2725,7 @@ static int cmd_link(void) return 1; } - if (!cli_unix_hardlink(targetcli, targetname, newname)) { + if (!NT_STATUS_IS_OK(cli_posix_hardlink(targetcli, targetname, newname))) { d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname); return 1; } @@ -2733,6 +2733,54 @@ static int cmd_link(void) } /**************************************************************************** + UNIX readlink. +****************************************************************************/ + +static int cmd_readlink(void) +{ + TALLOC_CTX *ctx = talloc_tos(); + char *name= NULL; + char *buf = NULL; + char *targetname = NULL; + char linkname[PATH_MAX+1]; + struct cli_state *targetcli; + + if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { + d_printf("readlink <name>\n"); + return 1; + } + name = talloc_asprintf(ctx, + "%s%s", + client_get_cur_dir(), + buf); + if (!name) { + return 1; + } + + if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) { + d_printf("readlink %s: %s\n", name, cli_errstr(cli)); + return 1; + } + + if (!SERVER_HAS_UNIX_CIFS(targetcli)) { + d_printf("Server doesn't support UNIX CIFS calls.\n"); + return 1; + } + + if (!NT_STATUS_IS_OK(cli_posix_readlink(targetcli, name, + linkname, PATH_MAX+1))) { + d_printf("%s readlink on file %s\n", + cli_errstr(targetcli), name); + return 1; + } + + d_printf("%s -> %s\n", name, linkname); + + return 0; +} + + +/**************************************************************************** UNIX symlink. ****************************************************************************/ @@ -2776,7 +2824,7 @@ static int cmd_symlink(void) return 1; } - if (!cli_unix_symlink(targetcli, targetname, newname)) { + if (!NT_STATUS_IS_OK(cli_posix_symlink(targetcli, targetname, newname))) { d_printf("%s symlinking files (%s -> %s)\n", cli_errstr(targetcli), newname, targetname); return 1; @@ -3022,7 +3070,7 @@ static int cmd_getfacl(void) } d_printf("# file: %s\n", src); - d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_uid, (unsigned int)sbuf.st_gid); + d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_ex_uid, (unsigned int)sbuf.st_ex_gid); if (num_file_acls == 0 && num_dir_acls == 0) { d_printf("No acls found.\n"); @@ -3120,6 +3168,7 @@ static int cmd_stat(void) fstring mode_str; SMB_STRUCT_STAT sbuf; struct tm *lt; + time_t tmp_time; if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) { d_printf("stat file\n"); @@ -3152,30 +3201,31 @@ static int cmd_stat(void) /* Print out the stat values. */ d_printf("File: %s\n", src); d_printf("Size: %-12.0f\tBlocks: %u\t%s\n", - (double)sbuf.st_size, - (unsigned int)sbuf.st_blocks, - filetype_to_str(sbuf.st_mode)); + (double)sbuf.st_ex_size, + (unsigned int)sbuf.st_ex_blocks, + filetype_to_str(sbuf.st_ex_mode)); #if defined(S_ISCHR) && defined(S_ISBLK) - if (S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode)) { + if (S_ISCHR(sbuf.st_ex_mode) || S_ISBLK(sbuf.st_ex_mode)) { d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n", - (double)sbuf.st_ino, - (unsigned int)sbuf.st_nlink, - unix_dev_major(sbuf.st_rdev), - unix_dev_minor(sbuf.st_rdev)); + (double)sbuf.st_ex_ino, + (unsigned int)sbuf.st_ex_nlink, + unix_dev_major(sbuf.st_ex_rdev), + unix_dev_minor(sbuf.st_ex_rdev)); } else #endif d_printf("Inode: %.0f\tLinks: %u\n", - (double)sbuf.st_ino, - (unsigned int)sbuf.st_nlink); + (double)sbuf.st_ex_ino, + (unsigned int)sbuf.st_ex_nlink); d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n", - ((int)sbuf.st_mode & 0777), - unix_mode_to_str(mode_str, sbuf.st_mode), - (unsigned int)sbuf.st_uid, - (unsigned int)sbuf.st_gid); + ((int)sbuf.st_ex_mode & 0777), + unix_mode_to_str(mode_str, sbuf.st_ex_mode), + (unsigned int)sbuf.st_ex_uid, + (unsigned int)sbuf.st_ex_gid); - lt = localtime(&sbuf.st_atime); + tmp_time = convert_timespec_to_time_t(sbuf.st_ex_atime); + lt = localtime(&tmp_time); if (lt) { strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt); } else { @@ -3183,7 +3233,8 @@ static int cmd_stat(void) } d_printf("Access: %s\n", mode_str); - lt = localtime(&sbuf.st_mtime); + tmp_time = convert_timespec_to_time_t(sbuf.st_ex_mtime); + lt = localtime(&tmp_time); if (lt) { strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt); } else { @@ -3191,7 +3242,8 @@ static int cmd_stat(void) } d_printf("Modify: %s\n", mode_str); - lt = localtime(&sbuf.st_ctime); + tmp_time = convert_timespec_to_time_t(sbuf.st_ex_ctime); + lt = localtime(&tmp_time); if (lt) { strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt); } else { @@ -3400,7 +3452,7 @@ static int cmd_newer(void) ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL); if (ok && (sys_stat(buf,&sbuf) == 0)) { - newer_than = sbuf.st_mtime; + newer_than = convert_timespec_to_time_t(sbuf.st_ex_mtime); DEBUG(1,("Getting files newer than %s", time_to_asc(newer_than))); } else { @@ -3949,6 +4001,7 @@ static struct { {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}}, {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}}, + {"readlink",cmd_readlink,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE,COMPL_REMOTE}}, {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}}, {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}}, {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}}, diff --git a/source3/client/clitar.c b/source3/client/clitar.c index ff71924555..d973329427 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -412,7 +412,7 @@ static void dotareof(int f) /* Could be a pipe, in which case S_ISREG should fail, * and we should write out at full size */ if (tp > 0) { - size_t towrite = S_ISREG(stbuf.st_mode) ? tp : tbufsiz; + size_t towrite = S_ISREG(stbuf.st_ex_mode) ? tp : tbufsiz; if (sys_write(f, tarbuf, towrite) != towrite) { DEBUG(0,("dotareof: sys_write fail\n")); } @@ -1793,7 +1793,8 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind) SMB_STRUCT_STAT stbuf; if (sys_stat(argv[Optind], &stbuf) == 0) { - newer_than = stbuf.st_mtime; + newer_than = convert_timespec_to_time_t( + stbuf.st_ex_mtime); DEBUG(1,("Getting files newer than %s", time_to_asc(newer_than))); newOptind++; diff --git a/source3/configure.in b/source3/configure.in index 44374b989c..f980911666 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -2778,6 +2778,8 @@ if test x"$samba_cv_HAVE_STAT_ST_BLOCKS" = x"yes"; then AC_DEFINE(HAVE_STAT_ST_BLOCKS,1,[Whether the stat struct has a st_block property]) fi +AC_CHECK_TYPES([blksize_t, blkcnt_t], [], [], [[#include <sys/stat.h>]]) + AC_CACHE_CHECK([for st_blksize in struct stat],samba_cv_HAVE_STAT_ST_BLKSIZE,[ AC_TRY_COMPILE([#include <sys/types.h> #include <sys/stat.h> diff --git a/source3/include/includes.h b/source3/include/includes.h index 596c772d9e..e468bd5c38 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -431,17 +431,49 @@ typedef uint64_t br_off; #define IVAL_TO_SMB_OFF_T(buf,off) ((SMB_OFF_T)(( ((uint32)(IVAL((buf),(off)))) & 0xFFFFFFFF ))) #endif +#ifndef HAVE_BLKSIZE_T +/* This is mainly for HP/UX which defines st_blksize as long */ +typedef long blksize_t; +#endif + +#ifndef HAVE_BLKCNT_T +/* This is mainly for HP/UX which doesn't have blkcnt_t */ +typedef long blkcnt_t; +#endif + /* * Type for stat structure. */ -#ifndef SMB_STRUCT_STAT -# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_STAT64) && defined(HAVE_OFF64_T) -# define SMB_STRUCT_STAT struct stat64 -# else -# define SMB_STRUCT_STAT struct stat -# endif -#endif +struct stat_ex { + dev_t st_ex_dev; + ino_t st_ex_ino; + mode_t st_ex_mode; + nlink_t st_ex_nlink; + uid_t st_ex_uid; + gid_t st_ex_gid; + dev_t st_ex_rdev; + off_t st_ex_size; + struct timespec st_ex_atime; + struct timespec st_ex_mtime; + struct timespec st_ex_ctime; + struct timespec st_ex_btime; /* birthtime */ + blksize_t st_ex_blksize; + blkcnt_t st_ex_blocks; + + uint32_t st_ex_flags; + uint32_t st_ex_mask; + + /* + * Add space for VFS internal extensions. The initial user of this + * would be the onefs modules, passing the snapid from the stat calls + * to the file_id_create call. Maybe we'll have to expand this later, + * but the core of Samba should never look at this field. + */ + uint64_t vfs_private; +}; + +typedef struct stat_ex SMB_STRUCT_STAT; /* * Type for dirent structure. diff --git a/source3/include/proto.h b/source3/include/proto.h index e0b0e59700..342c1432eb 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1010,13 +1010,6 @@ void srv_put_dos_date2(char *buf,int offset, time_t unixdate); void srv_put_dos_date3(char *buf,int offset,time_t unixdate); void put_long_date_timespec(char *p, struct timespec ts); void put_long_date(char *p, time_t t); -struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,bool fake_dirs); -struct timespec get_atimespec(const SMB_STRUCT_STAT *pst); -void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts); -struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst); -void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts); -struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst); -void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts); void dos_filetime_timespec(struct timespec *tsp); time_t make_unix_date2(const void *date_ptr, int zone_offset); time_t make_unix_date3(const void *date_ptr, int zone_offset); @@ -1113,7 +1106,7 @@ char *clean_name(TALLOC_CTX *ctx, const char *s); ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos); int set_blocking(int fd, bool set); void smb_msleep(unsigned int t); -bool reinit_after_fork(struct messaging_context *msg_ctx, +NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, struct event_context *ev_ctx, bool parent_longlived); bool yesno(const char *p); @@ -2339,12 +2332,37 @@ void cli_reset_error(struct cli_state *cli); /* The following definitions come from libsmb/clifile.c */ +struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *oldname, + const char *newname); +NTSTATUS cli_posix_symlink_recv(struct tevent_req *req); +NTSTATUS cli_posix_symlink(struct cli_state *cli, + const char *oldname, + const char *newname); +struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + size_t len); +NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli, + char *retpath, size_t len); +NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname, + char *linkpath, size_t len); +struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *oldname, + const char *newname); +NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req); +NTSTATUS cli_posix_hardlink(struct cli_state *cli, + const char *oldname, + const char *newname); uint32_t unix_perms_to_wire(mode_t perms); mode_t wire_perms_to_unix(uint32_t perms); bool cli_unix_getfacl(struct cli_state *cli, const char *name, size_t *prb_size, char **retbuf); bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbuf); -bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname); -bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname); bool cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode); bool cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid); struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx, @@ -4087,7 +4105,7 @@ bool lp_recursive_veto_delete(int ); bool lp_dos_filemode(int ); bool lp_dos_filetimes(int ); bool lp_dos_filetime_resolution(int ); -bool lp_fake_dir_create_times(int ); +bool lp_fake_dir_create_times(void); bool lp_blocking_locks(int ); bool lp_inherit_perms(int ); bool lp_inherit_acls(int ); @@ -6174,7 +6192,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, char **pp_fname_out, SMB_OFF_T *size, uint32 *mode, - time_t *date, + struct timespec *date, bool check_descend, bool ask_sharemode); bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto); diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 22cfaaf581..7528883c2d 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -88,9 +88,9 @@ * stat structure is valid. */ -#define VALID_STAT(st) ((st).st_nlink != 0) -#define VALID_STAT_OF_DIR(st) (VALID_STAT(st) && S_ISDIR((st).st_mode)) -#define SET_STAT_INVALID(st) ((st).st_nlink = 0) +#define VALID_STAT(st) ((st).st_ex_nlink != 0) +#define VALID_STAT_OF_DIR(st) (VALID_STAT(st) && S_ISDIR((st).st_ex_mode)) +#define SET_STAT_INVALID(st) ((st).st_ex_nlink = 0) /* Macros to get at offsets within smb_lkrng and smb_unlkrng structures. We cannot define these as actual structures diff --git a/source3/lib/debug.c b/source3/lib/debug.c index 14aca3adad..419af61ef3 100644 --- a/source3/lib/debug.c +++ b/source3/lib/debug.c @@ -739,7 +739,7 @@ void check_log_size( void ) maxlog = lp_max_log_size() * 1024; - if( sys_fstat( x_fileno( dbf ), &st ) == 0 && st.st_size > maxlog ) { + if( sys_fstat( x_fileno( dbf ), &st ) == 0 && st.st_ex_size > maxlog ) { (void)reopen_logs(); if( dbf && get_file_size( debugf ) > maxlog ) { char *name = NULL; diff --git a/source3/lib/system.c b/source3/lib/system.c index 517e347c0f..d9d3266fbc 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -290,6 +290,201 @@ int sys_fcntl_long(int fd, int cmd, long arg) return ret; } +/**************************************************************************** + Return the best approximation to a 'create time' under UNIX from a stat + structure. +****************************************************************************/ + +static time_t calc_create_time(const struct stat *st) +{ + time_t ret, ret1; + + ret = MIN(st->st_ctime, st->st_mtime); + ret1 = MIN(ret, st->st_atime); + + if(ret1 != (time_t)0) { + return ret1; + } + + /* + * One of ctime, mtime or atime was zero (probably atime). + * Just return MIN(ctime, mtime). + */ + return ret; +} + +/**************************************************************************** + Return the 'create time' from a stat struct if it exists (birthtime) or else + use the best approximation. +****************************************************************************/ + +static struct timespec get_create_timespec(const struct stat *pst) +{ + struct timespec ret; + + if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) { + ret.tv_sec = 315493200L; /* 1/1/1980 */ + ret.tv_nsec = 0; + return ret; + } + +#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) + ret = pst->st_birthtimespec; +#elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) + ret.tv_sec = pst->st_birthtime; + ret.tv_nsec = pst->st_birthtimenspec; +#elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) + ret.tv_sec = pst->st_birthtime; + ret.tv_nsec = 0; +#else + ret.tv_sec = calc_create_time(pst); + ret.tv_nsec = 0; +#endif + + /* Deal with systems that don't initialize birthtime correctly. + * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>. + */ + if (null_timespec(ret)) { + ret.tv_sec = calc_create_time(pst); + ret.tv_nsec = 0; + } + return ret; +} + +/**************************************************************************** + Get/Set all the possible time fields from a stat struct as a timespec. +****************************************************************************/ + +static struct timespec get_atimespec(const struct stat *pst) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; + + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_atime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + return pst->st_atim; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_atimensec; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_atime_n; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_uatime * 1000; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) + return pst->st_atimespec; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} + +static struct timespec get_mtimespec(const struct stat *pst) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; + + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + return pst->st_mtim; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_mtimensec; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_mtime_n; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_umtime * 1000; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) + return pst->st_mtimespec; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} + +static struct timespec get_ctimespec(const struct stat *pst) +{ +#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) + struct timespec ret; + + /* Old system - no ns timestamp. */ + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = 0; + return ret; +#else +#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + return pst->st_ctim; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_ctimensec; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_ctime_n; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_uctime * 1000; + return ret; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) + return pst->st_ctimespec; +#else +#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT +#endif +#endif +} + +static void init_stat_ex_from_stat (struct stat_ex *dst, + const struct stat *src) +{ + dst->st_ex_dev = src->st_dev; + dst->st_ex_ino = src->st_ino; + dst->st_ex_mode = src->st_mode; + dst->st_ex_nlink = src->st_nlink; + dst->st_ex_uid = src->st_uid; + dst->st_ex_gid = src->st_gid; + dst->st_ex_rdev = src->st_rdev; + dst->st_ex_size = src->st_size; + dst->st_ex_atime = get_atimespec(src); + dst->st_ex_mtime = get_mtimespec(src); + dst->st_ex_ctime = get_ctimespec(src); + dst->st_ex_btime = get_create_timespec(src); + dst->st_ex_blksize = src->st_blksize; + dst->st_ex_blocks = src->st_blocks; + +#ifdef HAVE_STAT_ST_FLAGS + dst->st_ex_flags = src->st_flags; +#else + dst->st_ex_flags = 0; +#endif +} + /******************************************************************* A stat() wrapper that will deal with 64 bit filesizes. ********************************************************************/ @@ -300,10 +495,16 @@ int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf) #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64) ret = stat64(fname, sbuf); #else - ret = stat(fname, sbuf); + struct stat statbuf; + ret = stat(fname, &statbuf); #endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(statbuf.st_mode)) { + statbuf.st_size = 0; + } + init_stat_ex_from_stat(sbuf, &statbuf); + } return ret; } @@ -317,10 +518,16 @@ int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf) #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64) ret = fstat64(fd, sbuf); #else - ret = fstat(fd, sbuf); + struct stat statbuf; + ret = fstat(fd, &statbuf); #endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(statbuf.st_mode)) { + statbuf.st_size = 0; + } + init_stat_ex_from_stat(sbuf, &statbuf); + } return ret; } @@ -334,10 +541,16 @@ int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf) #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64) ret = lstat64(fname, sbuf); #else - ret = lstat(fname, sbuf); + struct stat statbuf; + ret = lstat(fname, &statbuf); #endif - /* we always want directories to appear zero size */ - if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0; + if (ret == 0) { + /* we always want directories to appear zero size */ + if (S_ISDIR(statbuf.st_mode)) { + statbuf.st_size = 0; + } + init_stat_ex_from_stat(sbuf, &statbuf); + } return ret; } diff --git a/source3/lib/time.c b/source3/lib/time.c index 611debe366..a2e615acc5 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -322,251 +322,6 @@ void put_long_date(char *p, time_t t) put_long_date_timespec(p, ts); } -/**************************************************************************** - Return the best approximation to a 'create time' under UNIX from a stat - structure. -****************************************************************************/ - -static time_t calc_create_time(const SMB_STRUCT_STAT *st) -{ - time_t ret, ret1; - - ret = MIN(st->st_ctime, st->st_mtime); - ret1 = MIN(ret, st->st_atime); - - if(ret1 != (time_t)0) { - return ret1; - } - - /* - * One of ctime, mtime or atime was zero (probably atime). - * Just return MIN(ctime, mtime). - */ - return ret; -} - -/**************************************************************************** - Return the 'create time' from a stat struct if it exists (birthtime) or else - use the best approximation. -****************************************************************************/ - -struct timespec get_create_timespec(const SMB_STRUCT_STAT *pst,bool fake_dirs) -{ - struct timespec ret; - - if(S_ISDIR(pst->st_mode) && fake_dirs) { - ret.tv_sec = 315493200L; /* 1/1/1980 */ - ret.tv_nsec = 0; - return ret; - } - -#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) - ret = pst->st_birthtimespec; -#elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) - ret.tv_sec = pst->st_birthtime; - ret.tv_nsec = pst->st_birthtimenspec; -#elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME) - ret.tv_sec = pst->st_birthtime; - ret.tv_nsec = 0; -#else - ret.tv_sec = calc_create_time(pst); - ret.tv_nsec = 0; -#endif - - /* Deal with systems that don't initialize birthtime correctly. - * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>. - */ - if (null_timespec(ret)) { - ret.tv_sec = calc_create_time(pst); - ret.tv_nsec = 0; - } - return ret; -} - -/**************************************************************************** - Get/Set all the possible time fields from a stat struct as a timespec. -****************************************************************************/ - -struct timespec get_atimespec(const SMB_STRUCT_STAT *pst) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; - - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_atime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - return pst->st_atim; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_atime; - ret.tv_nsec = pst->st_atimensec; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - struct timespec ret; - ret.tv_sec = pst->st_atime; - ret.tv_nsec = pst->st_atime_n; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - struct timespec ret; - ret.tv_sec = pst->st_atime; - ret.tv_nsec = pst->st_uatime * 1000; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - return pst->st_atimespec; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - -void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - /* Old system - no ns timestamp. */ - pst->st_atime = ts.tv_sec; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - pst->st_atim = ts; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - pst->st_atime = ts.tv_sec; - pst->st_atimensec = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - pst->st_atime = ts.tv_sec; - pst->st_atime_n = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - pst->st_atime = ts.tv_sec; - pst->st_uatime = ts.tv_nsec / 1000; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - pst->st_atimespec = ts; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - -struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; - - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - return pst->st_mtim; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = pst->st_mtimensec; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - struct timespec ret; - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = pst->st_mtime_n; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - struct timespec ret; - ret.tv_sec = pst->st_mtime; - ret.tv_nsec = pst->st_umtime * 1000; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - return pst->st_mtimespec; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - -void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - /* Old system - no ns timestamp. */ - pst->st_mtime = ts.tv_sec; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - pst->st_mtim = ts; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - pst->st_mtime = ts.tv_sec; - pst->st_mtimensec = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - pst->st_mtime = ts.tv_sec; - pst->st_mtime_n = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - pst->st_mtime = ts.tv_sec; - pst->st_umtime = ts.tv_nsec / 1000; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - pst->st_mtimespec = ts; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - -struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - struct timespec ret; - - /* Old system - no ns timestamp. */ - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = 0; - return ret; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - return pst->st_ctim; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - struct timespec ret; - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = pst->st_ctimensec; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - struct timespec ret; - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = pst->st_ctime_n; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - struct timespec ret; - ret.tv_sec = pst->st_ctime; - ret.tv_nsec = pst->st_uctime * 1000; - return ret; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - return pst->st_ctimespec; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - -void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) -{ -#if !defined(HAVE_STAT_HIRES_TIMESTAMPS) - /* Old system - no ns timestamp. */ - pst->st_ctime = ts.tv_sec; -#else -#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - pst->st_ctim = ts; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) - pst->st_ctime = ts.tv_sec; - pst->st_ctimensec = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_MTIME_N) - pst->st_ctime = ts.tv_sec; - pst->st_ctime_n = ts.tv_nsec; -#elif defined(HAVE_STRUCT_STAT_ST_UMTIME) - pst->st_ctime = ts.tv_sec; - pst->st_uctime = ts.tv_nsec / 1000; -#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - pst->st_ctimespec = ts; -#else -#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT -#endif -#endif -} - void dos_filetime_timespec(struct timespec *tsp) { tsp->tv_sec &= ~1; diff --git a/source3/lib/util.c b/source3/lib/util.c index c86f259ce3..8e67edeae6 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -541,7 +541,7 @@ bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf) if (sys_stat(fname,sbuf) != 0) return(False); - return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode))); + return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode))); } /******************************************************************* @@ -554,7 +554,7 @@ bool socket_exist(const char *fname) if (sys_stat(fname,&st) != 0) return(False); - return S_ISSOCK(st.st_mode); + return S_ISSOCK(st.st_ex_mode); } /******************************************************************* @@ -572,7 +572,7 @@ bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st) if (sys_stat(dname,st) != 0) return(False); - ret = S_ISDIR(st->st_mode); + ret = S_ISDIR(st->st_ex_mode); if(!ret) errno = ENOTDIR; return ret; @@ -584,7 +584,7 @@ bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st) uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf) { - return sbuf->st_size; + return sbuf->st_ex_size; } /******************************************************************* @@ -594,7 +594,7 @@ uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf) SMB_OFF_T get_file_size(char *file_name) { SMB_STRUCT_STAT buf; - buf.st_size = 0; + buf.st_ex_size = 0; if(sys_stat(file_name,&buf) != 0) return (SMB_OFF_T)-1; return get_file_size_stat(&buf); @@ -927,11 +927,11 @@ void smb_msleep(unsigned int t) #endif } -bool reinit_after_fork(struct messaging_context *msg_ctx, +NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx, struct event_context *ev_ctx, bool parent_longlived) { - NTSTATUS status; + NTSTATUS status = NT_STATUS_OK; /* Reset the state of the random * number generation system, so @@ -942,7 +942,8 @@ bool reinit_after_fork(struct messaging_context *msg_ctx, /* tdb needs special fork handling */ if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) { DEBUG(0,("tdb_reopen_all failed.\n")); - return false; + status = NT_STATUS_OPEN_FAILED; + goto done; } if (ev_ctx) { @@ -958,11 +959,10 @@ bool reinit_after_fork(struct messaging_context *msg_ctx, if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("messaging_reinit() failed: %s\n", nt_errstr(status))); - return false; } } - - return true; + done: + return status; } /**************************************************************************** diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 2c80f1dd1a..187fcdf625 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -20,74 +20,510 @@ #include "includes.h" +/*********************************************************** + Common function for pushing stings, used by smb_bytes_push_str() + and trans_bytes_push_str(). Only difference is the align_odd + parameter setting. +***********************************************************/ + +static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2, + const char *str, size_t str_len, + bool align_odd, + size_t *pconverted_size) +{ + size_t buflen; + char *converted; + size_t converted_size; + + if (buf == NULL) { + return NULL; + } + + buflen = talloc_get_size(buf); + + if (align_odd && ucs2 && (buflen % 2 == 0)) { + /* + * We're pushing into an SMB buffer, align odd + */ + buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1); + if (buf == NULL) { + return NULL; + } + buf[buflen] = '\0'; + buflen += 1; + } + + if (!convert_string_talloc(talloc_tos(), CH_UNIX, + ucs2 ? CH_UTF16LE : CH_DOS, + str, str_len, &converted, + &converted_size, true)) { + return NULL; + } + + buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, + buflen + converted_size); + if (buf == NULL) { + TALLOC_FREE(converted); + return NULL; + } + + memcpy(buf + buflen, converted, converted_size); + + TALLOC_FREE(converted); + + if (pconverted_size) { + *pconverted_size = converted_size; + } + + return buf; +} + +/*********************************************************** + Push a string into an SMB buffer, with odd byte alignment + if it's a UCS2 string. +***********************************************************/ + +uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, + const char *str, size_t str_len, + size_t *pconverted_size) +{ + return internal_bytes_push_str(buf, ucs2, str, str_len, + true, pconverted_size); +} + +/*********************************************************** + Same as smb_bytes_push_str(), but without the odd byte + align for ucs2 (we're pushing into a param or data block). + static for now, although this will probably change when + other modules use async trans calls. +***********************************************************/ + +static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2, + const char *str, size_t str_len, + size_t *pconverted_size) +{ + return internal_bytes_push_str(buf, ucs2, str, str_len, + false, pconverted_size); +} + /**************************************************************************** Hard/Symlink a file (UNIX extensions). Creates new name (sym)linked to oldname. ****************************************************************************/ -static bool cli_link_internal(struct cli_state *cli, const char *oldname, const char *newname, bool hard_link) +struct link_state { + uint16_t setup; + uint8_t *param; + uint8_t *data; +}; + +static void cli_posix_link_internal_done(struct tevent_req *subreq) { - unsigned int data_len = 0; - unsigned int param_len = 0; - uint16_t setup = TRANSACT2_SETPATHINFO; - char *param; - char *data; - char *rparam=NULL, *rdata=NULL; - char *p; - size_t oldlen = 2*(strlen(oldname)+1); - size_t newlen = 2*(strlen(newname)+1); + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct link_state *state = tevent_req_data(req, struct link_state); + NTSTATUS status; - param = SMB_MALLOC_ARRAY(char, 6+newlen+2); + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} - if (!param) { - return false; +static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *oldname, + const char *newname, + bool hardlink) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct link_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct link_state); + if (req == NULL) { + return NULL; } - data = SMB_MALLOC_ARRAY(char, oldlen+2); + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO); - if (!data) { - SAFE_FREE(param); - return false; + /* Setup param array. */ + state->param = talloc_array(state, uint8_t, 6); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); } + memset(state->param, '\0', 6); + SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK); - SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK); - SIVAL(param,2,0); - p = ¶m[6]; + state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname, + strlen(newname)+1, NULL); - p += clistr_push(cli, p, newname, newlen, STR_TERMINATE); - param_len = PTR_DIFF(p, param); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); + } - p = data; - p += clistr_push(cli, p, oldname, oldlen, STR_TERMINATE); - data_len = PTR_DIFF(p, data); + /* Setup data array. */ + state->data = talloc_array(state, uint8_t, 0); + if (tevent_req_nomem(state->data, req)) { + return tevent_req_post(req, ev); + } + state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname, + strlen(oldname)+1, NULL); - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - data, data_len, cli->max_xmit /* data, length, max */ - )) { - SAFE_FREE(data); - SAFE_FREE(param); - return false; + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + talloc_get_size(state->param), /* num param. */ + 2, /* max returned param. */ + state->data, /* data. */ + talloc_get_size(state->data), /* num data. */ + 0); /* max returned data. */ + + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_posix_link_internal_done, req); + return req; +} - SAFE_FREE(data); - SAFE_FREE(param); +/**************************************************************************** + Symlink a file (UNIX extensions). +****************************************************************************/ - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - return false; +struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *oldname, + const char *newname) +{ + return cli_posix_link_internal_send(mem_ctx, ev, cli, + oldname, newname, false); +} + +NTSTATUS cli_posix_symlink_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; } + return NT_STATUS_OK; +} - SAFE_FREE(data); - SAFE_FREE(param); - SAFE_FREE(rdata); - SAFE_FREE(rparam); +NTSTATUS cli_posix_symlink(struct cli_state *cli, + const char *oldname, + const char *newname) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; - return true; + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_symlink_send(frame, + ev, + cli, + oldname, + newname); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_symlink_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; +} + +/**************************************************************************** + Read a POSIX symlink. +****************************************************************************/ + +struct readlink_state { + uint16_t setup; + uint8_t *param; + uint8_t *data; + uint32_t num_data; +}; + +static void cli_posix_readlink_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct readlink_state *state = tevent_req_data(req, struct readlink_state); + NTSTATUS status; + + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, + &state->data, &state->num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + if (state->num_data == 0) { + tevent_req_nterror(req, NT_STATUS_DATA_ERROR); + return; + } + if (state->data[state->num_data-1] != '\0') { + tevent_req_nterror(req, NT_STATUS_DATA_ERROR); + return; + } + tevent_req_done(req); +} + +struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + size_t len) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct readlink_state *state = NULL; + uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len); + + if (maxbytelen < len) { + return NULL; + } + + req = tevent_req_create(mem_ctx, &state, struct readlink_state); + if (req == NULL) { + return NULL; + } + + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO); + + /* Setup param array. */ + state->param = talloc_array(state, uint8_t, 6); + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); + } + memset(state->param, '\0', 6); + SSVAL(state->param,0,SMB_QUERY_FILE_UNIX_LINK); + + state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname, + strlen(fname)+1, NULL); + + if (tevent_req_nomem(state->param, req)) { + return tevent_req_post(req, ev); + } + + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + talloc_get_size(state->param), /* num param. */ + 2, /* max returned param. */ + NULL, /* data. */ + 0, /* num data. */ + maxbytelen); /* max returned data. */ + + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_posix_readlink_done, req); + return req; +} + +NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli, + char *retpath, size_t len) +{ + NTSTATUS status; + char *converted = NULL; + size_t converted_size = 0; + struct readlink_state *state = tevent_req_data(req, struct readlink_state); + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + /* The returned data is a pushed string, not raw data. */ + if (!convert_string_talloc(state, + cli_ucs2(cli) ? CH_UTF16LE : CH_DOS, + CH_UNIX, + state->data, + state->num_data, + &converted, + &converted_size, + true)) { + return NT_STATUS_NO_MEMORY; + } + + len = MIN(len,converted_size); + if (len == 0) { + return NT_STATUS_DATA_ERROR; + } + memcpy(retpath, converted, len); + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname, + char *linkpath, size_t len) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + /* Len is in bytes, we need it in UCS2 units. */ + if (2*len < len) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + req = cli_posix_readlink_send(frame, + ev, + cli, + fname, + len); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_readlink_recv(req, cli, linkpath, len); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; +} + + +/**************************************************************************** + Hard link a file (UNIX extensions). +****************************************************************************/ + +struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *oldname, + const char *newname) +{ + return cli_posix_link_internal_send(mem_ctx, ev, cli, + oldname, newname, true); +} + +NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_hardlink(struct cli_state *cli, + const char *oldname, + const char *newname) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_hardlink_send(frame, + ev, + cli, + oldname, + newname); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_hardlink_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -294,56 +730,37 @@ bool cli_unix_stat(struct cli_state *cli, const char *name, SMB_STRUCT_STAT *sbu return false; } - sbuf->st_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */ - sbuf->st_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */ + sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(rdata,0); /* total size, in bytes */ + sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(rdata,8); /* number of blocks allocated */ #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - sbuf->st_blocks /= STAT_ST_BLOCKSIZE; + sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE; #else /* assume 512 byte blocks */ - sbuf->st_blocks /= 512; + sbuf->st_ex_blocks /= 512; #endif - set_ctimespec(sbuf, interpret_long_date(rdata + 16)); /* time of last change */ - set_atimespec(sbuf, interpret_long_date(rdata + 24)); /* time of last access */ - set_mtimespec(sbuf, interpret_long_date(rdata + 32)); /* time of last modification */ + sbuf->st_ex_ctime = interpret_long_date(rdata + 16); /* time of last change */ + sbuf->st_ex_atime = interpret_long_date(rdata + 24); /* time of last access */ + sbuf->st_ex_mtime = interpret_long_date(rdata + 32); /* time of last modification */ - sbuf->st_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */ - sbuf->st_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */ - sbuf->st_mode |= unix_filetype_from_wire(IVAL(rdata, 56)); + sbuf->st_ex_uid = (uid_t) IVAL(rdata,40); /* user ID of owner */ + sbuf->st_ex_gid = (gid_t) IVAL(rdata,48); /* group ID of owner */ + sbuf->st_ex_mode |= unix_filetype_from_wire(IVAL(rdata, 56)); #if defined(HAVE_MAKEDEV) { uint32_t dev_major = IVAL(rdata,60); uint32_t dev_minor = IVAL(rdata,68); - sbuf->st_rdev = makedev(dev_major, dev_minor); + sbuf->st_ex_rdev = makedev(dev_major, dev_minor); } #endif - sbuf->st_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */ - sbuf->st_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */ - sbuf->st_nlink = IVAL(rdata,92); /* number of hard links */ + sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(rdata,76); /* inode */ + sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(rdata,84)); /* protection */ + sbuf->st_ex_nlink = IVAL(rdata,92); /* number of hard links */ SAFE_FREE(rdata); SAFE_FREE(rparam); return true; } - -/**************************************************************************** - Symlink a file (UNIX extensions). -****************************************************************************/ - -bool cli_unix_symlink(struct cli_state *cli, const char *oldname, const char *newname) -{ - return cli_link_internal(cli, oldname, newname, False); -} - -/**************************************************************************** - Hard a file (UNIX extensions). -****************************************************************************/ - -bool cli_unix_hardlink(struct cli_state *cli, const char *oldname, const char *newname) -{ - return cli_link_internal(cli, oldname, newname, True); -} - /**************************************************************************** Chmod or chown a file internal (UNIX extensions). ****************************************************************************/ @@ -1288,92 +1705,6 @@ NTSTATUS cli_ntcreate(struct cli_state *cli, return status; } -/*********************************************************** - Common function for pushing stings, used by smb_bytes_push_str() - and trans_bytes_push_str(). Only difference is the align_odd - parameter setting. -***********************************************************/ - -static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2, - const char *str, size_t str_len, - bool align_odd, - size_t *pconverted_size) -{ - size_t buflen; - char *converted; - size_t converted_size; - - if (buf == NULL) { - return NULL; - } - - buflen = talloc_get_size(buf); - - if (align_odd && ucs2 && (buflen % 2 == 0)) { - /* - * We're pushing into an SMB buffer, align odd - */ - buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1); - if (buf == NULL) { - return NULL; - } - buf[buflen] = '\0'; - buflen += 1; - } - - if (!convert_string_talloc(talloc_tos(), CH_UNIX, - ucs2 ? CH_UTF16LE : CH_DOS, - str, str_len, &converted, - &converted_size, true)) { - return NULL; - } - - buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, - buflen + converted_size); - if (buf == NULL) { - TALLOC_FREE(converted); - return NULL; - } - - memcpy(buf + buflen, converted, converted_size); - - TALLOC_FREE(converted); - - if (pconverted_size) { - *pconverted_size = converted_size; - } - - return buf; -} - -/*********************************************************** - Push a string into an SMB buffer, with odd byte alignment - if it's a UCS2 string. -***********************************************************/ - -uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2, - const char *str, size_t str_len, - size_t *pconverted_size) -{ - return internal_bytes_push_str(buf, ucs2, str, str_len, - true, pconverted_size); -} - -/*********************************************************** - Same as smb_bytes_push_str(), but without the odd byte - align for ucs2 (we're pushing into a param or data block). - static for now, although this will probably change when - other modules use async trans calls. -***********************************************************/ - -static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2, - const char *str, size_t str_len, - size_t *pconverted_size) -{ - return internal_bytes_push_str(buf, ucs2, str, str_len, - false, pconverted_size); -} - /**************************************************************************** Open a file WARNING: if you open with O_WRONLY then getattrE won't work! diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 1771e8fd25..c3ec82bd3e 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -1105,9 +1105,9 @@ bool cli_qpathinfo_basic( struct cli_state *cli, const char *name, return False; } - set_atimespec(sbuf, interpret_long_date( rdata+8 )); /* Access time. */ - set_mtimespec(sbuf, interpret_long_date( rdata+16 )); /* Write time. */ - set_ctimespec(sbuf, interpret_long_date( rdata+24 )); /* Change time. */ + sbuf->st_ex_atime = interpret_long_date( rdata+8 ); /* Access time. */ + sbuf->st_ex_mtime = interpret_long_date( rdata+16 ); /* Write time. */ + sbuf->st_ex_ctime = interpret_long_date( rdata+24 ); /* Change time. */ *attributes = IVAL( rdata, 32 ); diff --git a/source3/libsmb/libsmb_stat.c b/source3/libsmb/libsmb_stat.c index af7800ba32..4349b0a700 100644 --- a/source3/libsmb/libsmb_stat.c +++ b/source3/libsmb/libsmb_stat.c @@ -188,9 +188,9 @@ SMBC_stat_ctx(SMBCCTX *context, setup_stat(context, st, (char *) fname, size, mode); - set_atimespec(st, access_time_ts); - set_ctimespec(st, change_time_ts); - set_mtimespec(st, write_time_ts); + st->st_atime = convert_timespec_to_time_t(access_time_ts); + st->st_ctime = convert_timespec_to_time_t(change_time_ts); + st->st_mtime = convert_timespec_to_time_t(write_time_ts); st->st_dev = srv->dev; TALLOC_FREE(frame); @@ -293,9 +293,9 @@ SMBC_fstat_ctx(SMBCCTX *context, setup_stat(context, st, file->fname, size, mode); - set_atimespec(st, access_time_ts); - set_ctimespec(st, change_time_ts); - set_mtimespec(st, write_time_ts); + st->st_atime = convert_timespec_to_time_t(access_time_ts); + st->st_ctime = convert_timespec_to_time_t(change_time_ts); + st->st_mtime = convert_timespec_to_time_t(write_time_ts); st->st_dev = file->srv->dev; TALLOC_FREE(frame); diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 462e59313a..10a3733c14 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -289,10 +289,11 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf, * shouldn't alloc 0 for * win */ - uid_to_sid(&sid_owner, sbuf->st_uid); - gid_to_sid(&sid_group, sbuf->st_gid); + uid_to_sid(&sid_owner, sbuf->st_ex_uid); + gid_to_sid(&sid_group, sbuf->st_ex_gid); - if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group, S_ISDIR(sbuf->st_mode), + if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group, + S_ISDIR(sbuf->st_ex_mode), &nt_ace_list, &good_aces)==False) { DEBUG(8,("smbacl4_nfs42win failed\n")); return map_nt_error_from_unix(errno); @@ -315,7 +316,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf, } DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n", - ndr_size_security_descriptor(*ppdesc, NULL, 0))); + (int)ndr_size_security_descriptor(*ppdesc, NULL, 0))); return NT_STATUS_OK; } @@ -733,8 +734,8 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, DEBUG(8, ("unpack_nt_owners failed")); return status; } - if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) || + ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) { if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, @@ -759,7 +760,8 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, return NT_STATUS_OK; } - theacl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + theacl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, + sbuf.st_ex_uid, sbuf.st_ex_gid); if (!theacl) return map_nt_error_from_unix(errno); diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index a77f6d60f4..463250a9ed 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -414,8 +414,8 @@ static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx, struct security_ace *pace = NULL; struct security_acl *pacl = NULL; - uid_to_sid(&owner_sid, psbuf->st_uid); - gid_to_sid(&group_sid, psbuf->st_gid); + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2); if (!pace) { diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index 49e4899879..05156f8456 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -282,8 +282,8 @@ static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx, struct security_ace *pace = NULL; struct security_acl *pacl = NULL; - uid_to_sid(&owner_sid, psbuf->st_uid); - gid_to_sid(&group_sid, psbuf->st_gid); + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2); if (!pace) { diff --git a/source3/modules/vfs_afsacl.c b/source3/modules/vfs_afsacl.c index 8c89d2fd9f..e537f01b03 100644 --- a/source3/modules/vfs_afsacl.c +++ b/source3/modules/vfs_afsacl.c @@ -599,8 +599,8 @@ static size_t afs_to_nt_acl_common(struct afs_acl *afs_acl, struct afs_ace *afs_ace; - uid_to_sid(&owner_sid, psbuf->st_uid); - gid_to_sid(&group_sid, psbuf->st_gid); + uid_to_sid(&owner_sid, psbuf->st_ex_uid); + gid_to_sid(&group_sid, psbuf->st_ex_gid); if (afs_acl->num_aces) { nt_ace_list = TALLOC_ARRAY(mem_ctx, SEC_ACE, afs_acl->num_aces); @@ -626,7 +626,7 @@ static size_t afs_to_nt_acl_common(struct afs_acl *afs_acl, continue; } - if (S_ISDIR(psbuf->st_mode)) + if (S_ISDIR(psbuf->st_ex_mode)) afs_to_nt_dir_rights(afs_ace->rights, &nt_rights, &flag); else diff --git a/source3/modules/vfs_commit.c b/source3/modules/vfs_commit.c index a8105e021e..c22e8161d7 100644 --- a/source3/modules/vfs_commit.c +++ b/source3/modules/vfs_commit.c @@ -220,7 +220,7 @@ static int commit_open( if (SMB_VFS_FSTAT(fsp, &st) == -1) { return -1; } - c->eof = st.st_size; + c->eof = st.st_ex_size; } return 0; diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index aa207056b3..fe63d5001a 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -430,7 +430,7 @@ static int copy_reg(const char *source, const char *dest) if (sys_lstat (source, &source_stats) == -1) return -1; - if (!S_ISREG (source_stats.st_mode)) + if (!S_ISREG (source_stats.st_ex_mode)) return -1; if((ifd = sys_open (source, O_RDONLY, 0)) < 0) @@ -455,9 +455,9 @@ static int copy_reg(const char *source, const char *dest) */ #ifdef HAVE_FCHOWN - if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) + if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) #else - if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) + if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM)) #endif goto err; @@ -467,9 +467,9 @@ static int copy_reg(const char *source, const char *dest) */ #if defined(HAVE_FCHMOD) - if (fchmod (ofd, source_stats.st_mode & 07777)) + if (fchmod (ofd, source_stats.st_ex_mode & 07777)) #else - if (chmod (dest, source_stats.st_mode & 07777)) + if (chmod (dest, source_stats.st_ex_mode & 07777)) #endif goto err; @@ -483,8 +483,8 @@ static int copy_reg(const char *source, const char *dest) { struct utimbuf tv; - tv.actime = source_stats.st_atime; - tv.modtime = source_stats.st_mtime; + tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime); + tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime); utime(dest, &tv); } @@ -575,13 +575,13 @@ static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle, START_PROFILE(syscall_get_alloc_size); - if(S_ISDIR(sbuf->st_mode)) { + if(S_ISDIR(sbuf->st_ex_mode)) { result = 0; goto out; } #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks; + result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks; #else result = get_file_size_stat(sbuf); #endif @@ -777,18 +777,18 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs if (SMB_VFS_FSTAT(fsp, &st) == -1) return -1; - space_to_write = len - st.st_size; + space_to_write = len - st.st_ex_size; #ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) + if (S_ISFIFO(st.st_ex_mode)) return 0; #endif - if (st.st_size == len) + if (st.st_ex_size == len) return 0; /* Shrink - just ftruncate. */ - if (st.st_size > len) + if (st.st_ex_size > len) return sys_ftruncate(fsp->fh->fd, len); /* available disk space is enough or not? */ @@ -806,10 +806,10 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs } /* Write out the real space on disk. */ - if (SMB_VFS_LSEEK(fsp, st.st_size, SEEK_SET) != st.st_size) + if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size) return -1; - space_to_write = len - st.st_size; + space_to_write = len - st.st_ex_size; memset(zero_space, '\0', sizeof(zero_space)); while ( space_to_write > 0) { @@ -872,18 +872,18 @@ static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_O } #ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) { + if (S_ISFIFO(st.st_ex_mode)) { result = 0; goto done; } #endif - if (st.st_size == len) { + if (st.st_ex_size == len) { result = 0; goto done; } - if (st.st_size > len) { + if (st.st_ex_size > len) { /* the sys_ftruncate should have worked */ goto done; } @@ -1051,8 +1051,8 @@ static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, * blob */ ZERO_STRUCT(key); - key.devid = sbuf->st_dev; - key.inode = sbuf->st_ino; + key.devid = sbuf->st_ex_dev; + key.inode = sbuf->st_ex_ino; /* key.extid is unused by default. */ return key; @@ -1088,7 +1088,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, return map_nt_error_from_unix(errno); } - if (S_ISDIR(sbuf.st_mode)) { + if (S_ISDIR(sbuf.st_ex_mode)) { goto done; } @@ -1098,7 +1098,7 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, return NT_STATUS_NO_MEMORY; } - streams->size = sbuf.st_size; + streams->size = sbuf.st_ex_size; streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf); streams->name = talloc_strdup(streams, "::$DATA"); diff --git a/source3/modules/vfs_fake_perms.c b/source3/modules/vfs_fake_perms.c index 2989322147..cc3ab6220d 100644 --- a/source3/modules/vfs_fake_perms.c +++ b/source3/modules/vfs_fake_perms.c @@ -32,13 +32,13 @@ static int fake_perms_stat(vfs_handle_struct *handle, const char *fname, SMB_STR ret = SMB_VFS_NEXT_STAT(handle, fname, sbuf); if (ret == 0) { - if (S_ISDIR(sbuf->st_mode)) { - sbuf->st_mode = S_IFDIR | S_IRWXU; + if (S_ISDIR(sbuf->st_ex_mode)) { + sbuf->st_ex_mode = S_IFDIR | S_IRWXU; } else { - sbuf->st_mode = S_IRWXU; + sbuf->st_ex_mode = S_IRWXU; } - sbuf->st_uid = handle->conn->server_info->utok.uid; - sbuf->st_gid = handle->conn->server_info->utok.gid; + sbuf->st_ex_uid = handle->conn->server_info->utok.uid; + sbuf->st_ex_gid = handle->conn->server_info->utok.gid; } return ret; @@ -50,13 +50,13 @@ static int fake_perms_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_ST ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); if (ret == 0) { - if (S_ISDIR(sbuf->st_mode)) { - sbuf->st_mode = S_IFDIR | S_IRWXU; + if (S_ISDIR(sbuf->st_ex_mode)) { + sbuf->st_ex_mode = S_IFDIR | S_IRWXU; } else { - sbuf->st_mode = S_IRWXU; + sbuf->st_ex_mode = S_IRWXU; } - sbuf->st_uid = handle->conn->server_info->utok.uid; - sbuf->st_gid = handle->conn->server_info->utok.gid; + sbuf->st_ex_uid = handle->conn->server_info->utok.uid; + sbuf->st_ex_gid = handle->conn->server_info->utok.gid; } return ret; } diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c index 8152c5477e..93b71a4dc0 100644 --- a/source3/modules/vfs_fileid.c +++ b/source3/modules/vfs_fileid.c @@ -237,8 +237,8 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle, struct fileid_handle_data, return id); - id.devid = data->device_mapping_fn(data, sbuf->st_dev); - id.inode = sbuf->st_ino; + id.devid = data->device_mapping_fn(data, sbuf->st_ex_dev); + id.inode = sbuf->st_ex_ino; return id; } diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 7ef969d04b..2e4e7ede55 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -846,7 +846,7 @@ static int vfs_gpfs_chmod(vfs_handle_struct *handle, const char *path, mode_t mo } /* avoid chmod() if possible, to preserve acls */ - if ((st.st_mode & ~S_IFMT) == mode) { + if ((st.st_ex_mode & ~S_IFMT) == mode) { return 0; } @@ -866,7 +866,7 @@ static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t } /* avoid chmod() if possible, to preserve acls */ - if ((st.st_mode & ~S_IFMT) == mode) { + if ((st.st_ex_mode & ~S_IFMT) == mode) { return 0; } diff --git a/source3/modules/vfs_hpuxacl.c b/source3/modules/vfs_hpuxacl.c index f9293405fb..7d20a73d7b 100644 --- a/source3/modules/vfs_hpuxacl.c +++ b/source3/modules/vfs_hpuxacl.c @@ -252,7 +252,7 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); goto done; } - if (S_ISDIR(s.st_mode)) { + if (S_ISDIR(s.st_ex_mode)) { HPUX_ACL_T other_acl; int other_count; SMB_ACL_TYPE_T other_type; diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index e2fa0fb88a..ed35922359 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/modules/vfs_netatalk.c @@ -82,7 +82,7 @@ static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, const char *fnam sys_lstat(*orig_path, orig_info); - if (S_ISDIR(orig_info->st_mode)) { + if (S_ISDIR(orig_info->st_ex_mode)) { *adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", path, &fname[ptr0], APPLEDOUBLE); } else { @@ -242,7 +242,7 @@ static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, c &adbl_info, &orig_info) != 0) goto exit_rename; - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_rename; } @@ -298,7 +298,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, const char *path) &adbl_info, &orig_info) != 0) goto exit_unlink; - if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { + if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_unlink; } @@ -330,7 +330,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_ &adbl_info, &orig_info) != 0) goto exit_chmod; - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); goto exit_chmod; } @@ -362,7 +362,7 @@ static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t &adbl_info, &orig_info) != 0) goto exit_chown; - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); goto exit_chown; } @@ -396,7 +396,7 @@ static int atalk_lchown(struct vfs_handle_struct *handle, const char *path, uid_ &adbl_info, &orig_info) != 0) goto exit_lchown; - if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) { + if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", orig_path)); goto exit_lchown; } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 2b0edcdb4a..f1791aa6b1 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -215,7 +215,7 @@ static bool recycle_directory_exist(vfs_handle_struct *handle, const char *dname SMB_STRUCT_STAT st; if (SMB_VFS_NEXT_STAT(handle, dname, &st) == 0) { - if (S_ISDIR(st.st_mode)) { + if (S_ISDIR(st.st_ex_mode)) { return True; } } @@ -228,7 +228,7 @@ static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname) SMB_STRUCT_STAT st; if (SMB_VFS_NEXT_STAT(handle, fname, &st) == 0) { - if (S_ISREG(st.st_mode)) { + if (S_ISREG(st.st_ex_mode)) { return True; } } @@ -251,7 +251,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn return (SMB_OFF_T)0; } - return(st.st_size); + return(st.st_ex_size); } /** @@ -402,7 +402,7 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, return; } ft.atime = timespec_current(); /* atime */ - ft.mtime = touch_mtime ? ft.atime : get_mtimespec(&st); /* mtime */ + ft.mtime = touch_mtime ? ft.atime : st.st_ex_mtime; /* mtime */ become_root(); ret = SMB_VFS_NEXT_NTIMES(handle, fname, &ft); diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 9543af32b9..acfac57b51 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -314,7 +314,7 @@ static void convert_sbuf(vfs_handle_struct *handle, const char *fname, SMB_STRUC if (shash == 0) { shash = 1; } - sbuf->st_ino ^= shash; + sbuf->st_ex_ino ^= shash; } } diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index e5a70b1a49..72affe402a 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -182,7 +182,7 @@ static char *stream_dir(vfs_handle_struct *handle, const char *base_path, if (SMB_VFS_NEXT_STAT(handle, result, &sbuf) == 0) { char *newname; - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { errno = EINVAL; goto fail; } @@ -504,7 +504,7 @@ static int streams_depot_unlink(vfs_handle_struct *handle, const char *fname) return -1; } - if (sbuf.st_nlink == 1) { + if (sbuf.st_ex_nlink == 1) { char *dirname = stream_dir(handle, fname, &sbuf, false); if (dirname != NULL) { @@ -652,7 +652,7 @@ static bool collect_one_stream(const char *dirname, if (!add_one_stream(state->mem_ctx, &state->num_streams, &state->streams, - dirent, sbuf.st_size, + dirent, sbuf.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(state->handle->conn, NULL, &sbuf))) { state->status = NT_STATUS_NO_MEMORY; @@ -698,10 +698,10 @@ static NTSTATUS streams_depot_streaminfo(vfs_handle_struct *handle, state.streams = NULL; state.num_streams = 0; - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, - "::$DATA", sbuf.st_size, + "::$DATA", sbuf.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf))) { return NT_STATUS_NO_MEMORY; diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 3d5478d7a2..ebc51e79e3 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -42,17 +42,17 @@ static SMB_INO_T stream_inode(const SMB_STRUCT_STAT *sbuf, const char *sname) char *upper_sname; DEBUG(10, ("stream_inode called for %lu/%lu [%s]\n", - (unsigned long)sbuf->st_dev, - (unsigned long)sbuf->st_ino, sname)); + (unsigned long)sbuf->st_ex_dev, + (unsigned long)sbuf->st_ex_ino, sname)); upper_sname = talloc_strdup_upper(talloc_tos(), sname); SMB_ASSERT(upper_sname != NULL); MD5Init(&ctx); - MD5Update(&ctx, (unsigned char *)&(sbuf->st_dev), - sizeof(sbuf->st_dev)); - MD5Update(&ctx, (unsigned char *)&(sbuf->st_ino), - sizeof(sbuf->st_ino)); + MD5Update(&ctx, (unsigned char *)&(sbuf->st_ex_dev), + sizeof(sbuf->st_ex_dev)); + MD5Update(&ctx, (unsigned char *)&(sbuf->st_ex_ino), + sizeof(sbuf->st_ex_ino)); MD5Update(&ctx, (unsigned char *)upper_sname, talloc_get_size(upper_sname)-1); MD5Final(hash, &ctx); @@ -159,18 +159,18 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, return -1; } - sbuf->st_size = get_xattr_size(handle->conn, fsp->base_fsp, + sbuf->st_ex_size = get_xattr_size(handle->conn, fsp->base_fsp, io->base, io->xattr_name); - if (sbuf->st_size == -1) { + if (sbuf->st_ex_size == -1) { return -1; } - DEBUG(10, ("sbuf->st_size = %d\n", (int)sbuf->st_size)); + DEBUG(10, ("sbuf->st_ex_size = %d\n", (int)sbuf->st_ex_size)); - sbuf->st_ino = stream_inode(sbuf, io->xattr_name); - sbuf->st_mode &= ~S_IFMT; - sbuf->st_mode |= S_IFREG; - sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1; + sbuf->st_ex_ino = stream_inode(sbuf, io->xattr_name); + sbuf->st_ex_mode &= ~S_IFMT; + sbuf->st_ex_mode |= S_IFREG; + sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1; return 0; } @@ -208,16 +208,16 @@ static int streams_xattr_stat(vfs_handle_struct *handle, const char *fname, goto fail; } - sbuf->st_size = get_xattr_size(handle->conn, NULL, base, xattr_name); - if (sbuf->st_size == -1) { + sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name); + if (sbuf->st_ex_size == -1) { errno = ENOENT; goto fail; } - sbuf->st_ino = stream_inode(sbuf, xattr_name); - sbuf->st_mode &= ~S_IFMT; - sbuf->st_mode |= S_IFREG; - sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1; + sbuf->st_ex_ino = stream_inode(sbuf, xattr_name); + sbuf->st_ex_mode &= ~S_IFMT; + sbuf->st_ex_mode |= S_IFREG; + sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1; result = 0; fail: @@ -259,16 +259,16 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname, goto fail; } - sbuf->st_size = get_xattr_size(handle->conn, NULL, base, xattr_name); - if (sbuf->st_size == -1) { + sbuf->st_ex_size = get_xattr_size(handle->conn, NULL, base, xattr_name); + if (sbuf->st_ex_size == -1) { errno = ENOENT; goto fail; } - sbuf->st_ino = stream_inode(sbuf, xattr_name); - sbuf->st_mode &= ~S_IFMT; - sbuf->st_mode |= S_IFREG; - sbuf->st_blocks = sbuf->st_size % STAT_ST_BLOCKSIZE + 1; + sbuf->st_ex_ino = stream_inode(sbuf, xattr_name); + sbuf->st_ex_mode &= ~S_IFMT; + sbuf->st_ex_mode |= S_IFREG; + sbuf->st_ex_blocks = sbuf->st_ex_size % STAT_ST_BLOCKSIZE + 1; result = 0; fail: @@ -740,10 +740,10 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, state.streams = NULL; state.num_streams = 0; - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { if (!add_one_stream(mem_ctx, &state.num_streams, &state.streams, - "::$DATA", sbuf.st_size, + "::$DATA", sbuf.st_ex_size, SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf))) { return NT_STATUS_NO_MEMORY; diff --git a/source3/modules/vfs_tsmsm.c b/source3/modules/vfs_tsmsm.c index 6fb1d1d2d4..57807105f6 100644 --- a/source3/modules/vfs_tsmsm.c +++ b/source3/modules/vfs_tsmsm.c @@ -153,10 +153,12 @@ static bool tsmsm_is_offline(struct vfs_handle_struct *handle, /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available, then assume it is not offline (it may not be 100%, as it could be sparse) */ - if (512 * (off_t)stbuf->st_blocks >= stbuf->st_size * tsmd->online_ratio) { + if (512 * (off_t)stbuf->st_ex_blocks >= + stbuf->st_ex_size * tsmd->online_ratio) { DEBUG(10,("%s not offline: st_blocks=%ld st_size=%ld " - "online_ratio=%.2f\n", path, (long)stbuf->st_blocks, - (long)stbuf->st_size, tsmd->online_ratio)); + "online_ratio=%.2f\n", path, + (long)stbuf->st_ex_blocks, + (long)stbuf->st_ex_size, tsmd->online_ratio)); return false; } @@ -254,9 +256,10 @@ static bool tsmsm_aio_force(struct vfs_handle_struct *handle, struct files_struc */ if(SMB_VFS_FSTAT(fsp, &sbuf) == 0) { DEBUG(10,("tsmsm_aio_force st_blocks=%ld st_size=%ld " - "online_ratio=%.2f\n", (long)sbuf.st_blocks, - (long)sbuf.st_size, tsmd->online_ratio)); - return !(512 * (off_t)sbuf.st_blocks >= sbuf.st_size * tsmd->online_ratio); + "online_ratio=%.2f\n", (long)sbuf.st_ex_blocks, + (long)sbuf.st_ex_size, tsmd->online_ratio)); + return !(512 * (off_t)sbuf.st_ex_blocks >= + sbuf.st_ex_size * tsmd->online_ratio); } return false; } diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index 0736a66fb8..85729ae7ac 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -164,8 +164,8 @@ void start_async_dns(void) CatchSignal(SIGHUP, SIG_IGN); CatchSignal(SIGTERM, SIGNAL_CAST sig_term ); - if (!reinit_after_fork(nmbd_messaging_context(), - nmbd_event_context(), true)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(), + nmbd_event_context(), true))) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index daf4c295a6..903dc36d53 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -913,8 +913,8 @@ static bool open_sockets(bool isdaemon, int port) pidfile_create("nmbd"); - if (!reinit_after_fork(nmbd_messaging_context(), - nmbd_event_context(), false)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(nmbd_messaging_context(), + nmbd_event_context(), false))) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/pam_smbpass/pam_smb_acct.c b/source3/pam_smbpass/pam_smb_acct.c index 2a8bd26597..9ad74788f0 100644 --- a/source3/pam_smbpass/pam_smb_acct.c +++ b/source3/pam_smbpass/pam_smb_acct.c @@ -58,26 +58,25 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, /* Samba initialization. */ load_case_tables(); - setup_logging( "pam_smbpass", False ); lp_set_in_client(True); - ctrl = set_ctrl( flags, argc, argv ); + ctrl = set_ctrl(pamh, flags, argc, argv ); /* get the username */ retval = pam_get_user( pamh, &name, "Username: " ); if (retval != PAM_SUCCESS) { if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "acct: could not identify user" ); + _log_err(pamh, LOG_DEBUG, "acct: could not identify user" ); } return retval; } if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "acct: username [%s] obtained", name ); + _log_err(pamh, LOG_DEBUG, "acct: username [%s] obtained", name ); } if (geteuid() != 0) { - _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); return PAM_AUTHINFO_UNAVAIL; } @@ -85,7 +84,7 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, from a SIGPIPE it's not expecting */ oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); if (!initialize_password_db(True, NULL)) { - _log_err( LOG_ALERT, "Cannot access samba password database" ); + _log_err(pamh, LOG_ALERT, "Cannot access samba password database" ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_AUTHINFO_UNAVAIL; } @@ -99,7 +98,7 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, } if (!pdb_getsampwnam(sampass, name )) { - _log_err( LOG_DEBUG, "acct: could not identify user" ); + _log_err(pamh, LOG_DEBUG, "acct: could not identify user"); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } @@ -112,8 +111,8 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags, if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) { if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG - , "acct: account %s is administratively disabled", name ); + _log_err(pamh, LOG_DEBUG, + "acct: account %s is administratively disabled", name); } make_remark( pamh, ctrl, PAM_ERROR_MSG , "Your account has been disabled; " diff --git a/source3/pam_smbpass/pam_smb_auth.c b/source3/pam_smbpass/pam_smb_auth.c index b5a6a473b6..88ff9851f5 100644 --- a/source3/pam_smbpass/pam_smb_auth.c +++ b/source3/pam_smbpass/pam_smb_auth.c @@ -81,10 +81,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, /* Samba initialization. */ load_case_tables(); - setup_logging("pam_smbpass",False); lp_set_in_client(True); - ctrl = set_ctrl(flags, argc, argv); + ctrl = set_ctrl(pamh, flags, argc, argv); /* Get a few bytes so we can pass our return value to pam_sm_setcred(). */ @@ -99,29 +98,29 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, retval = pam_get_user( pamh, &name, "Username: " ); if ( retval != PAM_SUCCESS ) { if (on( SMB_DEBUG, ctrl )) { - _log_err(LOG_DEBUG, "auth: could not identify user"); + _log_err(pamh, LOG_DEBUG, "auth: could not identify user"); } AUTH_RETURN; } if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "username [%s] obtained", name ); + _log_err(pamh, LOG_DEBUG, "username [%s] obtained", name ); } if (geteuid() != 0) { - _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); retval = PAM_AUTHINFO_UNAVAIL; AUTH_RETURN; } if (!initialize_password_db(True, NULL)) { - _log_err( LOG_ALERT, "Cannot access samba password database" ); + _log_err(pamh, LOG_ALERT, "Cannot access samba password database" ); retval = PAM_AUTHINFO_UNAVAIL; AUTH_RETURN; } sampass = samu_new( NULL ); if (!sampass) { - _log_err( LOG_ALERT, "Cannot talloc a samu struct" ); + _log_err(pamh, LOG_ALERT, "Cannot talloc a samu struct" ); retval = nt_status_to_pam(NT_STATUS_NO_MEMORY); AUTH_RETURN; } @@ -135,7 +134,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, } if (!found) { - _log_err(LOG_ALERT, "Failed to find entry for user %s.", name); + _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", name); retval = PAM_USER_UNKNOWN; TALLOC_FREE(sampass); sampass = NULL; @@ -154,7 +153,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, retval = _smb_read_password(pamh, ctrl, NULL, "Password: ", NULL, _SMB_AUTHTOK, &p); if (retval != PAM_SUCCESS ) { - _log_err(LOG_CRIT, "auth: no password provided for [%s]", name); + _log_err(pamh,LOG_CRIT, "auth: no password provided for [%s]", name); TALLOC_FREE(sampass); AUTH_RETURN; } @@ -202,7 +201,7 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl, retval = _pam_get_item( pamh, PAM_AUTHTOK, &pass ); if (retval != PAM_SUCCESS) { - _log_err( LOG_ALERT + _log_err(pamh, LOG_ALERT , "pam_get_item returned error to pam_sm_authenticate" ); return PAM_AUTHTOK_RECOVER_ERR; } else if (pass == NULL) { diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c index dce6e01ae9..9504e4d53c 100644 --- a/source3/pam_smbpass/pam_smb_passwd.c +++ b/source3/pam_smbpass/pam_smb_passwd.c @@ -106,10 +106,9 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, /* Samba initialization. */ load_case_tables(); - setup_logging( "pam_smbpass", False ); lp_set_in_client(True); - ctrl = set_ctrl(flags, argc, argv); + ctrl = set_ctrl(pamh, flags, argc, argv); /* * First get the name of a user. No need to do anything if we can't @@ -119,16 +118,16 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = pam_get_user( pamh, &user, "Username: " ); if (retval != PAM_SUCCESS) { if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "password: could not identify user" ); + _log_err(pamh, LOG_DEBUG, "password: could not identify user"); } return retval; } if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "username [%s] obtained", user ); + _log_err(pamh, LOG_DEBUG, "username [%s] obtained", user); } if (geteuid() != 0) { - _log_err( LOG_DEBUG, "Cannot access samba password database, not running as root."); + _log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root."); return PAM_AUTHINFO_UNAVAIL; } @@ -137,7 +136,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); if (!initialize_password_db(False, NULL)) { - _log_err( LOG_ALERT, "Cannot access samba password database" ); + _log_err(pamh, LOG_ALERT, "Cannot access samba password database" ); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_AUTHINFO_UNAVAIL; } @@ -149,12 +148,12 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } if (!pdb_getsampwnam(sampass,user)) { - _log_err( LOG_ALERT, "Failed to find entry for user %s.", user ); + _log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", user); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_USER_UNKNOWN; } if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_DEBUG, "Located account for %s", user ); + _log_err(pamh, LOG_DEBUG, "Located account for %s", user); } if (flags & PAM_PRELIM_CHECK) { @@ -180,7 +179,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, #define greeting "Changing password for " Announce = SMB_MALLOC_ARRAY(char, sizeof(greeting)+strlen(user)); if (Announce == NULL) { - _log_err(LOG_CRIT, "password: out of memory"); + _log_err(pamh, LOG_CRIT, "password: out of memory"); TALLOC_FREE(sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return PAM_BUF_ERR; @@ -195,8 +194,8 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, SAFE_FREE( Announce ); if (retval != PAM_SUCCESS) { - _log_err( LOG_NOTICE - , "password - (old) token not obtained" ); + _log_err(pamh, LOG_NOTICE, + "password - (old) token not obtained"); TALLOC_FREE(sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; @@ -241,7 +240,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } if (retval != PAM_SUCCESS) { - _log_err( LOG_NOTICE, "password: user not authenticated" ); + _log_err(pamh, LOG_NOTICE, "password: user not authenticated"); TALLOC_FREE(sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); return retval; @@ -266,8 +265,8 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, if (retval != PAM_SUCCESS) { if (on( SMB_DEBUG, ctrl )) { - _log_err( LOG_ALERT - , "password: new password not obtained" ); + _log_err(pamh, LOG_ALERT, + "password: new password not obtained"); } pass_old = NULL; /* tidy up */ TALLOC_FREE(sampass); @@ -288,7 +287,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new); if (retval != PAM_SUCCESS) { - _log_err(LOG_NOTICE, "new password not acceptable"); + _log_err(pamh, LOG_NOTICE, "new password not acceptable"); pass_new = pass_old = NULL; /* tidy up */ TALLOC_FREE(sampass); CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler); @@ -308,16 +307,17 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, /* password updated */ if (!sid_to_uid(pdb_get_user_sid(sampass), &uid)) { - _log_err( LOG_NOTICE, "Unable to get uid for user %s", + _log_err(pamh, LOG_NOTICE, + "Unable to get uid for user %s", pdb_get_username(sampass)); - _log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)", + _log_err(pamh, LOG_NOTICE, "password for (%s) changed by (%s/%d)", user, uidtoname(getuid()), getuid()); } else { - _log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)", + _log_err(pamh, LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)", user, uid, uidtoname(getuid()), getuid()); } } else { - _log_err( LOG_ERR, "password change failed for user %s", user); + _log_err(pamh, LOG_ERR, "password change failed for user %s", user); } pass_old = pass_new = NULL; @@ -328,7 +328,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, } else { /* something has broken with the library */ - _log_err( LOG_ALERT, "password received unknown request" ); + _log_err(pamh, LOG_ALERT, "password received unknown request"); retval = PAM_ABORT; } diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c index b6cf3a886d..855885a6d7 100644 --- a/source3/pam_smbpass/support.c +++ b/source3/pam_smbpass/support.c @@ -14,6 +14,7 @@ * this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "config.h" #include "includes.h" #include "general.h" @@ -64,17 +65,42 @@ void _cleanup(pam_handle_t *, void *, int); char *_pam_delete(register char *); /* syslogging function for errors and other information */ +#ifdef HAVE_PAM_VSYSLOG +void _log_err( pam_handle_t *pamh, int err, const char *format, ... ) +{ + va_list args; -void _log_err( int err, const char *format, ... ) + va_start(args, format); + pam_vsyslog(pamh, err, format, args); + va_end(args); +} +#else +void _log_err( pam_handle_t *pamh, int err, const char *format, ... ) { - va_list args; + va_list args; + const char tag[] = "(pam_smbpass) "; + char *mod_format; + + mod_format = SMB_MALLOC_ARRAY(char, sizeof(tag) + strlen(format)); + /* try really, really hard to log something, since this may have + been a message about a malloc() failure... */ + if (mod_format == NULL) { + va_start(args, format); + vsyslog(err | LOG_AUTH, format, args); + va_end(args); + return; + } - va_start( args, format ); - openlog( "PAM_smbpass", LOG_CONS | LOG_PID, LOG_AUTH ); - vsyslog( err, format, args ); - va_end( args ); - closelog(); + strncpy(mod_format, tag, strlen(tag)+1); + strncat(mod_format, format, strlen(format)); + + va_start(args, format); + vsyslog(err | LOG_AUTH, mod_format, args); + va_end(args); + + free(mod_format); } +#endif /* this is a front-end for module-application conversations */ @@ -92,11 +118,11 @@ int converse( pam_handle_t * pamh, int ctrl, int nargs ,response, conv->appdata_ptr); if (retval != PAM_SUCCESS && on(SMB_DEBUG, ctrl)) { - _log_err(LOG_DEBUG, "conversation failure [%s]" + _log_err(pamh, LOG_DEBUG, "conversation failure [%s]" ,pam_strerror(pamh, retval)); } } else { - _log_err(LOG_ERR, "couldn't obtain coversation function [%s]" + _log_err(pamh, LOG_ERR, "couldn't obtain coversation function [%s]" ,pam_strerror(pamh, retval)); } @@ -123,7 +149,7 @@ int make_remark( pam_handle_t * pamh, unsigned int ctrl /* set the control flags for the SMB module. */ -int set_ctrl( int flags, int argc, const char **argv ) +int set_ctrl( pam_handle_t *pamh, int flags, int argc, const char **argv ) { int i = 0; const char *service_file = NULL; @@ -165,7 +191,7 @@ int set_ctrl( int flags, int argc, const char **argv ) /* Read some options from the Samba config. Can be overridden by the PAM config. */ if(lp_load(service_file,True,False,False,True) == False) { - _log_err( LOG_ERR, "Error loading service file %s", service_file ); + _log_err(pamh, LOG_ERR, "Error loading service file %s", service_file); } secrets_init(); @@ -188,7 +214,7 @@ int set_ctrl( int flags, int argc, const char **argv ) } if (j >= SMB_CTRLS_) { - _log_err( LOG_ERR, "unrecognized option [%s]", *argv ); + _log_err(pamh, LOG_ERR, "unrecognized option [%s]", *argv); } else { ctrl &= smb_args[j].mask; /* for turning things off */ ctrl |= smb_args[j].flag; /* for turning things on */ @@ -227,7 +253,7 @@ void _cleanup( pam_handle_t * pamh, void *x, int error_status ) * evidence of old token around for later stack analysis. * */ -char * smbpXstrDup( const char *x ) +char * smbpXstrDup( pam_handle_t *pamh, const char *x ) { register char *newstr = NULL; @@ -237,7 +263,7 @@ char * smbpXstrDup( const char *x ) for (i = 0; x[i]; ++i); /* length of string */ if ((newstr = SMB_MALLOC_ARRAY(char, ++i)) == NULL) { i = 0; - _log_err( LOG_CRIT, "out of memory in smbpXstrDup" ); + _log_err(pamh, LOG_CRIT, "out of memory in smbpXstrDup"); } else { while (i-- > 0) { newstr[i] = x[i]; @@ -279,7 +305,7 @@ void _cleanup_failures( pam_handle_t * pamh, void *fl, int err ) /* log the number of authentication failures */ if (failure->count != 0) { _pam_get_item( pamh, PAM_SERVICE, &service ); - _log_err( LOG_NOTICE + _log_err(pamh, LOG_NOTICE , "%d authentication %s " "from %s for service %s as %s(%d)" , failure->count @@ -288,7 +314,7 @@ void _cleanup_failures( pam_handle_t * pamh, void *fl, int err ) , service == NULL ? "**unknown**" : service , failure->user, failure->id ); if (failure->count > SMB_MAX_RETRIES) { - _log_err( LOG_ALERT + _log_err(pamh, LOG_ALERT , "service(%s) ignoring max retries; %d > %d" , service == NULL ? "**unknown**" : service , failure->count @@ -324,8 +350,7 @@ int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass, if (!pdb_get_nt_passwd(sampass)) { - _log_err( LOG_DEBUG, "user %s has null SMB password" - , name ); + _log_err(pamh, LOG_DEBUG, "user %s has null SMB password", name); if (off( SMB__NONULL, ctrl ) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) @@ -335,7 +360,7 @@ int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass, const char *service; _pam_get_item( pamh, PAM_SERVICE, &service ); - _log_err( LOG_NOTICE, "failed auth request by %s for service %s as %s", + _log_err(pamh, LOG_NOTICE, "failed auth request by %s for service %s as %s", uidtoname(getuid()), service ? service : "**unknown**", name); return PAM_AUTH_ERR; } @@ -343,7 +368,7 @@ int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass, data_name = SMB_MALLOC_ARRAY(char, sizeof(FAIL_PREFIX) + strlen( name )); if (data_name == NULL) { - _log_err( LOG_CRIT, "no memory for data-name" ); + _log_err(pamh, LOG_CRIT, "no memory for data-name" ); return PAM_AUTH_ERR; } strncpy( data_name, FAIL_PREFIX, sizeof(FAIL_PREFIX) ); @@ -390,31 +415,31 @@ int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass, retval = PAM_MAXTRIES; } } else { - _log_err(LOG_NOTICE, + _log_err(pamh, LOG_NOTICE, "failed auth request by %s for service %s as %s", uidtoname(getuid()), service ? service : "**unknown**", name); newauth->count = 1; } if (!sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id))) { - _log_err(LOG_NOTICE, + _log_err(pamh, LOG_NOTICE, "failed auth request by %s for service %s as %s", uidtoname(getuid()), service ? service : "**unknown**", name); } - newauth->user = smbpXstrDup( name ); - newauth->agent = smbpXstrDup( uidtoname( getuid() ) ); + newauth->user = smbpXstrDup( pamh, name ); + newauth->agent = smbpXstrDup( pamh, uidtoname( getuid() ) ); pam_set_data( pamh, data_name, newauth, _cleanup_failures ); } else { - _log_err( LOG_CRIT, "no memory for failure recorder" ); - _log_err(LOG_NOTICE, + _log_err(pamh, LOG_CRIT, "no memory for failure recorder" ); + _log_err(pamh, LOG_NOTICE, "failed auth request by %s for service %s as %s(%d)", uidtoname(getuid()), service ? service : "**unknown**", name); } } - _log_err(LOG_NOTICE, + _log_err(pamh, LOG_NOTICE, "failed auth request by %s for service %s as %s(%d)", uidtoname(getuid()), service ? service : "**unknown**", name); @@ -422,7 +447,7 @@ int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass, } _pam_delete( data_name ); - + return retval; } @@ -490,8 +515,8 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, retval = _pam_get_item( pamh, authtok_flag, &item ); if (retval != PAM_SUCCESS) { /* very strange. */ - _log_err( LOG_ALERT - , "pam_get_item returned error to smb_read_password" ); + _log_err(pamh, LOG_ALERT, + "pam_get_item returned error to smb_read_password"); return retval; } else if (item != NULL) { /* we have a password! */ *pass = item; @@ -543,7 +568,7 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, if (retval == PAM_SUCCESS) { /* a good conversation */ - token = smbpXstrDup(resp[j++].resp); + token = smbpXstrDup(pamh, resp[j++].resp); if (token != NULL) { if (expect == 2) { /* verify that password entered correctly */ @@ -555,7 +580,8 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, } } } else { - _log_err(LOG_NOTICE, "could not recover authentication token"); + _log_err(pamh, LOG_NOTICE, + "could not recover authentication token"); } } @@ -568,7 +594,7 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, if (retval != PAM_SUCCESS) { if (on( SMB_DEBUG, ctrl )) - _log_err( LOG_DEBUG, "unable to obtain a password" ); + _log_err(pamh, LOG_DEBUG, "unable to obtain a password"); return retval; } /* 'token' is the entered password */ @@ -583,7 +609,7 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, || (retval = _pam_get_item( pamh, authtok_flag ,&item )) != PAM_SUCCESS) { - _log_err( LOG_CRIT, "error manipulating password" ); + _log_err(pamh, LOG_CRIT, "error manipulating password"); return retval; } } else { @@ -597,8 +623,8 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl, || (retval = _pam_get_data( pamh, data_name, &item )) != PAM_SUCCESS) { - _log_err( LOG_CRIT, "error manipulating password data [%s]" - , pam_strerror( pamh, retval )); + _log_err(pamh, LOG_CRIT, "error manipulating password data [%s]", + pam_strerror( pamh, retval )); _pam_delete( token ); item = NULL; return retval; @@ -622,8 +648,8 @@ int _pam_smb_approve_pass(pam_handle_t * pamh, if (pass_new == NULL || (pass_old && !strcmp( pass_old, pass_new ))) { if (on(SMB_DEBUG, ctrl)) { - _log_err( LOG_DEBUG, - "passwd: bad authentication token (null or unchanged)" ); + _log_err(pamh, LOG_DEBUG, + "passwd: bad authentication token (null or unchanged)"); } make_remark( pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ? "No password supplied" : "Password unchanged" ); diff --git a/source3/pam_smbpass/support.h b/source3/pam_smbpass/support.h index 87f1690a60..7ee77042d7 100644 --- a/source3/pam_smbpass/support.h +++ b/source3/pam_smbpass/support.h @@ -1,8 +1,8 @@ /* syslogging function for errors and other information */ -extern void _log_err(int, const char *, ...); +extern void _log_err(pam_handle_t *, int, const char *, ...); /* set the control flags for the UNIX module. */ -extern int set_ctrl(int, int, const char **); +extern int set_ctrl(pam_handle_t *, int, int, const char **); /* generic function for freeing pam data segments */ extern void _cleanup(pam_handle_t *, void *, int); @@ -12,7 +12,7 @@ extern void _cleanup(pam_handle_t *, void *, int); * evidence of old token around for later stack analysis. */ -extern char *smbpXstrDup(const char *); +extern char *smbpXstrDup(pam_handle_t *,const char *); /* ************************************************************** * * Useful non-trivial functions * diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 6da792a8d7..57fdb6e044 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -351,6 +351,7 @@ struct global { int cups_connection_timeout; char *szSMBPerfcountModule; bool bMapUntrustedToDomain; + bool bFakeDirCreateTimes; }; static struct global Globals; @@ -362,7 +363,7 @@ struct service { bool valid; bool autoloaded; int usershare; - time_t usershare_last_mod; + struct timespec usershare_last_mod; char *szService; char *szPath; char *szUsername; @@ -468,7 +469,6 @@ struct service { bool bDosFilemode; bool bDosFiletimes; bool bDosFiletimeResolution; - bool bFakeDirCreateTimes; bool bBlockingLocks; bool bInheritPerms; bool bInheritACLS; @@ -506,7 +506,7 @@ static struct service sDefault = { True, /* valid */ False, /* not autoloaded */ 0, /* not a usershare */ - (time_t)0, /* No last mod time */ + {0, }, /* No last mod time */ NULL, /* szService */ NULL, /* szPath */ NULL, /* szUsername */ @@ -612,7 +612,6 @@ static struct service sDefault = { False, /* bDosFilemode */ True, /* bDosFiletimes */ False, /* bDosFiletimeResolution */ - False, /* bFakeDirCreateTimes */ True, /* bBlockingLocks */ False, /* bInheritPerms */ False, /* bInheritACLS */ @@ -4274,11 +4273,11 @@ static struct parm_struct parm_table[] = { { .label = "fake directory create times", .type = P_BOOL, - .p_class = P_LOCAL, - .ptr = &sDefault.bFakeDirCreateTimes, + .p_class = P_GLOBAL, + .ptr = &Globals.bFakeDirCreateTimes, .special = NULL, .enum_list = NULL, - .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL, + .flags = FLAG_ADVANCED | FLAG_GLOBAL, }, { .label = "panic action", @@ -5000,7 +4999,7 @@ static void init_globals(bool first_time_only) a large number of sites (tridge) */ Globals.bHostnameLookups = False; - string_set(&Globals.szPassdbBackend, "smbpasswd"); + string_set(&Globals.szPassdbBackend, "tdbsam"); string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapMachineSuffix, ""); string_set(&Globals.szLdapUserSuffix, ""); @@ -5584,7 +5583,7 @@ FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles) FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode) FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes) FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution) -FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes) +FN_GLOBAL_BOOL(lp_fake_dir_create_times, &Globals.bFakeDirCreateTimes) FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks) FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms) FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS) @@ -8330,27 +8329,27 @@ static void set_allowed_client_auth(void) static bool check_usershare_stat(const char *fname, const SMB_STRUCT_STAT *psbuf) { - if (!S_ISREG(psbuf->st_mode)) { + if (!S_ISREG(psbuf->st_ex_mode)) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u is " "not a regular file\n", - fname, (unsigned int)psbuf->st_uid )); + fname, (unsigned int)psbuf->st_ex_uid )); return False; } /* Ensure this doesn't have the other write bit set. */ - if (psbuf->st_mode & S_IWOTH) { + if (psbuf->st_ex_mode & S_IWOTH) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows " "public write. Refusing to allow as a usershare file.\n", - fname, (unsigned int)psbuf->st_uid )); + fname, (unsigned int)psbuf->st_ex_uid )); return False; } /* Should be 10k or less. */ - if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) { + if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u is " "too large (%u) to be a user share file.\n", - fname, (unsigned int)psbuf->st_uid, - (unsigned int)psbuf->st_size )); + fname, (unsigned int)psbuf->st_ex_uid, + (unsigned int)psbuf->st_ex_size )); return False; } @@ -8509,7 +8508,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, sys_closedir(dp); - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n", servicename, sharepath )); return USERSHARE_PATH_NOT_DIRECTORY; @@ -8521,7 +8520,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, if (lp_usershare_owner_only()) { /* root can share anything. */ - if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) { + if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) { return USERSHARE_PATH_NOT_ALLOWED; } } @@ -8599,7 +8598,9 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i TALLOC_FREE(canon_name); } - if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) { + if (iService != -1 && + timespec_compare(&ServicePtrs[iService]->usershare_last_mod, + &lsbuf.st_ex_mtime) == 0) { /* Nothing changed - Mark valid and return. */ DEBUG(10,("process_usershare_file: service %s not changed.\n", service_name )); @@ -8632,7 +8633,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i } /* Is it the same dev/inode as was lstated ? */ - if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) { + if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) { close(fd); DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. " "Symlink spoofing going on ?\n", fname )); @@ -8652,7 +8653,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i close(fd); if (lines == NULL) { DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n", - fname, (unsigned int)sbuf.st_uid )); + fname, (unsigned int)sbuf.st_ex_uid )); SAFE_FREE(fname); return -1; } @@ -8716,7 +8717,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i } /* And note when it was loaded. */ - ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime; + ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime; string_set(&ServicePtrs[iService]->szPath, sharepath); string_set(&ServicePtrs[iService]->comment, comment); @@ -8729,7 +8730,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i Checks if a usershare entry has been modified since last load. ***************************************************************************/ -static bool usershare_exists(int iService, time_t *last_mod) +static bool usershare_exists(int iService, struct timespec *last_mod) { SMB_STRUCT_STAT lsbuf; const char *usersharepath = Globals.szUsersharePath; @@ -8746,13 +8747,13 @@ static bool usershare_exists(int iService, time_t *last_mod) return false; } - if (!S_ISREG(lsbuf.st_mode)) { + if (!S_ISREG(lsbuf.st_ex_mode)) { SAFE_FREE(fname); return false; } SAFE_FREE(fname); - *last_mod = lsbuf.st_mtime; + *last_mod = lsbuf.st_ex_mtime; return true; } @@ -8777,7 +8778,7 @@ int load_usershare_service(const char *servicename) return -1; } - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { DEBUG(0,("load_usershare_service: %s is not a directory.\n", usersharepath )); return -1; @@ -8789,9 +8790,9 @@ int load_usershare_service(const char *servicename) */ #ifdef S_ISVTX - if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) { #else - if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) { #endif DEBUG(0,("load_usershare_service: directory %s is not owned by root " "or does not have the sticky bit 't' set or is writable by anyone.\n", @@ -8860,9 +8861,9 @@ int load_usershare_shares(void) */ #ifdef S_ISVTX - if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) { #else - if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) { #endif DEBUG(0,("load_usershare_shares: directory %s is not owned by root " "or does not have the sticky bit 't' set or is writable by anyone.\n", @@ -9263,7 +9264,7 @@ int lp_servicenumber(const char *pszServiceName) } if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) { - time_t last_mod; + struct timespec last_mod; if (!usershare_exists(iService, &last_mod)) { /* Remove the share security tdb entry for it. */ @@ -9275,7 +9276,8 @@ int lp_servicenumber(const char *pszServiceName) } /* Has it been modified ? If so delete and reload. */ - if (ServicePtrs[iService]->usershare_last_mod < last_mod) { + if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod, + &last_mod) < 0) { /* Remove it from the array. */ free_service_byindex(iService); /* and now reload it. */ diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index b45000e77e..3a03cfe081 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -468,12 +468,15 @@ static bool lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, sid_string_dbg(domain_sid))); if (num_rids) { - *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids); + *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); if ((*names == NULL) || (*types == NULL)) { return false; } + + for (i = 0; i < num_rids; i++) + (*types)[i] = SID_NAME_UNKNOWN; } else { *names = NULL; *types = NULL; diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index d663c7f0b2..8074b2e3a1 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -292,7 +292,7 @@ Error was %s\n", pfile, strerror(errno))); return NULL; } - if( sbuf1.st_ino == sbuf2.st_ino) { + if( sbuf1.st_ex_ino == sbuf2.st_ex_ino) { /* No race. */ break; } diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 39e9661bd6..a05e0def7b 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1352,7 +1352,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr if (SMB_VFS_FSTAT(fsp, &st) == -1) { goto error_exit; } - old_create_time = st.st_mtime; + old_create_time = convert_timespec_to_time_t(st.st_ex_mtime); DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", (long)old_create_time)); } @@ -1404,7 +1404,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr if (SMB_VFS_FSTAT(fsp, &st) == -1) { goto error_exit; } - new_create_time = st.st_mtime; + new_create_time = convert_timespec_to_time_t(st.st_ex_mtime); DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", (long)new_create_time)); } diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index 7edfb5edbe..18f42138c9 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -433,8 +433,8 @@ static bool cups_pcap_load_async(int *pfd) close_all_print_db(); - if (!reinit_after_fork(smbd_messaging_context(), - smbd_event_context(), true)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), true))) { DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n")); smb_panic("cups_pcap_load_async: reinit_after_fork() failed"); } diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index 243b8ea03b..a8e175a684 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -75,7 +75,7 @@ NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn, string_set(&fsp->fsp_name,print_job_fname(lp_const_servicename(SNUM(conn)),jobid)); fsp->wcp = NULL; SMB_VFS_FSTAT(fsp, psbuf); - fsp->mode = psbuf->st_mode; + fsp->mode = psbuf->st_ex_mode; fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); return NT_STATUS_OK; diff --git a/source3/printing/printing.c b/source3/printing/printing.c index ce98792096..e73669fef5 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1436,8 +1436,9 @@ void start_background_queue(void) close(pause_pipe[0]); pause_pipe[0] = -1; - if (!reinit_after_fork(smbd_messaging_context(), - smbd_event_context(), true)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), + true))) { DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } @@ -2563,7 +2564,7 @@ bool print_job_end(int snum, uint32 jobid, enum file_close_type close_type) if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && (sys_fstat(pjob->fd, &sbuf) == 0)) { - pjob->size = sbuf.st_size; + pjob->size = sbuf.st_ex_size; close(pjob->fd); pjob->fd = -1; } else { diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index cc6a6f4103..38411d8556 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -84,7 +84,7 @@ static int read_block( REGF_FILE *file, prs_struct *ps, uint32 file_offset, uint return -1; } - if ( (size_t)file_offset >= sbuf.st_size ) + if ( (size_t)file_offset >= sbuf.st_ex_size ) return -1; /* if block_size == 0, we are parsing HBIN records and need @@ -1434,7 +1434,7 @@ static REGF_HBIN* regf_hbin_allocate( REGF_FILE *file, uint32 block_size ) return NULL; } - hbin->file_off = sbuf.st_size; + hbin->file_off = sbuf.st_ex_size; hbin->free_off = HBIN_HEADER_REC_SIZE; hbin->free_size = block_size - hbin->free_off + sizeof(uint32);; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index d23b509af2..9aab3a7405 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -103,7 +103,7 @@ static void check_magic(struct files_struct *fsp) return; } - transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size); + transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size); close(tmp_fd); close(outfd); TALLOC_FREE(ctx); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ab4a0d27e3..f5a9e22d14 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -824,7 +824,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, char **pp_fname_out, SMB_OFF_T *size, uint32 *mode, - time_t *date, + struct timespec *date, bool check_descend, bool ask_sharemode) { @@ -910,8 +910,8 @@ bool get_dir_entry(TALLOC_CTX *ctx, continue; } - *size = sbuf.st_size; - *date = sbuf.st_mtime; + *size = sbuf.st_ex_size; + *date = sbuf.st_ex_mtime; if (ask_sharemode) { struct timespec write_time_ts; @@ -920,7 +920,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, fileid = vfs_file_id_from_sbuf(conn, &sbuf); get_file_infos(fileid, NULL, &write_time_ts); if (!null_timespec(write_time_ts)) { - *date = convert_timespec_to_time_t(write_time_ts); + *date = write_time_ts; } } @@ -989,7 +989,7 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ /* Pseudo-open the file */ - if(S_ISDIR(pst->st_mode)) { + if(S_ISDIR(pst->st_ex_mode)) { return True; } @@ -1012,7 +1012,7 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT SMB_ASSERT(VALID_STAT(*pst)); - if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) + if (S_ISREG(pst->st_ex_mode) || S_ISDIR(pst->st_ex_mode) || S_ISLNK(pst->st_ex_mode)) return False; return True; diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 5ae7151303..6468544748 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -3,17 +3,17 @@ dos mode handling functions Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) James Peach 2006 - + 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/>. */ @@ -23,7 +23,7 @@ static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf) { #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) - if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) { + if (sbuf->st_ex_size > sbuf->st_ex_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) { return FILE_ATTRIBUTE_SPARSE; } #endif @@ -88,7 +88,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, } /* Save for later - but explicitly remove setuid bit for safety. */ - dir_mode = sbuf.st_mode & ~S_ISUID; + dir_mode = sbuf.st_ex_mode & ~S_ISUID; DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode)); /* Clear "result" */ result = 0; @@ -117,7 +117,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode)) result |= S_IXGRP; - + if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode)) result |= S_IXOTH; @@ -147,7 +147,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ if (ro_opts == MAP_READONLY_YES) { /* Original Samba method - map inverse of user "w" bit. */ - if ((sbuf->st_mode & S_IWUSR) == 0) { + if ((sbuf->st_ex_mode & S_IWUSR) == 0) { result |= aRONLY; } } else if (ro_opts == MAP_READONLY_PERMISSIONS) { @@ -157,16 +157,16 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ } } /* Else never set the readonly bit. */ - if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0)) + if (MAP_ARCHIVE(conn) && ((sbuf->st_ex_mode & S_IXUSR) != 0)) result |= aARCH; - if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0)) + if (MAP_SYSTEM(conn) && ((sbuf->st_ex_mode & S_IXGRP) != 0)) result |= aSYSTEM; - - if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0)) + + if (MAP_HIDDEN(conn) && ((sbuf->st_ex_mode & S_IXOTH) != 0)) result |= aHIDDEN; - - if (S_ISDIR(sbuf->st_mode)) + + if (S_ISDIR(sbuf->st_ex_mode)) result = aDIR | (result & aRONLY); result |= set_sparse_flag(sbuf); @@ -179,7 +179,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ if (result & aSYSTEM) DEBUG(8, ("s")); if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); - + DEBUG(8,("\n")); return result; } @@ -225,7 +225,7 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S return False; } - if (S_ISDIR(sbuf->st_mode)) { + if (S_ISDIR(sbuf->st_ex_mode)) { dosattr |= aDIR; } *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK); @@ -237,7 +237,7 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S if (dosattr & aSYSTEM) DEBUG(8, ("s")); if (dosattr & aDIR ) DEBUG(8, ("d")); if (dosattr & aARCH ) DEBUG(8, ("a")); - + DEBUG(8,("\n")); return True; @@ -332,7 +332,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT result |= aHIDDEN; } } - + result |= dos_mode_from_sbuf(conn, path, sbuf); /* Optimization : Only call is_hidden_path if it's not already @@ -349,7 +349,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); - + DEBUG(8,("\n")); return(result); @@ -406,7 +406,7 @@ static bool get_stat_dos_flags(connection_struct *conn, *dosmode |= aSYSTEM; if (sbuf->st_flags & UF_DOS_NOINDEX) *dosmode |= FILE_ATTRIBUTE_NONINDEXED; - if (S_ISDIR(sbuf->st_mode)) + if (S_ISDIR(sbuf->st_ex_mode)) *dosmode |= aDIR; *dosmode |= set_sparse_flag(sbuf); @@ -493,7 +493,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) result |= aHIDDEN; } } - + #ifdef HAVE_STAT_DOS_FLAGS used_stat_dos_flags = get_stat_dos_flags(conn, path, sbuf, &result); #endif @@ -506,9 +506,8 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) } } - offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf); - if (S_ISREG(sbuf->st_mode) && offline) { + if (S_ISREG(sbuf->st_ex_mode) && offline) { result |= FILE_ATTRIBUTE_OFFLINE; } @@ -526,7 +525,7 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) if (result & aDIR ) DEBUG(8, ("d")); if (result & aARCH ) DEBUG(8, ("a")); if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]")); - + DEBUG(8,("\n")); return(result); @@ -563,17 +562,17 @@ int file_set_dosmode(connection_struct *conn, const char *fname, return(-1); } - unixmode = st->st_mode; + unixmode = st->st_ex_mode; - get_acl_group_bits(conn, fname, &st->st_mode); + get_acl_group_bits(conn, fname, &st->st_ex_mode); - if (S_ISDIR(st->st_mode)) + if (S_ISDIR(st->st_ex_mode)) dosmode |= aDIR; else dosmode &= ~aDIR; old_mode = dos_mode(conn,fname,st); - + if (dosmode & FILE_ATTRIBUTE_OFFLINE) { if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) { lret = SMB_VFS_SET_OFFLINE(conn, fname); @@ -590,7 +589,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, old_mode &= ~FILE_ATTRIBUTE_OFFLINE; if (old_mode == dosmode) { - st->st_mode = unixmode; + st->st_ex_mode = unixmode; return(0); } @@ -605,7 +604,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } - st->st_mode = unixmode; + st->st_ex_mode = unixmode; return 0; } } @@ -617,7 +616,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } - st->st_mode = unixmode; + st->st_ex_mode = unixmode; return 0; } @@ -639,10 +638,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname, if (!MAP_HIDDEN(conn)) mask |= S_IXOTH; - unixmode |= (st->st_mode & mask); + unixmode |= (st->st_ex_mode & mask); /* if we previously had any r bits set then leave them alone */ - if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { + if ((tmp = st->st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); unixmode |= tmp; } @@ -650,7 +649,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, /* if we previously had any w bits set then leave them alone whilst adding in the new w bits, if the new mode is not rdonly */ if (!IS_DOS_READONLY(dosmode)) { - unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); + unixmode |= (st->st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } ret = SMB_VFS_CHMOD(conn, fname, unixmode); @@ -659,7 +658,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } - st->st_mode = unixmode; + st->st_ex_mode = unixmode; return 0; } @@ -696,7 +695,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); } if (ret == 0) { - st->st_mode = unixmode; + st->st_ex_mode = unixmode; } } diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index abffcd2f4f..a248dd9f3b 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -80,7 +80,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) /* fast paths first */ - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { return False; } if (conn->server_info->utok.uid == 0 || conn->admin_user) { @@ -90,7 +90,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) #ifdef S_ISVTX /* sticky bit means delete only by owner or root. */ - if (sbuf.st_mode & S_ISVTX) { + if (sbuf.st_ex_mode & S_ISVTX) { SMB_STRUCT_STAT sbuf_file; if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { if (errno == ENOENT) { @@ -105,7 +105,7 @@ bool can_delete_file_in_directory(connection_struct *conn, const char *fname) * for bug #3348. Don't assume owning sticky bit * directory means write access allowed. */ - if (conn->server_info->utok.uid != sbuf_file.st_uid) { + if (conn->server_info->utok.uid != sbuf_file.st_ex_uid) { return False; } } @@ -156,17 +156,17 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT } /* Check primary owner access. */ - if (conn->server_info->utok.uid == psbuf->st_uid) { + if (conn->server_info->utok.uid == psbuf->st_ex_uid) { switch (access_mask) { case FILE_READ_DATA: - return (psbuf->st_mode & S_IRUSR) ? True : False; + return (psbuf->st_ex_mode & S_IRUSR) ? True : False; case FILE_WRITE_DATA: - return (psbuf->st_mode & S_IWUSR) ? True : False; + return (psbuf->st_ex_mode & S_IWUSR) ? True : False; default: /* FILE_READ_DATA|FILE_WRITE_DATA */ - if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { + if ((psbuf->st_ex_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) { return True; } else { return False; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index adf664b396..de5f83c868 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -296,7 +296,7 @@ ssize_t write_file(struct smb_request *req, */ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { - setup_write_cache(fsp, st.st_size); + setup_write_cache(fsp, st.st_ex_size); wcp = fsp->wcp; } } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 36503483a8..72b4ab7aa6 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -424,7 +424,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * It exists. it must either be a directory or this must * be the last part of the path for it to be OK. */ - if (end && !(st.st_mode & S_IFDIR)) { + if (end && !S_ISDIR(st.st_ex_mode)) { /* * An intermediate part of the name isn't * a directory. diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 9e7d103562..3dc057e18d 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -127,7 +127,6 @@ int max_send = BUFFER_SIZE; int max_recv = BUFFER_SIZE; uint16 last_session_tag = UID_FIELD_INVALID; int trans_num = 0; -char *orig_inbuf = NULL; pid_t mypid = 0; time_t last_smb_conf_reload_time = 0; time_t last_printer_reload_time = 0; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 9d5eead939..2f9f7afd65 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -125,7 +125,6 @@ extern int max_send; extern int max_recv; extern uint16 last_session_tag; extern int trans_num; -extern char *orig_inbuf; extern pid_t mypid; extern time_t last_smb_conf_reload_time; @@ -206,6 +205,13 @@ struct smbd_smb2_tcon; DATA_BLOB negprot_spnego(void); +NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key, + struct iovec *vector, + int count); +NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key, + const struct iovec *vector, + int count); + bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size); void reply_smb2002(struct smb_request *req, uint16_t choice); @@ -244,6 +250,7 @@ struct smbd_smb2_request { struct smbd_smb2_tcon *tcon; int current_idx; + bool do_signing; struct { /* the NBT header is not allocated */ @@ -299,6 +306,9 @@ struct smbd_smb2_session { NTSTATUS status; uint64_t vuid; AUTH_NTLMSSP_STATE *auth_ntlmssp_state; + struct auth_serversupplied_info *server_info; + DATA_BLOB session_key; + bool do_signing; struct { /* an id tree used to allocate tids */ @@ -319,11 +329,13 @@ struct smbd_smb2_tcon { }; struct smbd_server_connection { - struct fd_event *fde; - uint64_t num_requests; - struct smb_signing_state *signing_state; bool allow_smb2; struct { + struct fd_event *fde; + uint64_t num_requests; + struct smb_signing_state *signing_state; + } smb1; + struct { struct tevent_context *event_ctx; struct tevent_queue *recv_queue; struct tevent_queue *send_queue; diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 7f99a186aa..e2f31f077c 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -443,7 +443,7 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, goto err; } - if (!S_ISLNK(sbufp->st_mode)) { + if (!S_ISLNK(sbufp->st_ex_mode)) { DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", path)); goto err; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 204cdf9e31..d6be35d29b 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -570,7 +570,7 @@ void reply_ntcreate_and_X(struct smb_request *req) oplock_granted = NO_OPLOCK_RETURN; } - file_len = sbuf.st_size; + file_len = sbuf.st_ex_size; fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; @@ -604,10 +604,9 @@ void reply_ntcreate_and_X(struct smb_request *req) p += 4; /* Create time. */ - c_timespec = get_create_timespec( - &sbuf,lp_fake_dir_create_times(SNUM(conn))); - a_timespec = get_atimespec(&sbuf); - m_timespec = get_mtimespec(&sbuf); + c_timespec = sbuf.st_ex_btime; + a_timespec = sbuf.st_ex_atime; + m_timespec = sbuf.st_ex_mtime; if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&c_timespec); @@ -1037,7 +1036,7 @@ static void call_nt_transact_create(connection_struct *conn, oplock_granted = NO_OPLOCK_RETURN; } - file_len = sbuf.st_size; + file_len = sbuf.st_ex_size; fattr = dos_mode(conn,fsp->fsp_name,&sbuf); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; @@ -1071,10 +1070,9 @@ static void call_nt_transact_create(connection_struct *conn, p += 8; /* Create time. */ - c_timespec = get_create_timespec( - &sbuf,lp_fake_dir_create_times(SNUM(conn))); - a_timespec = get_atimespec(&sbuf); - m_timespec = get_mtimespec(&sbuf); + c_timespec = sbuf.st_ex_btime; + a_timespec = sbuf.st_ex_atime; + m_timespec = sbuf.st_ex_mtime; if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&c_timespec); @@ -1220,7 +1218,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, } /* No links from a directory. */ - if (S_ISDIR(smb_fname->st.st_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { status = NT_STATUS_FILE_IS_A_DIRECTORY; goto out; } @@ -1283,8 +1281,8 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, goto out; } - if (smb_fname->st.st_size) { - ret = vfs_transfer_file(fsp1, fsp2, smb_fname->st.st_size); + if (smb_fname->st.st_ex_size) { + ret = vfs_transfer_file(fsp1, fsp2, smb_fname->st.st_ex_size); } /* @@ -1296,7 +1294,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, close_file(NULL, fsp1, NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - set_close_write_time(fsp2, get_mtimespec(&smb_fname->st)); + set_close_write_time(fsp2, smb_fname->st.st_ex_mtime); status = close_file(NULL, fsp2, NORMAL_CLOSE); @@ -1311,7 +1309,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, false); TALLOC_FREE(parent); - if (ret < (SMB_OFF_T)smb_fname->st.st_size) { + if (ret < (SMB_OFF_T)smb_fname->st.st_ex_size) { status = NT_STATUS_DISK_FULL; goto out; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e6f523a162..c1b29f68f3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -206,19 +206,19 @@ void change_file_owner_to_parent(connection_struct *conn, } become_root(); - ret = SMB_VFS_FCHOWN(fsp, parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, parent_st.st_ex_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { DEBUG(0,("change_file_owner_to_parent: failed to fchown " "file %s to parent directory uid %u. Error " "was %s\n", fsp->fsp_name, - (unsigned int)parent_st.st_uid, + (unsigned int)parent_st.st_ex_uid, strerror(errno) )); } DEBUG(10,("change_file_owner_to_parent: changed new file %s to " "parent directory uid %u.\n", fsp->fsp_name, - (unsigned int)parent_st.st_uid )); + (unsigned int)parent_st.st_ex_uid )); } NTSTATUS change_dir_owner_to_parent(connection_struct *conn, @@ -276,9 +276,9 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn, } /* Ensure we're pointing at the same place. */ - if (sbuf.st_dev != psbuf->st_dev || - sbuf.st_ino != psbuf->st_ino || - sbuf.st_mode != psbuf->st_mode ) { + if (sbuf.st_ex_dev != psbuf->st_ex_dev || + sbuf.st_ex_ino != psbuf->st_ex_ino || + sbuf.st_ex_mode != psbuf->st_ex_mode ) { DEBUG(0,("change_dir_owner_to_parent: " "device/inode/mode on directory %s changed. " "Refusing to chown !\n", fname )); @@ -287,20 +287,20 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn, } become_root(); - ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_ex_uid, (gid_t)-1); unbecome_root(); if (ret == -1) { status = map_nt_error_from_unix(errno); DEBUG(10,("change_dir_owner_to_parent: failed to chown " "directory %s to parent directory uid %u. " "Error was %s\n", fname, - (unsigned int)parent_st.st_uid, strerror(errno) )); + (unsigned int)parent_st.st_ex_uid, strerror(errno) )); goto out; } DEBUG(10,("change_dir_owner_to_parent: changed ownership of new " "directory %s to parent directory uid %u.\n", - fname, (unsigned int)parent_st.st_uid )); + fname, (unsigned int)parent_st.st_ex_uid )); out: @@ -396,7 +396,7 @@ static NTSTATUS open_file(files_struct *fsp, * open flags. JRA. */ - if (file_existed && S_ISFIFO(psbuf->st_mode)) { + if (file_existed && S_ISFIFO(psbuf->st_ex_mode)) { local_flags |= O_NONBLOCK; } #endif @@ -498,7 +498,7 @@ static NTSTATUS open_file(files_struct *fsp, } } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && fsp->posix_open && - S_ISLNK(psbuf->st_mode)) { + S_ISLNK(psbuf->st_ex_mode)) { /* This is a POSIX stat open for delete * or rename on a symlink that points * nowhere. Allow. */ @@ -543,13 +543,13 @@ static NTSTATUS open_file(files_struct *fsp, * so catch a directory open and return an EISDIR. JRA. */ - if(S_ISDIR(psbuf->st_mode)) { + if(S_ISDIR(psbuf->st_ex_mode)) { fd_close(fsp); errno = EISDIR; return NT_STATUS_FILE_IS_A_DIRECTORY; } - fsp->mode = psbuf->st_mode; + fsp->mode = psbuf->st_ex_mode; fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; @@ -1583,7 +1583,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_CREATE " "requested for file %s and file " "already exists.\n", fname )); - if (S_ISDIR(psbuf->st_mode)) { + if (S_ISDIR(psbuf->st_ex_mode)) { errno = EISDIR; } else { errno = EEXIST; @@ -1610,13 +1610,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, (create_disposition == FILE_OVERWRITE_IF))) { if (!open_match_attributes(conn, fname, existing_dos_attributes, - new_dos_attributes, psbuf->st_mode, + new_dos_attributes, psbuf->st_ex_mode, unx_mode, &new_unx_mode)) { DEBUG(5,("open_file_ntcreate: attributes missmatch " "for file %s (%x %x) (0%o, 0%o)\n", fname, existing_dos_attributes, new_dos_attributes, - (unsigned int)psbuf->st_mode, + (unsigned int)psbuf->st_ex_mode, (unsigned int)unx_mode )); errno = EACCES; return NT_STATUS_ACCESS_DENIED; @@ -1715,7 +1715,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } if (file_existed) { - struct timespec old_write_time = get_mtimespec(psbuf); + struct timespec old_write_time = psbuf->st_ex_mtime; id = vfs_file_id_from_sbuf(conn, psbuf); lck = get_share_mode_lock(talloc_tos(), id, @@ -1919,7 +1919,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, } if (!file_existed) { - struct timespec old_write_time = get_mtimespec(psbuf); + struct timespec old_write_time = psbuf->st_ex_mtime; /* * Deal with the race condition where two smbd's detect the * file doesn't exist and do the create at the same time. One @@ -2134,7 +2134,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, new_dos_attributes | aARCH, &tmp_sbuf, parent_dir, true) == 0) { - unx_mode = tmp_sbuf.st_mode; + unx_mode = tmp_sbuf.st_ex_mode; } } } @@ -2305,7 +2305,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return map_nt_error_from_unix(errno); } - if (!S_ISDIR(psbuf->st_mode)) { + if (!S_ISDIR(psbuf->st_ex_mode)) { DEBUG(0, ("Directory just '%s' created is not a directory\n", name)); return NT_STATUS_ACCESS_DENIED; @@ -2331,9 +2331,9 @@ static NTSTATUS mkdir_internal(connection_struct *conn, * Consider bits automagically set by UNIX, i.e. SGID bit from parent * dir. */ - if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) { + if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_ex_mode)) { SMB_VFS_CHMOD(conn, name, - psbuf->st_mode | (mode & ~psbuf->st_mode)); + psbuf->st_ex_mode | (mode & ~psbuf->st_ex_mode)); } } @@ -2475,7 +2475,7 @@ static NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_INVALID_PARAMETER; } - if(!S_ISDIR(psbuf->st_mode)) { + if(!S_ISDIR(psbuf->st_ex_mode)) { DEBUG(5,("open_directory: %s is not a directory !\n", fname )); return NT_STATUS_NOT_A_DIRECTORY; @@ -2524,7 +2524,7 @@ static NTSTATUS open_directory(connection_struct *conn, * Setup the files_struct for it. */ - fsp->mode = psbuf->st_mode; + fsp->mode = psbuf->st_ex_mode; fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf); fsp->vuid = req ? req->vuid : UID_FIELD_INVALID; fsp->file_pid = req ? req->smbpid : 0; @@ -2547,7 +2547,7 @@ static NTSTATUS open_directory(connection_struct *conn, string_set(&fsp->fsp_name,fname); - mtimespec = get_mtimespec(psbuf); + mtimespec = psbuf->st_ex_mtime; lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, @@ -3161,7 +3161,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, } } - if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) { + if (!fsp->is_directory && S_ISDIR(sbuf.st_ex_mode)) { status = NT_STATUS_ACCESS_DENIED; goto fail; } @@ -3169,7 +3169,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { if (allocation_size - && (allocation_size > sbuf.st_size)) { + && (allocation_size > sbuf.st_ex_size)) { fsp->initial_allocation_size = smb_roundup( fsp->conn, allocation_size); if (fsp->is_directory) { @@ -3184,7 +3184,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, } } else { fsp->initial_allocation_size = smb_roundup( - fsp->conn, (uint64_t)sbuf.st_size); + fsp->conn, (uint64_t)sbuf.st_ex_size); } } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 8d172e17bd..08b1c8c41a 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -884,8 +884,8 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) { - uid_to_sid( powner_sid, psbuf->st_uid ); - gid_to_sid( pgroup_sid, psbuf->st_gid ); + uid_to_sid( powner_sid, psbuf->st_ex_uid ); + gid_to_sid( pgroup_sid, psbuf->st_ex_gid ); } /**************************************************************************** @@ -1369,7 +1369,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, ZERO_STRUCTP(pace); pace->type = SMB_ACL_USER_OBJ; pace->owner_type = UID_ACE; - pace->unix_ug.uid = pst->st_uid; + pace->unix_ug.uid = pst->st_ex_uid; pace->trustee = *pfile_owner_sid; pace->attr = ALLOW_ACE; @@ -1399,7 +1399,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, apply_default_perms(params, is_directory, pace, S_IRUSR); } else { - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR); + pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR); } DLIST_ADD(*pp_ace, pace); @@ -1414,7 +1414,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, ZERO_STRUCTP(pace); pace->type = SMB_ACL_GROUP_OBJ; pace->owner_type = GID_ACE; - pace->unix_ug.uid = pst->st_gid; + pace->unix_ug.uid = pst->st_ex_gid; pace->trustee = *pfile_grp_sid; pace->attr = ALLOW_ACE; if (setting_acl) { @@ -1425,7 +1425,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = 0; apply_default_perms(params, is_directory, pace, S_IRGRP); } else { - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP); + pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP); } DLIST_ADD(*pp_ace, pace); @@ -1447,7 +1447,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace, pace->perms = 0; apply_default_perms(params, is_directory, pace, S_IROTH); } else - pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH); + pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH); DLIST_ADD(*pp_ace, pace); } @@ -1625,7 +1625,7 @@ static bool create_canon_ace_lists(files_struct *fsp, current_ace->type = SMB_ACL_OTHER; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) { current_ace->owner_type = UID_ACE; - current_ace->unix_ug.uid = pst->st_uid; + current_ace->unix_ug.uid = pst->st_ex_uid; current_ace->type = SMB_ACL_USER_OBJ; /* @@ -1638,7 +1638,7 @@ static bool create_canon_ace_lists(files_struct *fsp, psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) { current_ace->owner_type = GID_ACE; - current_ace->unix_ug.gid = pst->st_gid; + current_ace->unix_ug.gid = pst->st_ex_gid; current_ace->type = SMB_ACL_GROUP_OBJ; /* @@ -1653,7 +1653,7 @@ static bool create_canon_ace_lists(files_struct *fsp, current_ace->owner_type = UID_ACE; /* If it's the owning user, this is a user_obj, not * a user. */ - if (current_ace->unix_ug.uid == pst->st_uid) { + if (current_ace->unix_ug.uid == pst->st_ex_uid) { current_ace->type = SMB_ACL_USER_OBJ; } else { current_ace->type = SMB_ACL_USER; @@ -1662,7 +1662,7 @@ static bool create_canon_ace_lists(files_struct *fsp, current_ace->owner_type = GID_ACE; /* If it's the primary group, this is a group_obj, not * a group. */ - if (current_ace->unix_ug.gid == pst->st_gid) { + if (current_ace->unix_ug.gid == pst->st_ex_gid) { current_ace->type = SMB_ACL_GROUP_OBJ; } else { current_ace->type = SMB_ACL_GROUP; @@ -2272,7 +2272,7 @@ static bool unpack_canon_ace(files_struct *fsp, * A default 3 element mode entry for a directory should be rwx --- ---. */ - pst->st_mode = create_default_mode(fsp, False); + pst->st_ex_mode = create_default_mode(fsp, False); if (!ensure_canon_entry_valid(&file_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); @@ -2288,7 +2288,7 @@ static bool unpack_canon_ace(files_struct *fsp, * it's a directory. */ - pst->st_mode = create_default_mode(fsp, True); + pst->st_ex_mode = create_default_mode(fsp, True); if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) { free_canon_ace_list(file_ace); @@ -2402,7 +2402,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, case SMB_ACL_USER_OBJ: /* Get the SID from the owner. */ sid_copy(&sid, powner); - unix_ug.uid = psbuf->st_uid; + unix_ug.uid = psbuf->st_ex_uid; owner_type = UID_ACE; break; case SMB_ACL_USER: @@ -2419,7 +2419,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, * entries out of the blue when setting ACLs, so a get/set * cycle will drop them. */ - if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) { + if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_ex_uid) { SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); continue; } @@ -2432,7 +2432,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, case SMB_ACL_GROUP_OBJ: /* Get the SID from the owning group. */ sid_copy(&sid, pgroup); - unix_ug.gid = psbuf->st_gid; + unix_ug.gid = psbuf->st_ex_gid; owner_type = GID_ACE; break; case SMB_ACL_GROUP: @@ -2486,7 +2486,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn, */ if (!ensure_canon_entry_valid(&l_head, conn->params, - S_ISDIR(psbuf->st_mode), powner, pgroup, + S_ISDIR(psbuf->st_ex_mode), powner, pgroup, psbuf, False)) goto fail; @@ -3097,7 +3097,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, goto done; } - if (S_ISDIR(sbuf->st_mode) && def_acl) { + if (S_ISDIR(sbuf->st_ex_mode) && def_acl) { dir_ace = canonicalise_acl(conn, name, def_acl, sbuf, &global_sid_Creator_Owner, @@ -3181,7 +3181,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, uint32_t acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - S_ISDIR(sbuf->st_mode)); + S_ISDIR(sbuf->st_ex_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -3202,7 +3202,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn, uint32_t acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, ace->perms, - S_ISDIR(sbuf->st_mode)); + S_ISDIR(sbuf->st_ex_mode)); init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, @@ -3357,7 +3357,7 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS); /* If it's a directory get the default POSIX ACL. */ - if(S_ISDIR(sbuf.st_mode)) { + if(S_ISDIR(sbuf.st_ex_mode)) { def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT); def_acl = free_empty_sys_acl(conn, def_acl); } @@ -3687,7 +3687,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC } /* Save the original element we check against. */ - orig_mode = sbuf.st_mode; + orig_mode = sbuf.st_ex_mode; /* * Unpack the user/group/world id's. @@ -3704,7 +3704,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC * Noticed by Simo. */ - if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) { + if (((user != (uid_t)-1) && (sbuf.st_ex_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_ex_gid != grp))) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); @@ -3741,7 +3741,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC } /* Save the original element we check against. */ - orig_mode = sbuf.st_mode; + orig_mode = sbuf.st_ex_mode; /* If we successfully chowned, we know we must * be able to set the acl, so do it as root. @@ -3785,7 +3785,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support); + ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_ex_gid, &acl_set_support); if (set_acl_as_root) { unbecome_root(); } @@ -3802,7 +3802,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - ret = set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support); + ret = set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_ex_gid, &acl_set_support); if (set_acl_as_root) { unbecome_root(); } @@ -3827,7 +3827,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC unbecome_root(); } if (sret == -1) { - if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) { + if (acl_group_override(conn, sbuf.st_ex_gid, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override delete_def_acl\n", fsp->fsp_name )); @@ -3889,7 +3889,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC unbecome_root(); } if(sret == -1) { - if (acl_group_override(conn, sbuf.st_gid, fsp->fsp_name)) { + if (acl_group_override(conn, sbuf.st_ex_gid, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override chmod\n", fsp->fsp_name )); @@ -4285,7 +4285,7 @@ bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_ { SMB_ACL_T def_acl = NULL; - if (!S_ISDIR(psbuf->st_mode)) { + if (!S_ISDIR(psbuf->st_ex_mode)) { if (num_def_acls) { DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname )); errno = EISDIR; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5cad8bfc9a..e014965147 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1462,7 +1462,7 @@ static void process_smb(struct smbd_server_connection *conn, trans_num++; done: - conn->num_requests++; + conn->smb1.num_requests++; /* The timeout_processing function isn't run nearly often enough to implement 'max log size' without @@ -1471,7 +1471,7 @@ done: level 10. Checking every 50 SMBs is a nice tradeoff of performance vs log file size overrun. */ - if ((conn->num_requests % 50) == 0 && + if ((conn->smb1.num_requests % 50) == 0 && need_to_check_log_size()) { change_to_root_user(); check_log_size(); @@ -2158,13 +2158,13 @@ void smbd_process(void) max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - smbd_server_conn->fde = event_add_fd(smbd_event_context(), - smbd_server_conn, - smbd_server_fd(), - EVENT_FD_READ, - smbd_server_connection_handler, - smbd_server_conn); - if (!smbd_server_conn->fde) { + smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(), + smbd_server_conn, + smbd_server_fd(), + EVENT_FD_READ, + smbd_server_connection_handler, + smbd_server_conn); + if (!smbd_server_conn->smb1.fde) { exit_server("failed to create smbd_server_connection fde"); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index d5ee918b82..8657bd6e18 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1022,7 +1022,7 @@ void reply_checkpath(struct smb_request *req) goto path_err; } - if (!S_ISDIR(smb_fname->st.st_mode)) { + if (!S_ISDIR(smb_fname->st.st_ex_mode)) { reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY, ERRDOS, ERRbadpath); goto out; @@ -1135,8 +1135,8 @@ void reply_getatr(struct smb_request *req) } mode = dos_mode(conn, fname, &smb_fname->st); - size = smb_fname->st.st_size; - mtime = smb_fname->st.st_mtime; + size = smb_fname->st.st_ex_size; + mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); if (mode & aDIR) { size = 0; } @@ -1336,7 +1336,7 @@ void reply_search(struct smb_request *req) char *fname = NULL; SMB_OFF_T size; uint32 mode; - time_t date; + struct timespec date; uint32 dirtype; unsigned int numentries = 0; unsigned int maxentries = 0; @@ -1555,7 +1555,7 @@ void reply_search(struct smb_request *req) fname, size, mode, - date, + convert_timespec_to_time_t(date), !allow_long_path_components)) { reply_nterror(req, NT_STATUS_NO_MEMORY); END_PROFILE(SMBsearch); @@ -1775,9 +1775,9 @@ void reply_open(struct smb_request *req) return; } - size = sbuf.st_size; + size = sbuf.st_ex_size; fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = sbuf.st_mtime; + mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); if (fattr & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name)); @@ -1939,11 +1939,11 @@ void reply_open_and_X(struct smb_request *req) END_PROFILE(SMBopenX); return; } - sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); + sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); } fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = sbuf.st_mtime; + mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS, ERRnoaccess); @@ -1992,7 +1992,7 @@ void reply_open_and_X(struct smb_request *req) } else { srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime); } - SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size); + SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size); SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); SSVAL(req->outbuf,smb_vwv11,smb_action); @@ -2124,7 +2124,7 @@ void reply_mknew(struct smb_request *req) return; } - ft.atime = get_atimespec(&sbuf); /* atime. */ + ft.atime = sbuf.st_ex_atime; /* atime. */ status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); @@ -2306,7 +2306,7 @@ void reply_ctemp(struct smb_request *req) DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) ); DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name, - fsp->fh->fd, (unsigned int)smb_fname->st.st_mode)); + fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode)); out: TALLOC_FREE(smb_fname); END_PROFILE(SMBctemp); @@ -2331,7 +2331,7 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, return NT_STATUS_NO_SUCH_FILE; } - if (S_ISDIR(pst->st_mode)) { + if (S_ISDIR(pst->st_ex_mode)) { if (fsp->posix_open) { return NT_STATUS_OK; } @@ -2893,7 +2893,7 @@ static void send_file_readbraw(connection_struct *conn, if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && - lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) { + lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) { ssize_t sendfile_read = -1; char header[4]; DATA_BLOB header_blob; @@ -3104,7 +3104,7 @@ void reply_readbraw(struct smb_request *req) } if (SMB_VFS_FSTAT(fsp, &st) == 0) { - size = st.st_size; + size = st.st_ex_size; } if (startpos >= size) { @@ -3393,8 +3393,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, return; } - if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size) - || (smb_maxcnt > (sbuf.st_size - startpos))) { + if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size) + || (smb_maxcnt > (sbuf.st_ex_size - startpos))) { /* * We already know that we would do a short read, so don't * try the sendfile() path. @@ -3412,7 +3412,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, if (!req_is_in_chain(req) && !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) && (fsp->wcp == NULL) && - lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) { + lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) { uint8 headerbuf[smb_size + 12 * 2]; DATA_BLOB header; @@ -4442,7 +4442,7 @@ void reply_lseek(struct smb_request *req) return; } - current_pos += sbuf.st_size; + current_pos += sbuf.st_ex_size; if(current_pos < 0) res = SMB_VFS_LSEEK(fsp,0,SEEK_SET); } @@ -5287,7 +5287,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, break; } - if(st.st_mode & S_IFDIR) { + if(st.st_ex_mode & S_IFDIR) { if(!recursive_rmdir(ctx, conn, fullname)) { ret = False; break; @@ -5322,12 +5322,12 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, return map_nt_error_from_unix(errno); } - if (S_ISLNK(st.st_mode)) { + if (S_ISLNK(st.st_ex_mode)) { /* Is what it points to a directory ? */ if(SMB_VFS_STAT(conn, directory, &st) != 0) { return map_nt_error_from_unix(errno); } - if (!(S_ISDIR(st.st_mode))) { + if (!(S_ISDIR(st.st_ex_mode))) { return NT_STATUS_NOT_A_DIRECTORY; } ret = SMB_VFS_UNLINK(conn,directory); @@ -5404,7 +5404,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { break; } - if(st.st_mode & S_IFDIR) { + if(st.st_ex_mode & S_IFDIR) { if(!recursive_rmdir(ctx, conn, fullname)) { break; } @@ -6103,7 +6103,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, SMB_VFS_STAT(conn, directory, &smb_fname->st); } - if (S_ISDIR(smb_fname->st.st_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { create_options |= FILE_DIRECTORY_FILE; } @@ -6229,7 +6229,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, create_options = 0; - if (S_ISDIR(smb_fname->st.st_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { create_options |= FILE_DIRECTORY_FILE; } @@ -6510,18 +6510,18 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, * Stop the copy from occurring. */ ret = -1; - src_sbuf.st_size = 0; + src_sbuf.st_ex_size = 0; } } - if (src_sbuf.st_size) { - ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size); + if (src_sbuf.st_ex_size) { + ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_ex_size); } close_file(NULL, fsp1, NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - set_close_write_time(fsp2, get_mtimespec(&src_sbuf)); + set_close_write_time(fsp2, src_sbuf.st_ex_mtime); /* * As we are opening fsp1 read-only we only expect @@ -6535,7 +6535,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, return status; } - if (ret != (SMB_OFF_T)src_sbuf.st_size) { + if (ret != (SMB_OFF_T)src_sbuf.st_ex_size) { return NT_STATUS_DISK_FULL; } @@ -7551,19 +7551,20 @@ void reply_getattrE(struct smb_request *req) reply_outbuf(req, 11, 0); - create_ts = get_create_timespec(&sbuf, - lp_fake_dir_create_times(SNUM(conn))); + create_ts = sbuf.st_ex_btime; srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec); - srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime); + srv_put_dos_date2((char *)req->outbuf, smb_vwv2, + convert_timespec_to_time_t(sbuf.st_ex_atime)); /* Should we check pending modtime here ? JRA */ - srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime); + srv_put_dos_date2((char *)req->outbuf, smb_vwv4, + convert_timespec_to_time_t(sbuf.st_ex_mtime)); if (mode & aDIR) { SIVAL(req->outbuf, smb_vwv6, 0); SIVAL(req->outbuf, smb_vwv8, 0); } else { uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf); - SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size); + SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size); SIVAL(req->outbuf, smb_vwv8, allocation_size); } SSVAL(req->outbuf,smb_vwv10, mode); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 67836f785b..685b26fa1a 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -356,6 +356,7 @@ static void smbd_accept_connection(struct tevent_context *ev, pid = sys_fork(); if (pid == 0) { + NTSTATUS status = NT_STATUS_OK; /* Child code ... */ am_parent = 0; @@ -374,10 +375,15 @@ static void smbd_accept_connection(struct tevent_context *ev, talloc_free(s->parent); s = NULL; - if (!reinit_after_fork( - smbd_messaging_context(), - smbd_event_context(), - true)) { + status = reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), true); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_TOO_MANY_OPENED_FILES)) { + DEBUG(0,("child process cannot initialize " + "because too many files are open\n")); + goto exit; + } DEBUG(0,("reinit_after_fork() failed\n")); smb_panic("reinit_after_fork() failed"); } @@ -386,6 +392,7 @@ static void smbd_accept_connection(struct tevent_context *ev, smbd_setup_sig_hup_handler(); smbd_process(); + exit: exit_server_cleanly("end of child"); return; } else if (pid < 0) { @@ -1122,8 +1129,8 @@ extern void build_options(bool screen); if (is_daemon) pidfile_create("smbd"); - if (!reinit_after_fork(smbd_messaging_context(), - smbd_event_context(), false)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(), + smbd_event_context(), false))) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index bc07f0b90d..75c19ce131 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -993,8 +993,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, I have disabled this chdir check (tridge) */ /* the alternative is just to check the directory exists */ if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || - !S_ISDIR(st.st_mode)) { - if (ret == 0 && !S_ISDIR(st.st_mode)) { + !S_ISDIR(st.st_ex_mode)) { + if (ret == 0 && !S_ISDIR(st.st_ex_mode)) { DEBUG(0,("'%s' is not a directory, when connecting to " "[%s]\n", conn->connectpath, lp_servicename(snum))); diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c index b56eb71f45..9b5e3452f9 100644 --- a/source3/smbd/signing.c +++ b/source3/smbd/signing.c @@ -35,8 +35,8 @@ bool srv_check_sign_mac(struct smbd_server_connection *conn, return true; } - *seqnum = smb_signing_next_seqnum(conn->signing_state, false); - return smb_signing_check_pdu(conn->signing_state, + *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false); + return smb_signing_check_pdu(conn->smb1.signing_state, (const uint8_t *)inbuf, *seqnum); } @@ -53,7 +53,7 @@ void srv_calculate_sign_mac(struct smbd_server_connection *conn, return; } - smb_signing_sign_pdu(conn->signing_state, (uint8_t *)outbuf, seqnum); + smb_signing_sign_pdu(conn->smb1.signing_state, (uint8_t *)outbuf, seqnum); } @@ -62,7 +62,7 @@ void srv_calculate_sign_mac(struct smbd_server_connection *conn, ************************************************************/ void srv_cancel_sign_response(struct smbd_server_connection *conn) { - smb_signing_cancel_reply(conn->signing_state, true); + smb_signing_cancel_reply(conn->smb1.signing_state, true); } /*********************************************************** @@ -87,9 +87,9 @@ bool srv_init_signing(struct smbd_server_connection *conn) break; } - conn->signing_state = smb_signing_init(smbd_event_context(), - allowed, mandatory); - if (!conn->signing_state) { + conn->smb1.signing_state = smb_signing_init(smbd_event_context(), + allowed, mandatory); + if (!conn->smb1.signing_state) { return false; } @@ -98,7 +98,7 @@ bool srv_init_signing(struct smbd_server_connection *conn) void srv_set_signing_negotiated(struct smbd_server_connection *conn) { - smb_signing_set_negotiated(conn->signing_state); + smb_signing_set_negotiated(conn->smb1.signing_state); } /*********************************************************** @@ -108,7 +108,7 @@ void srv_set_signing_negotiated(struct smbd_server_connection *conn) bool srv_is_signing_active(struct smbd_server_connection *conn) { - return smb_signing_is_active(conn->signing_state); + return smb_signing_is_active(conn->smb1.signing_state); } @@ -119,7 +119,7 @@ bool srv_is_signing_active(struct smbd_server_connection *conn) bool srv_is_signing_negotiated(struct smbd_server_connection *conn) { - return smb_signing_is_negotiated(conn->signing_state); + return smb_signing_is_negotiated(conn->smb1.signing_state); } /*********************************************************** @@ -136,8 +136,8 @@ void srv_set_signing(struct smbd_server_connection *conn, if (!user_session_key.length) return; - negotiated = smb_signing_is_negotiated(conn->signing_state); - mandatory = smb_signing_is_mandatory(conn->signing_state); + negotiated = smb_signing_is_negotiated(conn->smb1.signing_state); + mandatory = smb_signing_is_mandatory(conn->smb1.signing_state); if (!negotiated && !mandatory) { DEBUG(5,("srv_set_signing: signing negotiated = %u, " @@ -146,7 +146,7 @@ void srv_set_signing(struct smbd_server_connection *conn, return; } - if (!smb_signing_activate(conn->signing_state, + if (!smb_signing_activate(conn->smb1.signing_state, user_session_key, response)) { return; } diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index b976ea2399..e9464900f2 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -74,8 +74,10 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) size_t body_size; size_t expected_dyn_size = 0; size_t c; + uint16_t security_mode; uint16_t dialect_count; uint16_t dialect; + uint32_t capabilities; /* TODO: drop the connection with INVALI_PARAMETER */ @@ -103,12 +105,12 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) for (c=0; c < dialect_count; c++) { dialect = SVAL(indyn, c*2); - if (dialect == 0x0202) { + if (dialect == SMB2_DIALECT_REVISION_202) { break; } } - if (dialect != 0x0202) { + if (dialect != SMB2_DIALECT_REVISION_202) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } @@ -129,6 +131,16 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR); } + security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; + if (lp_server_signing() == Required) { + security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED; + } + + capabilities = 0; + if (lp_host_msdfs()) { + capabilities |= SMB2_CAP_DFS; + } + security_offset = SMB2_HDR_BODY + 0x40; security_buffer = data_blob_const(negprot_spnego_blob.data + 16, negprot_spnego_blob.length - 16); @@ -142,13 +154,14 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) } SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */ -/*TODO: indicate signing enabled */ - SSVAL(outbody.data, 0x02, 0); /* security mode */ + SSVAL(outbody.data, 0x02, + security_mode); /* security mode */ SSVAL(outbody.data, 0x04, dialect); /* dialect revision */ SSVAL(outbody.data, 0x06, 0); /* reserved */ memcpy(outbody.data + 0x08, negprot_spnego_blob.data, 16); /* server guid */ - SIVAL(outbody.data, 0x18, 0); /* capabilities */ + SIVAL(outbody.data, 0x18, + capabilities); /* capabilities */ SIVAL(outbody.data, 0x1C, 0x00010000); /* max transact size */ SIVAL(outbody.data, 0x20, 0x00010000); /* max read size */ SIVAL(outbody.data, 0x24, 0x00010000); /* max write size */ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 32bb5543ae..0d901714e0 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -41,7 +41,7 @@ static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *conn) NTSTATUS status; int ret; - TALLOC_FREE(conn->fde); + TALLOC_FREE(conn->smb1.fde); conn->smb2.event_ctx = smbd_event_context(); @@ -288,14 +288,45 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) const uint8_t *inhdr; int i = req->current_idx; uint16_t opcode; + uint32_t flags; NTSTATUS status; + NTSTATUS session_status; inhdr = (const uint8_t *)req->in.vector[i].iov_base; /* TODO: verify more things */ + flags = IVAL(inhdr, SMB2_HDR_FLAGS); opcode = IVAL(inhdr, SMB2_HDR_OPCODE); DEBUG(10,("smbd_smb2_request_dispatch: opcode[%u]\n", opcode)); + +#define TMP_SMB2_ALLOWED_FLAGS ( \ + SMB2_HDR_FLAG_CHAINED | \ + SMB2_HDR_FLAG_SIGNED | \ + SMB2_HDR_FLAG_DFS) + if ((flags & ~TMP_SMB2_ALLOWED_FLAGS) != 0) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } +#undef TMP_SMB2_ALLOWED_FLAGS + + session_status = smbd_smb2_request_check_session(req); + + req->do_signing = false; + if (flags & SMB2_HDR_FLAG_SIGNED) { + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); + } + + req->do_signing = true; + status = smb2_signing_check_pdu(req->session->session_key, + &req->in.vector[i], 3); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } + } else if (req->session && req->session->do_signing) { + return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED); + } + switch (opcode) { case SMB2_OP_NEGPROT: return smbd_smb2_request_process_negprot(req); @@ -304,13 +335,15 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_sesssetup(req); case SMB2_OP_LOGOFF: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } return smbd_smb2_request_process_logoff(req); case SMB2_OP_TCON: + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); + } status = smbd_smb2_request_check_session(req); if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(req, status); @@ -318,9 +351,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_tcon(req); case SMB2_OP_TDIS: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -329,9 +361,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_tdis(req); case SMB2_OP_CREATE: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -340,9 +371,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_CLOSE: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -351,9 +381,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_FLUSH: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -362,9 +391,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_READ: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -373,9 +401,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_WRITE: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -384,9 +411,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_LOCK: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -395,9 +421,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_IOCTL: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -412,9 +437,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_process_keepalive(req); case SMB2_OP_FIND: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -423,9 +447,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_NOTIFY: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -434,9 +457,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_GETINFO: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -445,9 +467,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_SETINFO: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -456,9 +477,8 @@ static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NOT_IMPLEMENTED); case SMB2_OP_BREAK: - status = smbd_smb2_request_check_session(req); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); + if (!NT_STATUS_IS_OK(session_status)) { + return smbd_smb2_request_error(req, session_status); } status = smbd_smb2_request_check_tcon(req); if (!NT_STATUS_IS_OK(status)) { @@ -481,6 +501,16 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) smb2_setup_nbt_length(req->out.vector, req->out.vector_count); + if (req->do_signing) { + int i = req->current_idx; + NTSTATUS status; + status = smb2_signing_sign_pdu(req->session->session_key, + &req->out.vector[i], 3); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + req->current_idx += 3; if (req->current_idx > req->in.vector_count) { diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index fafda24ca4..be37aec04d 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -24,7 +24,9 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, uint64_t in_session_id, + uint8_t in_security_mode, DATA_BLOB in_security_buffer, + uint16_t *out_session_flags, DATA_BLOB *out_security_buffer, uint64_t *out_session_id); @@ -39,9 +41,11 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req) size_t expected_body_size = 0x19; size_t body_size; uint64_t in_session_id; + uint8_t in_security_mode; uint16_t in_security_offset; uint16_t in_security_length; DATA_BLOB in_security_buffer; + uint16_t out_session_flags; uint64_t out_session_id; uint16_t out_security_offset; DATA_BLOB out_security_buffer; @@ -72,12 +76,15 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req) } in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID); + in_security_mode = CVAL(inbody, 0x03); in_security_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base; in_security_buffer.length = in_security_length; status = smbd_smb2_session_setup(req, in_session_id, + in_security_mode, in_security_buffer, + &out_session_flags, &out_security_buffer, &out_session_id); if (!NT_STATUS_IS_OK(status) && @@ -98,7 +105,8 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req) SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id); SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */ - SSVAL(outbody.data, 0x02, 0); /* session flags */ + SSVAL(outbody.data, 0x02, + out_session_flags); /* session flags */ SSVAL(outbody.data, 0x04, out_security_offset); /* security buffer offset */ SSVAL(outbody.data, 0x06, @@ -132,13 +140,17 @@ static int smbd_smb2_session_destructor(struct smbd_smb2_session *session) static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, uint64_t in_session_id, + uint8_t in_security_mode, DATA_BLOB in_security_buffer, + uint16_t *out_session_flags, DATA_BLOB *out_security_buffer, uint64_t *out_session_id) { struct smbd_smb2_session *session; NTSTATUS status; + *out_session_flags = 0; + if (in_session_id == 0) { int id; @@ -185,6 +197,7 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, if (session->auth_ntlmssp_state == NULL) { status = auth_ntlmssp_start(&session->auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(session); return status; } } @@ -193,19 +206,54 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req, in_security_buffer, out_security_buffer); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - /* nothing to do */ - } else if (NT_STATUS_IS_OK(status)) { - /* TODO: setup session key for signing */ - session->status = NT_STATUS_OK; - /* - * we attach the session to the request - * so that the response can be signed - */ - req->session = session; - } else { + *out_session_id = session->vuid; + return status; + } else if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(session); return status; } + /* TODO: setup session key for signing */ + + if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || + lp_server_signing() == Required) { + session->do_signing = true; + } + + if (session->auth_ntlmssp_state->server_info->guest) { + /* we map anonymous to guest internally */ + *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST; + *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL; + /* force no signing */ + session->do_signing = false; + } + + session->server_info = session->auth_ntlmssp_state->server_info; + data_blob_free(&session->server_info->user_session_key); + session->server_info->user_session_key = + data_blob_talloc( + session->server_info, + session->auth_ntlmssp_state->ntlmssp_state->session_key.data, + session->auth_ntlmssp_state->ntlmssp_state->session_key.length); + if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) { + if (session->server_info->user_session_key.data == NULL) { + TALLOC_FREE(session); + return NT_STATUS_NO_MEMORY; + } + } + session->session_key = session->server_info->user_session_key; + + session->status = NT_STATUS_OK; + + /* + * we attach the session to the request + * so that the response can be signed + */ + req->session = session; + if (session->do_signing) { + req->do_signing = true; + } + *out_session_id = session->vuid; return status; } diff --git a/source3/smbd/smb2_signing.c b/source3/smbd/smb2_signing.c new file mode 100644 index 0000000000..55ed4f6d1c --- /dev/null +++ b/source3/smbd/smb2_signing.c @@ -0,0 +1,135 @@ +/* + Unix SMB/CIFS implementation. + SMB2 signing + + Copyright (C) Stefan Metzmacher 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 "smbd/globals.h" +#include "../source4/libcli/smb2/smb2_constants.h" +#include "../lib/crypto/crypto.h" + +NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key, + struct iovec *vector, + int count) +{ + uint8_t *hdr; + uint64_t session_id; + struct HMACSHA256Context m; + uint8_t res[SHA256_DIGEST_LENGTH]; + int i; + + if (count < 2) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (vector[0].iov_len != SMB2_HDR_BODY) { + return NT_STATUS_INVALID_PARAMETER; + } + + hdr = (uint8_t *)vector[0].iov_base; + + session_id = BVAL(hdr, SMB2_HDR_SESSION_ID); + if (session_id == 0) { + /* + * do not sign messages with a zero session_id. + * See MS-SMB2 3.2.4.1.1 + */ + return NT_STATUS_OK; + } + + if (session_key.length == 0) { + DEBUG(2,("Wrong session key length %u for SMB2 signing\n", + (unsigned)session_key.length)); + return NT_STATUS_ACCESS_DENIED; + } + + memset(hdr + SMB2_HDR_SIGNATURE, 0, 16); + + SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); + + ZERO_STRUCT(m); + hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); + for (i=0; i < count; i++) { + hmac_sha256_update((const uint8_t *)vector[i].iov_base, + vector[i].iov_len, &m); + } + hmac_sha256_final(res, &m); + DEBUG(5,("signed SMB2 message\n")); + + memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16); + + return NT_STATUS_OK; +} + +NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key, + const struct iovec *vector, + int count) +{ + const uint8_t *hdr; + const uint8_t *sig; + uint64_t session_id; + struct HMACSHA256Context m; + uint8_t res[SHA256_DIGEST_LENGTH]; + static const uint8_t zero_sig[16]; + int i; + + if (count < 2) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (vector[0].iov_len != SMB2_HDR_BODY) { + return NT_STATUS_INVALID_PARAMETER; + } + + hdr = (const uint8_t *)vector[0].iov_base; + + session_id = BVAL(hdr, SMB2_HDR_SESSION_ID); + if (session_id == 0) { + /* + * do not sign messages with a zero session_id. + * See MS-SMB2 3.2.4.1.1 + */ + return NT_STATUS_OK; + } + + if (session_key.length == 0) { + /* we don't have the session key yet */ + return NT_STATUS_OK; + } + + sig = hdr+SMB2_HDR_SIGNATURE; + + ZERO_STRUCT(m); + hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); + hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m); + hmac_sha256_update(zero_sig, 16, &m); + for (i=1; i < count; i++) { + hmac_sha256_update((const uint8_t *)vector[i].iov_base, + vector[i].iov_len, &m); + } + hmac_sha256_final(res, &m); + + if (memcmp(res, sig, 16) != 0) { + DEBUG(0,("Bad SMB2 signature for message\n")); + dump_data(0, sig, 16); + dump_data(0, res, 16); + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1748cfa0b8..1d95c207ba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1015,8 +1015,8 @@ static void call_trans2open(connection_struct *conn, size = get_file_size_stat(&sbuf); fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = sbuf.st_mtime; - inode = sbuf.st_ino; + mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); + inode = sbuf.st_ex_ino; if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); @@ -1136,7 +1136,7 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, if (!VALID_STAT(*psbuf)) { return NT_STATUS_INVALID_PARAMETER; } else { - *ret_perms = psbuf->st_mode; + *ret_perms = psbuf->st_ex_mode; return NT_STATUS_OK; } } @@ -1207,7 +1207,7 @@ static bool check_msdfs_link(connection_struct *conn, DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s " "as a directory\n", pathname)); - psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR; + psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR; errno = saved_errno; return true; } @@ -1417,10 +1417,9 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf); - mdate_ts = get_mtimespec(&sbuf); - adate_ts = get_atimespec(&sbuf); - create_date_ts = get_create_timespec(&sbuf, - lp_fake_dir_create_times(SNUM(conn))); + mdate_ts = sbuf.st_ex_mtime; + adate_ts = sbuf.st_ex_atime; + create_date_ts = sbuf.st_ex_btime; if (ask_sharemode) { struct timespec write_time_ts; @@ -1737,8 +1736,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, p +=4; } SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII); @@ -1793,8 +1792,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } p += 26; SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */ + SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */ len = srvstr_push(base_data, flags2, p, fname, PTR_DIFF(end_data, p), STR_TERMINATE_ASCII); @@ -2579,7 +2578,7 @@ static void call_trans2qfsinfo(connection_struct *conn, int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); uint32 additional_flags = 0; - + if (total_params < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -2654,10 +2653,10 @@ static void call_trans2qfsinfo(connection_struct *conn, sectors_per_unit = bsize/bytes_per_sector; DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \ -cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit, +cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit, (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); - SIVAL(pdata,l1_idFileSystem,st.st_dev); + SIVAL(pdata,l1_idFileSystem,st.st_ex_dev); SIVAL(pdata,l1_cSectorUnit,sectors_per_unit); SIVAL(pdata,l1_cUnit,dsize); SIVAL(pdata,l1_cUnitAvail,dfree); @@ -2686,7 +2685,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", - (unsigned)st.st_ctime, len, vname)); + (unsigned)convert_timespec_to_time_t(st.st_ex_ctime), + len, vname)); break; case SMB_QUERY_FS_ATTRIBUTE_INFO: @@ -2849,13 +2849,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned */ files_struct fsp; SMB_NTQUOTA_STRUCT quotas; - + ZERO_STRUCT(fsp); ZERO_STRUCT(quotas); - + fsp.conn = conn; fsp.fnum = -1; - + /* access check */ if (conn->server_info->utok.uid != 0) { DEBUG(0,("set_user_quota: access_denied " @@ -2865,7 +2865,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned reply_doserror(req, ERRDOS, ERRnoaccess); return; } - + if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); reply_doserror(req, ERRSRV, ERRerror); @@ -2875,25 +2875,25 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 48; DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn)))); - + /* Unknown1 24 NULL bytes*/ SBIG_UINT(pdata,0,(uint64_t)0); SBIG_UINT(pdata,8,(uint64_t)0); SBIG_UINT(pdata,16,(uint64_t)0); - + /* Default Soft Quota 8 bytes */ SBIG_UINT(pdata,24,quotas.softlim); /* Default Hard Quota 8 bytes */ SBIG_UINT(pdata,32,quotas.hardlim); - + /* Quota flag 2 bytes */ SSVAL(pdata,40,quotas.qflags); - + /* Unknown3 6 NULL bytes */ SSVAL(pdata,42,0); SIVAL(pdata,44,0); - + break; } #endif /* HAVE_SYS_QUOTAS */ @@ -3300,7 +3300,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", { files_struct *fsp = NULL; SMB_NTQUOTA_STRUCT quotas; - + ZERO_STRUCT(quotas); /* access check */ @@ -3335,9 +3335,9 @@ cap_low = 0x%x, cap_high = 0x%x\n", NT_STATUS_INVALID_PARAMETER); return; } - + /* unknown_1 24 NULL bytes in pdata*/ - + /* the soft quotas 8 bytes (uint64_t)*/ quotas.softlim = (uint64_t)IVAL(pdata,24); #ifdef LARGE_SMB_OFF_T @@ -3353,7 +3353,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", return; } #endif /* LARGE_SMB_OFF_T */ - + /* the hard quotas 8 bytes (uint64_t)*/ quotas.hardlim = (uint64_t)IVAL(pdata,32); #ifdef LARGE_SMB_OFF_T @@ -3369,19 +3369,19 @@ cap_low = 0x%x, cap_high = 0x%x\n", return; } #endif /* LARGE_SMB_OFF_T */ - + /* quota_flags 2 bytes **/ quotas.qflags = SVAL(pdata,40); - + /* unknown_2 6 NULL bytes follow*/ - + /* now set the quotas */ if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); reply_doserror(req, ERRSRV, ERRerror); return; } - + break; } default: @@ -3461,7 +3461,7 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ switch (tagtype) { case SMB_ACL_USER_OBJ: SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ); - own_grp = (unsigned int)pst->st_uid; + own_grp = (unsigned int)pst->st_ex_uid; SIVAL(pdata,2,own_grp); SIVAL(pdata,6,0); break; @@ -3481,7 +3481,7 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_ } case SMB_ACL_GROUP_OBJ: SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ); - own_grp = (unsigned int)pst->st_gid; + own_grp = (unsigned int)pst->st_ex_gid; SIVAL(pdata,2,own_grp); SIVAL(pdata,6,0); break; @@ -3530,7 +3530,7 @@ static char *store_file_unix_basic(connection_struct *conn, const SMB_STRUCT_STAT *psbuf) { DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n")); - DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode)); + DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode)); SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */ pdata += 8; @@ -3538,38 +3538,38 @@ static char *store_file_unix_basic(connection_struct *conn, SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; - put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */ - put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */ - put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */ + put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */ + put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */ + put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */ pdata += 24; - SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */ + SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */ SIVAL(pdata,4,0); pdata += 8; - SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */ + SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */ SIVAL(pdata,4,0); pdata += 8; - SIVAL(pdata,0,unix_filetype(psbuf->st_mode)); + SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode)); pdata += 4; - SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */ + SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */ SIVAL(pdata,4,0); pdata += 8; - SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */ + SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */ SIVAL(pdata,4,0); pdata += 8; - SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */ + SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */ pdata += 8; - - SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */ + + SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */ SIVAL(pdata,4,0); pdata += 8; - SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */ + SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */ SIVAL(pdata,4,0); pdata += 8; @@ -3613,16 +3613,14 @@ static const struct {unsigned stat_fflag; unsigned smb_fflag;} static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf, uint32 *smb_fflags, uint32 *smb_fmask) { -#ifdef HAVE_STAT_ST_FLAGS int i; for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) { *smb_fmask |= info2_flags_map[i].smb_fflag; - if (psbuf->st_flags & info2_flags_map[i].stat_fflag) { + if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) { *smb_fflags |= info2_flags_map[i].smb_fflag; } } -#endif /* HAVE_STAT_ST_FLAGS */ } static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf, @@ -3630,11 +3628,10 @@ static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf, const uint32 smb_fmask, int *stat_fflags) { -#ifdef HAVE_STAT_ST_FLAGS uint32 max_fmask = 0; int i; - *stat_fflags = psbuf->st_flags; + *stat_fflags = psbuf->st_ex_flags; /* For each flags requested in smb_fmask, check the state of the * corresponding flag in smb_fflags and set or clear the matching @@ -3660,9 +3657,6 @@ static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf, } return True; -#else - return False; -#endif /* HAVE_STAT_ST_FLAGS */ } @@ -3680,7 +3674,7 @@ static char *store_file_unix_basic_info2(connection_struct *conn, pdata = store_file_unix_basic(conn, pdata, fsp, psbuf); /* Create (birth) time 64 bit */ - put_long_date_timespec(pdata, get_create_timespec(psbuf, False)); + put_long_date_timespec(pdata, psbuf->st_ex_btime); pdata += 8; map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask); @@ -4101,7 +4095,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, if (!mode) mode = FILE_ATTRIBUTE_NORMAL; - nlink = sbuf.st_nlink; + nlink = sbuf.st_ex_nlink; if (nlink && (mode&aDIR)) { nlink = 1; @@ -4195,9 +4189,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dstart = pdata; dend = dstart + data_size - 1; - create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - mtime_ts = get_mtimespec(&sbuf); - atime_ts = get_atimespec(&sbuf); + create_time_ts = sbuf.st_ex_btime; + mtime_ts = sbuf.st_ex_mtime; + atime_ts = sbuf.st_ex_atime; allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); @@ -4454,8 +4448,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd BasicFileInformationTest. -tpot */ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); - SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */ - SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */ + SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */ + SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */ data_size = 8; break; @@ -4624,7 +4618,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK - if(!S_ISLNK(sbuf.st_mode)) { + if(!S_ISLNK(sbuf.st_ex_mode)) { reply_unixerror(req, ERRSRV, ERRbadlink); return; @@ -4674,7 +4668,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return; } - if (S_ISDIR(sbuf.st_mode)) { + if (S_ISDIR(sbuf.st_ex_mode)) { if (fsp && fsp->is_directory) { def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); } else { @@ -4890,7 +4884,7 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, } /* No links from a directory. */ - if (S_ISDIR(smb_fname->st.st_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { status = NT_STATUS_FILE_IS_A_DIRECTORY; goto out; } @@ -4935,12 +4929,12 @@ NTSTATUS smb_set_file_time(connection_struct *conn, /* get some defaults (no modifications) if any info is zero or -1. */ if (null_timespec(ft->atime)) { - ft->atime= get_atimespec(psbuf); + ft->atime= psbuf->st_ex_atime; action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } if (null_timespec(ft->mtime)) { - ft->mtime = get_mtimespec(psbuf); + ft->mtime = psbuf->st_ex_mtime; action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } @@ -4964,8 +4958,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, */ { - struct timespec mts = get_mtimespec(psbuf); - struct timespec ats = get_atimespec(psbuf); + struct timespec mts = psbuf->st_ex_mtime; + struct timespec ats = psbuf->st_ex_atime; if ((timespec_compare(&ft->atime, &ats) == 0) && (timespec_compare(&ft->mtime, &mts) == 0)) { return NT_STATUS_OK; @@ -5035,9 +5029,9 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, fname = fsp->fsp_name; } } - + if (dosmode) { - if (S_ISDIR(psbuf->st_mode)) { + if (S_ISDIR(psbuf->st_ex_mode)) { dosmode |= aDIR; } else { dosmode &= ~aDIR; @@ -6099,7 +6093,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, raw_unixmode = IVAL(pdata,84); if (VALID_STAT(*psbuf)) { - if (S_ISDIR(psbuf->st_mode)) { + if (S_ISDIR(psbuf->st_ex_mode)) { ptype = PERM_EXISTING_DIR; } else { ptype = PERM_EXISTING_FILE; @@ -6136,8 +6130,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; size = get_file_size_stat(psbuf); - ft.atime = get_atimespec(psbuf); - ft.mtime = get_mtimespec(psbuf); + ft.atime = psbuf->st_ex_atime; + ft.mtime = psbuf->st_ex_mtime; /* * We continue here as we might want to change the * owner uid/gid. @@ -6171,13 +6165,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Deal with the UNIX specific uid set. */ - if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) { + if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) { int ret; DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n", (unsigned int)set_owner, fname )); - if (S_ISLNK(psbuf->st_mode)) { + if (S_ISLNK(psbuf->st_ex_mode)) { ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1); } else { ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1); @@ -6196,7 +6190,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Deal with the UNIX specific gid set. */ - if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) { + if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) { DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", (unsigned int)set_owner, fname )); if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) { @@ -7123,7 +7117,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ @@ -7150,7 +7143,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size, max_data_bytes); - + return; } @@ -7253,7 +7246,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, reply_nterror(req, status); return; } - + /* Try and set any given EA. */ if (ea_list) { status = set_ea(conn, NULL, directory, ea_list); @@ -7274,7 +7267,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, SSVAL(params,0,0); send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes); - + return; } @@ -7327,7 +7320,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn, fnf_handle = 257; send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes); - + return; } @@ -7358,7 +7351,7 @@ static void call_trans2findnotifynext(connection_struct *conn, SSVAL(params,2,0); /* No EA errors */ send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes); - + return; } @@ -7508,7 +7501,7 @@ void reply_findnclose(struct smb_request *req) END_PROFILE(SMBfindnclose); return; } - + dptr_num = SVAL(req->vwv+0, 0); DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num)); @@ -7928,7 +7921,7 @@ void reply_transs2(struct smb_request *req) state->received_param += pcnt; state->received_data += dcnt; - + if ((state->received_data > state->total_data) || (state->received_param > state->total_param)) goto bad_param; diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index f219e5554c..0f70669772 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -353,7 +353,7 @@ bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ if (SMB_VFS_STAT(conn,dname,st) != 0) return(False); - ret = S_ISDIR(st->st_mode); + ret = S_ISDIR(st->st_ex_mode); if(!ret) errno = ENOTDIR; @@ -393,7 +393,7 @@ bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT * if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return False; - return(S_ISREG(sbuf->st_mode)); + return(S_ISREG(sbuf->st_ex_mode)); } /**************************************************************************** @@ -542,14 +542,14 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) if (ret == -1) return ret; - if (len == (uint64_t)st.st_size) + if (len == (uint64_t)st.st_ex_size) return 0; - if (len < (uint64_t)st.st_size) { + if (len < (uint64_t)st.st_ex_size) { /* Shrink - use ftruncate. */ DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", - fsp->fsp_name, (double)st.st_size )); + fsp->fsp_name, (double)st.st_ex_size )); contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK); @@ -571,7 +571,7 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) if (!lp_strict_allocate(SNUM(fsp->conn))) return 0; - len -= st.st_size; + len -= st.st_ex_size; len /= 1024; /* Len is now number of 1k blocks needed. */ space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); if (space_avail == (uint64_t)-1) { @@ -579,7 +579,7 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) } DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", - fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); + fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)space_avail )); if (len > space_avail) { errno = ENOSPC; @@ -639,12 +639,12 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) return ret; } - if (len <= st.st_size) { + if (len <= st.st_ex_size) { return 0; } DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n", - fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size))); + fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)(len - st.st_ex_size))); contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE); @@ -659,8 +659,8 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) } } - offset = st.st_size; - num_to_write = len - st.st_size; + offset = st.st_ex_size; + num_to_write = len - st.st_ex_size; total = 0; while (total < num_to_write) { @@ -816,8 +816,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn) && (cache_value.data[cache_value.length-1] == '\0')); if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0) - && (st.st_dev == st2.st_dev) && (st.st_ino == st2.st_ino) - && (S_ISDIR(st.st_mode))) { + && (st.st_ex_dev == st2.st_ex_dev) && (st.st_ex_ino == st2.st_ex_ino) + && (S_ISDIR(st.st_ex_mode))) { /* * Ok, we're done */ @@ -973,7 +973,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) { + (S_ISLNK(statbuf.st_ex_mode)) ) { if (free_resolved_name) { SAFE_FREE(resolved_name); } diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 80ee3ec0e8..1664f9a94d 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -157,31 +157,35 @@ static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc printf("readdir: %s\n", dent->d_name); if (VALID_STAT(st)) { + time_t tmp_time; printf(" stat available"); - if (S_ISREG(st.st_mode)) printf(" Regular File\n"); - else if (S_ISDIR(st.st_mode)) printf(" Directory\n"); - else if (S_ISCHR(st.st_mode)) printf(" Character Device\n"); - else if (S_ISBLK(st.st_mode)) printf(" Block Device\n"); - else if (S_ISFIFO(st.st_mode)) printf(" Fifo\n"); - else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); - else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); - printf(" Size: %10u", (unsigned int)st.st_size); + if (S_ISREG(st.st_ex_mode)) printf(" Regular File\n"); + else if (S_ISDIR(st.st_ex_mode)) printf(" Directory\n"); + else if (S_ISCHR(st.st_ex_mode)) printf(" Character Device\n"); + else if (S_ISBLK(st.st_ex_mode)) printf(" Block Device\n"); + else if (S_ISFIFO(st.st_ex_mode)) printf(" Fifo\n"); + else if (S_ISLNK(st.st_ex_mode)) printf(" Symbolic Link\n"); + else if (S_ISSOCK(st.st_ex_mode)) printf(" Socket\n"); + printf(" Size: %10u", (unsigned int)st.st_ex_size); #ifdef HAVE_STAT_ST_BLOCKS - printf(" Blocks: %9u", (unsigned int)st.st_blocks); + printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks); #endif #ifdef HAVE_STAT_ST_BLKSIZE - printf(" IO Block: %u\n", (unsigned int)st.st_blksize); + printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize); #endif - printf(" Device: 0x%10x", (unsigned int)st.st_dev); - printf(" Inode: %10u", (unsigned int)st.st_ino); - printf(" Links: %10u\n", (unsigned int)st.st_nlink); - printf(" Access: %05o", (int)((st.st_mode) & 007777)); + printf(" Device: 0x%10x", (unsigned int)st.st_ex_dev); + printf(" Inode: %10u", (unsigned int)st.st_ex_ino); + printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink); + printf(" Access: %05o", (int)((st.st_ex_mode) & 007777)); printf(" Uid: %5lu Gid: %5lu\n", - (unsigned long)st.st_uid, - (unsigned long)st.st_gid); - printf(" Access: %s", ctime(&(st.st_atime))); - printf(" Modify: %s", ctime(&(st.st_mtime))); - printf(" Change: %s", ctime(&(st.st_ctime))); + (unsigned long)st.st_ex_uid, + (unsigned long)st.st_ex_gid); + tmp_time = convert_timespec_to_time_t(st.st_ex_atime); + printf(" Access: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_mtime); + printf(" Modify: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_ctime); + printf(" Change: %s", ctime(&tmp_time)); } return NT_STATUS_OK; @@ -540,6 +544,7 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c struct passwd *pwd = NULL; struct group *grp = NULL; SMB_STRUCT_STAT st; + time_t tmp_time; if (argc != 2) { printf("Usage: stat <fname>\n"); @@ -552,38 +557,41 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c return NT_STATUS_UNSUCCESSFUL; } - pwd = sys_getpwuid(st.st_uid); + pwd = sys_getpwuid(st.st_ex_uid); if (pwd != NULL) user = pwd->pw_name; else user = null_string; - grp = sys_getgrgid(st.st_gid); + grp = sys_getgrgid(st.st_ex_gid); if (grp != NULL) group = grp->gr_name; else group = null_string; printf("stat: ok\n"); printf(" File: %s", argv[1]); - if (S_ISREG(st.st_mode)) printf(" Regular File\n"); - else if (S_ISDIR(st.st_mode)) printf(" Directory\n"); - else if (S_ISCHR(st.st_mode)) printf(" Character Device\n"); - else if (S_ISBLK(st.st_mode)) printf(" Block Device\n"); - else if (S_ISFIFO(st.st_mode)) printf(" Fifo\n"); - else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); - else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); - printf(" Size: %10u", (unsigned int)st.st_size); + if (S_ISREG(st.st_ex_mode)) printf(" Regular File\n"); + else if (S_ISDIR(st.st_ex_mode)) printf(" Directory\n"); + else if (S_ISCHR(st.st_ex_mode)) printf(" Character Device\n"); + else if (S_ISBLK(st.st_ex_mode)) printf(" Block Device\n"); + else if (S_ISFIFO(st.st_ex_mode)) printf(" Fifo\n"); + else if (S_ISLNK(st.st_ex_mode)) printf(" Symbolic Link\n"); + else if (S_ISSOCK(st.st_ex_mode)) printf(" Socket\n"); + printf(" Size: %10u", (unsigned int)st.st_ex_size); #ifdef HAVE_STAT_ST_BLOCKS - printf(" Blocks: %9u", (unsigned int)st.st_blocks); + printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks); #endif #ifdef HAVE_STAT_ST_BLKSIZE - printf(" IO Block: %u\n", (unsigned int)st.st_blksize); + printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize); #endif - printf(" Device: 0x%10x", (unsigned int)st.st_dev); - printf(" Inode: %10u", (unsigned int)st.st_ino); - printf(" Links: %10u\n", (unsigned int)st.st_nlink); - printf(" Access: %05o", (int)((st.st_mode) & 007777)); - printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, - (unsigned long)st.st_gid, group); - printf(" Access: %s", ctime(&(st.st_atime))); - printf(" Modify: %s", ctime(&(st.st_mtime))); - printf(" Change: %s", ctime(&(st.st_ctime))); + printf(" Device: 0x%10x", (unsigned int)st.st_ex_dev); + printf(" Inode: %10u", (unsigned int)st.st_ex_ino); + printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink); + printf(" Access: %05o", (int)((st.st_ex_mode) & 007777)); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user, + (unsigned long)st.st_ex_gid, group); + tmp_time = convert_timespec_to_time_t(st.st_ex_atime); + printf(" Access: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_mtime); + printf(" Modify: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_ctime); + printf(" Change: %s", ctime(&tmp_time)); return NT_STATUS_OK; } @@ -597,6 +605,7 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, struct passwd *pwd = NULL; struct group *grp = NULL; SMB_STRUCT_STAT st; + time_t tmp_time; if (argc != 2) { printf("Usage: fstat <fd>\n"); @@ -619,37 +628,40 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_UNSUCCESSFUL; } - pwd = sys_getpwuid(st.st_uid); + pwd = sys_getpwuid(st.st_ex_uid); if (pwd != NULL) user = pwd->pw_name; else user = null_string; - grp = sys_getgrgid(st.st_gid); + grp = sys_getgrgid(st.st_ex_gid); if (grp != NULL) group = grp->gr_name; else group = null_string; printf("fstat: ok\n"); - if (S_ISREG(st.st_mode)) printf(" Regular File\n"); - else if (S_ISDIR(st.st_mode)) printf(" Directory\n"); - else if (S_ISCHR(st.st_mode)) printf(" Character Device\n"); - else if (S_ISBLK(st.st_mode)) printf(" Block Device\n"); - else if (S_ISFIFO(st.st_mode)) printf(" Fifo\n"); - else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); - else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); - printf(" Size: %10u", (unsigned int)st.st_size); + if (S_ISREG(st.st_ex_mode)) printf(" Regular File\n"); + else if (S_ISDIR(st.st_ex_mode)) printf(" Directory\n"); + else if (S_ISCHR(st.st_ex_mode)) printf(" Character Device\n"); + else if (S_ISBLK(st.st_ex_mode)) printf(" Block Device\n"); + else if (S_ISFIFO(st.st_ex_mode)) printf(" Fifo\n"); + else if (S_ISLNK(st.st_ex_mode)) printf(" Symbolic Link\n"); + else if (S_ISSOCK(st.st_ex_mode)) printf(" Socket\n"); + printf(" Size: %10u", (unsigned int)st.st_ex_size); #ifdef HAVE_STAT_ST_BLOCKS - printf(" Blocks: %9u", (unsigned int)st.st_blocks); + printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks); #endif #ifdef HAVE_STAT_ST_BLKSIZE - printf(" IO Block: %u\n", (unsigned int)st.st_blksize); + printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize); #endif - printf(" Device: 0x%10x", (unsigned int)st.st_dev); - printf(" Inode: %10u", (unsigned int)st.st_ino); - printf(" Links: %10u\n", (unsigned int)st.st_nlink); - printf(" Access: %05o", (int)((st.st_mode) & 007777)); - printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, - (unsigned long)st.st_gid, group); - printf(" Access: %s", ctime(&(st.st_atime))); - printf(" Modify: %s", ctime(&(st.st_mtime))); - printf(" Change: %s", ctime(&(st.st_ctime))); + printf(" Device: 0x%10x", (unsigned int)st.st_ex_dev); + printf(" Inode: %10u", (unsigned int)st.st_ex_ino); + printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink); + printf(" Access: %05o", (int)((st.st_ex_mode) & 007777)); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user, + (unsigned long)st.st_ex_gid, group); + tmp_time = convert_timespec_to_time_t(st.st_ex_atime); + printf(" Access: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_mtime); + printf(" Modify: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_ctime); + printf(" Change: %s", ctime(&tmp_time)); return NT_STATUS_OK; } @@ -662,6 +674,7 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, struct passwd *pwd = NULL; struct group *grp = NULL; SMB_STRUCT_STAT st; + time_t tmp_time; if (argc != 2) { printf("Usage: lstat <path>\n"); @@ -673,37 +686,40 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_UNSUCCESSFUL; } - pwd = sys_getpwuid(st.st_uid); + pwd = sys_getpwuid(st.st_ex_uid); if (pwd != NULL) user = pwd->pw_name; else user = null_string; - grp = sys_getgrgid(st.st_gid); + grp = sys_getgrgid(st.st_ex_gid); if (grp != NULL) group = grp->gr_name; else group = null_string; printf("lstat: ok\n"); - if (S_ISREG(st.st_mode)) printf(" Regular File\n"); - else if (S_ISDIR(st.st_mode)) printf(" Directory\n"); - else if (S_ISCHR(st.st_mode)) printf(" Character Device\n"); - else if (S_ISBLK(st.st_mode)) printf(" Block Device\n"); - else if (S_ISFIFO(st.st_mode)) printf(" Fifo\n"); - else if (S_ISLNK(st.st_mode)) printf(" Symbolic Link\n"); - else if (S_ISSOCK(st.st_mode)) printf(" Socket\n"); - printf(" Size: %10u", (unsigned int)st.st_size); + if (S_ISREG(st.st_ex_mode)) printf(" Regular File\n"); + else if (S_ISDIR(st.st_ex_mode)) printf(" Directory\n"); + else if (S_ISCHR(st.st_ex_mode)) printf(" Character Device\n"); + else if (S_ISBLK(st.st_ex_mode)) printf(" Block Device\n"); + else if (S_ISFIFO(st.st_ex_mode)) printf(" Fifo\n"); + else if (S_ISLNK(st.st_ex_mode)) printf(" Symbolic Link\n"); + else if (S_ISSOCK(st.st_ex_mode)) printf(" Socket\n"); + printf(" Size: %10u", (unsigned int)st.st_ex_size); #ifdef HAVE_STAT_ST_BLOCKS - printf(" Blocks: %9u", (unsigned int)st.st_blocks); + printf(" Blocks: %9u", (unsigned int)st.st_ex_blocks); #endif #ifdef HAVE_STAT_ST_BLKSIZE - printf(" IO Block: %u\n", (unsigned int)st.st_blksize); + printf(" IO Block: %u\n", (unsigned int)st.st_ex_blksize); #endif - printf(" Device: 0x%10x", (unsigned int)st.st_dev); - printf(" Inode: %10u", (unsigned int)st.st_ino); - printf(" Links: %10u\n", (unsigned int)st.st_nlink); - printf(" Access: %05o", (int)((st.st_mode) & 007777)); - printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, - (unsigned long)st.st_gid, group); - printf(" Access: %s", ctime(&(st.st_atime))); - printf(" Modify: %s", ctime(&(st.st_mtime))); - printf(" Change: %s", ctime(&(st.st_ctime))); + printf(" Device: 0x%10x", (unsigned int)st.st_ex_dev); + printf(" Inode: %10u", (unsigned int)st.st_ex_ino); + printf(" Links: %10u\n", (unsigned int)st.st_ex_nlink); + printf(" Access: %05o", (int)((st.st_ex_mode) & 007777)); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_ex_uid, user, + (unsigned long)st.st_ex_gid, group); + tmp_time = convert_timespec_to_time_t(st.st_ex_atime); + printf(" Access: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_mtime); + printf(" Modify: %s", ctime(&tmp_time)); + tmp_time = convert_timespec_to_time_t(st.st_ex_ctime); + printf(" Change: %s", ctime(&tmp_time)); return NT_STATUS_OK; } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 41343cab87..b05ca44f0e 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -4135,8 +4135,12 @@ static bool run_opentest(int dummy) static bool run_simple_posix_open_test(int dummy) { static struct cli_state *cli1; - const char *fname = "\\posix:file"; - const char *dname = "\\posix:dir"; + const char *fname = "posix:file"; + const char *hname = "posix:hlink"; + const char *sname = "posix:symlink"; + const char *dname = "posix:dir"; + char buf[10]; + char namebuf[11]; uint16 major, minor; uint32 caplow, caphigh; uint16_t fnum1 = (uint16_t)-1; @@ -4171,6 +4175,10 @@ static bool run_simple_posix_open_test(int dummy) cli_posix_unlink(cli1, fname); cli_setatr(cli1, dname, 0, 0); cli_posix_rmdir(cli1, dname); + cli_setatr(cli1, hname, 0, 0); + cli_posix_unlink(cli1, hname); + cli_setatr(cli1, sname, 0, 0); + cli_posix_unlink(cli1, sname); /* Create a directory. */ if (!NT_STATUS_IS_OK(cli_posix_mkdir(cli1, dname, 0777))) { @@ -4222,6 +4230,77 @@ static bool run_simple_posix_open_test(int dummy) } } + /* Create the file. */ + if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) { + printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1)); + goto out; + } + + /* Write some data into it. */ + if (cli_write(cli1, fnum1, 0, "TEST DATA\n", 0, 10) != 10) { + printf("cli_write failed: %s\n", cli_errstr(cli1)); + goto out; + } + + cli_close(cli1, fnum1); + + /* Now create a hardlink. */ + if (!NT_STATUS_IS_OK(cli_posix_hardlink(cli1, fname, hname))) { + printf("POSIX hardlink of %s failed (%s)\n", hname, cli_errstr(cli1)); + goto out; + } + + /* Now create a symlink. */ + if (!NT_STATUS_IS_OK(cli_posix_symlink(cli1, fname, sname))) { + printf("POSIX symlink of %s failed (%s)\n", sname, cli_errstr(cli1)); + goto out; + } + + /* Open the hardlink for read. */ + if (!NT_STATUS_IS_OK(cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1))) { + printf("POSIX open of %s failed (%s)\n", hname, cli_errstr(cli1)); + goto out; + } + + if (cli_read(cli1, fnum1, buf, 0, 10) != 10) { + printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1)); + goto out; + } + + if (memcmp(buf, "TEST DATA\n", 10)) { + printf("invalid data read from hardlink\n"); + goto out; + } + + cli_close(cli1, fnum1); + + /* Open the symlink for read - this should fail. A POSIX + client should not be doing opens on a symlink. */ + if (NT_STATUS_IS_OK(cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1))) { + printf("POSIX open of %s succeeded (should have failed)\n", sname); + goto out; + } else { + if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath, + NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + printf("POSIX open of %s should have failed " + "with NT_STATUS_OBJECT_PATH_NOT_FOUND, " + "failed with %s instead.\n", + sname, cli_errstr(cli1)); + goto out; + } + } + + if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) { + printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1)); + goto out; + } + + if (strcmp(namebuf, fname) != 0) { + printf("POSIX readlink on %s failed to match name %s (read %s)\n", + sname, fname, namebuf); + goto out; + } + if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) { printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1)); goto out; @@ -4237,6 +4316,10 @@ static bool run_simple_posix_open_test(int dummy) fnum1 = (uint16_t)-1; } + cli_setatr(cli1, sname, 0, 0); + cli_posix_unlink(cli1, sname); + cli_setatr(cli1, hname, 0, 0); + cli_posix_unlink(cli1, hname); cli_setatr(cli1, fname, 0, 0); cli_posix_unlink(cli1, fname); cli_setatr(cli1, dname, 0, 0); diff --git a/source3/utils/net_conf.c b/source3/utils/net_conf.c index 69a41e30d9..6b0f70adfa 100644 --- a/source3/utils/net_conf.c +++ b/source3/utils/net_conf.c @@ -662,7 +662,7 @@ static int net_conf_addshare(struct net_context *c, goto done; } - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { d_fprintf(stderr, "ERROR: path '%s' is not a directory.\n", path); diff --git a/source3/utils/net_usershare.c b/source3/utils/net_usershare.c index dadb88303b..992a03d813 100644 --- a/source3/utils/net_usershare.c +++ b/source3/utils/net_usershare.c @@ -250,13 +250,13 @@ static int get_share_list(TALLOC_CTX *ctx, const char *wcard, bool only_ours) continue; } - if (!S_ISREG(sbuf.st_mode)) { + if (!S_ISREG(sbuf.st_ex_mode)) { d_fprintf(stderr, "get_share_list: file %s is not a regular file. Ignoring.\n", path ); continue; } - if (only_ours && sbuf.st_uid != myuid) { + if (only_ours && sbuf.st_ex_uid != myuid) { continue; } @@ -364,7 +364,7 @@ static int info_fn(struct file_list *fl, void *priv) return -1; } - if (!S_ISREG(sbuf.st_mode)) { + if (!S_ISREG(sbuf.st_ex_mode)) { d_fprintf(stderr, "info_fn: file %s is not a regular file. Ignoring.\n", basepath ); close(fd); @@ -574,7 +574,7 @@ static int count_num_usershares(void) continue; } - if (!S_ISREG(sbuf.st_mode)) { + if (!S_ISREG(sbuf.st_ex_mode)) { d_fprintf(stderr, "count_num_usershares: file %s is not a regular file. Ignoring.\n", path ); continue; @@ -738,7 +738,7 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) return -1; } - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { d_fprintf(stderr, "net usershare add: path %s is not a directory.\n", us_path ); TALLOC_FREE(ctx); @@ -749,7 +749,7 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) /* If we're not root, check if we're restricted to sharing out directories that we own only. */ - if ((myeuid != 0) && lp_usershare_owner_only() && (myeuid != sbuf.st_uid)) { + if ((myeuid != 0) && lp_usershare_owner_only() && (myeuid != sbuf.st_ex_uid)) { d_fprintf(stderr, "net usershare add: cannot share path %s as " "we are restricted to only sharing directories we own.\n" "\tAsk the administrator to add the line \"usershare owner only = false\" \n" @@ -887,7 +887,7 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) return -1; } - if (!S_ISREG(sbuf.st_mode) || sbuf.st_dev != lsbuf.st_dev || sbuf.st_ino != lsbuf.st_ino) { + if (!S_ISREG(sbuf.st_ex_mode) || sbuf.st_ex_dev != lsbuf.st_ex_dev || sbuf.st_ex_ino != lsbuf.st_ex_ino) { d_fprintf(stderr, "net usershare add: tmp file %s is not a regular file ?\n", full_path_tmp ); TALLOC_FREE(ctx); diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index e8458fda1b..519eb6954a 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -60,7 +60,7 @@ cannot be set in the smb.conf file. nmbd will abort with this setting.\n"); fprintf(stderr, "ERROR: lock directory %s does not exist\n", lp_lockdir()); ret = 1; - } else if ((st.st_mode & 0777) != 0755) { + } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: lock directory %s should have permissions 0755 for browsing to work\n", lp_lockdir()); ret = 1; @@ -70,7 +70,7 @@ cannot be set in the smb.conf file. nmbd will abort with this setting.\n"); fprintf(stderr, "ERROR: state directory %s does not exist\n", lp_statedir()); ret = 1; - } else if ((st.st_mode & 0777) != 0755) { + } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: state directory %s should have permissions 0755 for browsing to work\n", lp_statedir()); ret = 1; @@ -80,7 +80,7 @@ cannot be set in the smb.conf file. nmbd will abort with this setting.\n"); fprintf(stderr, "ERROR: cache directory %s does not exist\n", lp_cachedir()); ret = 1; - } else if ((st.st_mode & 0777) != 0755) { + } else if ((st.st_ex_mode & 0777) != 0755) { fprintf(stderr, "WARNING: cache directory %s should have permissions 0755 for browsing to work\n", lp_cachedir()); ret = 1; diff --git a/source3/web/cgi.c b/source3/web/cgi.c index 261d4366bf..a31943fa8d 100644 --- a/source3/web/cgi.c +++ b/source3/web/cgi.c @@ -448,16 +448,16 @@ static void cgi_download(char *file) "The requested file was not found"); } - if (S_ISDIR(st.st_mode)) + if (S_ISDIR(st.st_ex_mode)) { snprintf(buf, sizeof(buf), "%s/index.html", file); - if (!file_exist_stat(buf, &st) || !S_ISREG(st.st_mode)) + if (!file_exist_stat(buf, &st) || !S_ISREG(st.st_ex_mode)) { cgi_setup_error("404 File Not Found","", "The requested file was not found"); } } - else if (S_ISREG(st.st_mode)) + else if (S_ISREG(st.st_ex_mode)) { snprintf(buf, sizeof(buf), "%s", file); } @@ -496,7 +496,7 @@ static void cgi_download(char *file) printf("Content-Language: %s\r\n", lang); } - printf("Content-Length: %d\r\n\r\n", (int)st.st_size); + printf("Content-Length: %d\r\n\r\n", (int)st.st_ex_size); while ((l=read(fd,buf,sizeof(buf)))>0) { if (fwrite(buf, 1, l, stdout) != l) { break; diff --git a/source3/winbindd/idmap.c b/source3/winbindd/idmap.c index c097170d03..4aa229cd66 100644 --- a/source3/winbindd/idmap.c +++ b/source3/winbindd/idmap.c @@ -761,7 +761,7 @@ NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id) struct idmap_domain *dom; struct id_map *maps[2]; - DEBUG(10, ("idmap_backend_sid_to_unixid: domain = '%s', sid = [%s]\n", + DEBUG(10, ("idmap_backends_sid_to_unixid: domain = '%s', sid = [%s]\n", domain?domain:"NULL", sid_string_dbg(id->sid))); maps[0] = id; diff --git a/source3/winbindd/idmap_ldap.c b/source3/winbindd/idmap_ldap.c index 88ece8c7de..3d1dd488d6 100644 --- a/source3/winbindd/idmap_ldap.c +++ b/source3/winbindd/idmap_ldap.c @@ -765,7 +765,6 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, NTSTATUS ret; struct idmap_ldap_context *ctx = NULL; char *config_option = NULL; - const char *range = NULL; const char *tmp = NULL; /* Only do init if we are online */ @@ -779,23 +778,63 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, return NT_STATUS_NO_MEMORY; } - config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); - if ( ! config_option) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } + if (strequal(dom->name, "*")) { + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; - /* load ranges */ - range = lp_parm_const_string(-1, config_option, "range", NULL); - if (range && range[0]) { - if ((sscanf(range, "%u - %u", &ctx->filter_low_id, - &ctx->filter_high_id) != 2) || - (ctx->filter_low_id > ctx->filter_high_id)) { - DEBUG(1, ("ERROR: invalid filter range [%s]", range)); - ctx->filter_low_id = 0; - ctx->filter_high_id = 0; + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + + if (lp_idmap_uid(&low_uid, &high_uid)) { + ctx->filter_low_id = low_uid; + ctx->filter_high_id = high_uid; + } else { + DEBUG(3, ("Warning: 'idmap uid' not set!\n")); + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + if ((low_gid != low_uid) || (high_gid != high_uid)) { + DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'" + " ranges do not agree -- building " + "intersection\n")); + ctx->filter_low_id = MAX(ctx->filter_low_id, + low_gid); + ctx->filter_high_id = MIN(ctx->filter_high_id, + high_gid); + } + } else { + DEBUG(3, ("Warning: 'idmap gid' not set!\n")); + } + } else { + const char *range = NULL; + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; } + + /* load ranges */ + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (range && range[0]) { + if ((sscanf(range, "%u - %u", &ctx->filter_low_id, + &ctx->filter_high_id) != 2)) + { + DEBUG(1, ("ERROR: invalid filter range [%s]", range)); + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + } + } + + if (ctx->filter_low_id > ctx->filter_high_id) { + DEBUG(1, ("ERROR: invalid filter range [%u-%u]", + ctx->filter_low_id, ctx->filter_high_id)); + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; } if (params != NULL) { diff --git a/source3/winbindd/idmap_tdb.c b/source3/winbindd/idmap_tdb.c index 22c17578e6..c42cd74cbe 100644 --- a/source3/winbindd/idmap_tdb.c +++ b/source3/winbindd/idmap_tdb.c @@ -593,8 +593,8 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) { NTSTATUS ret; struct idmap_tdb_context *ctx; - char *config_option = NULL; - const char *range; + + DEBUG(10, ("idmap_tdb_db_init called for domain '%s'\n", dom->name)); ctx = talloc(dom, struct idmap_tdb_context); if ( ! ctx) { @@ -602,29 +602,72 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params) return NT_STATUS_NO_MEMORY; } - config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); - if ( ! config_option) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto failed; - } + if (strequal(dom->name, "*")) { + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; - ret = idmap_tdb_open_db(ctx, false, &ctx->db); - if ( ! NT_STATUS_IS_OK(ret)) { - goto failed; + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + + if (lp_idmap_uid(&low_uid, &high_uid)) { + ctx->filter_low_id = low_uid; + ctx->filter_high_id = high_uid; + } else { + DEBUG(3, ("Warning: 'idmap uid' not set!\n")); + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + if ((low_gid != low_uid) || (high_gid != high_uid)) { + DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'" + " ranges do not agree -- building " + "intersection\n")); + ctx->filter_low_id = MAX(ctx->filter_low_id, + low_gid); + ctx->filter_high_id = MIN(ctx->filter_high_id, + high_gid); + } + } else { + DEBUG(3, ("Warning: 'idmap gid' not set!\n")); + } + } else { + char *config_option = NULL; + const char *range; + + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto failed; + } + + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (( ! range) || + (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2)) + { + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + + talloc_free(config_option); } - range = lp_parm_const_string(-1, config_option, "range", NULL); - if (( ! range) || - (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) || - (ctx->filter_low_id > ctx->filter_high_id)) { + if (ctx->filter_low_id > ctx->filter_high_id) { ctx->filter_low_id = 0; ctx->filter_high_id = 0; } + DEBUG(10, ("idmap_tdb_db_init: filter range %u-%u loaded for domain " + "'%s'\n", ctx->filter_low_id, ctx->filter_high_id, dom->name)); + + ret = idmap_tdb_open_db(ctx, false, &ctx->db); + if ( ! NT_STATUS_IS_OK(ret)) { + goto failed; + } + dom->private_data = ctx; - talloc_free(config_option); return NT_STATUS_OK; failed: diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c index b2723270eb..d34d289906 100644 --- a/source3/winbindd/idmap_tdb2.c +++ b/source3/winbindd/idmap_tdb2.c @@ -357,8 +357,6 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, { NTSTATUS ret; struct idmap_tdb2_context *ctx; - char *config_option = NULL; - const char *range; NTSTATUS status; status = idmap_tdb2_open_db(); @@ -370,24 +368,63 @@ static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom, return NT_STATUS_NO_MEMORY; } - config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); - if ( ! config_option) { - DEBUG(0, ("Out of memory!\n")); - ret = NT_STATUS_NO_MEMORY; - goto failed; + if (strequal(dom->name, "*")) { + uid_t low_uid = 0; + uid_t high_uid = 0; + gid_t low_gid = 0; + gid_t high_gid = 0; + + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + + if (lp_idmap_uid(&low_uid, &high_uid)) { + ctx->filter_low_id = low_uid; + ctx->filter_high_id = high_uid; + } else { + DEBUG(3, ("Warning: 'idmap uid' not set!\n")); + } + + if (lp_idmap_gid(&low_gid, &high_gid)) { + if ((low_gid != low_uid) || (high_gid != high_uid)) { + DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'" + " ranges do not agree -- building " + "intersection\n")); + ctx->filter_low_id = MAX(ctx->filter_low_id, + low_gid); + ctx->filter_high_id = MIN(ctx->filter_high_id, + high_gid); + } + } else { + DEBUG(3, ("Warning: 'idmap gid' not set!\n")); + } + } else { + char *config_option = NULL; + const char *range; + config_option = talloc_asprintf(ctx, "idmap config %s", dom->name); + if ( ! config_option) { + DEBUG(0, ("Out of memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto failed; + } + + range = lp_parm_const_string(-1, config_option, "range", NULL); + if (( ! range) || + (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2)) + { + ctx->filter_low_id = 0; + ctx->filter_high_id = 0; + } + + talloc_free(config_option); } - range = lp_parm_const_string(-1, config_option, "range", NULL); - if (( ! range) || - (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) || - (ctx->filter_low_id > ctx->filter_high_id)) { + if (ctx->filter_low_id > ctx->filter_high_id) { ctx->filter_low_id = 0; ctx->filter_high_id = 0; } dom->private_data = ctx; - talloc_free(config_option); return NT_STATUS_OK; failed: diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index e1ce223475..2b25616cf7 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -1304,8 +1304,9 @@ int main(int argc, char **argv, char **envp) * winbindd-specific resources we must free yet. JRA. */ - if (!reinit_after_fork(winbind_messaging_context(), - winbind_event_context(), false)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(), + winbind_event_context(), + false))) { DEBUG(0,("reinit_after_fork() failed\n")); exit(1); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index a69d34f30c..6fb0b5857c 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -1121,8 +1121,9 @@ bool winbindd_reinit_after_fork(const char *logfilename) struct winbindd_domain *domain; struct winbindd_child *cl; - if (!reinit_after_fork(winbind_messaging_context(), - winbind_event_context(), true)) { + if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(), + winbind_event_context(), + true))) { DEBUG(0,("reinit_after_fork() failed\n")); return false; } diff --git a/source4/autogen.sh b/source4/autogen.sh index 8b97023073..2d995caeae 100755 --- a/source4/autogen.sh +++ b/source4/autogen.sh @@ -22,7 +22,12 @@ TESTAUTOCONF="autoconf autoconf-2.53 autoconf2.50 autoconf259 autoconf253" AUTOHEADERFOUND="0" AUTOCONFFOUND="0" - +if which which > /dev/null 2>&1; then + echo -n +else + echo "$0: need 'which' to figure out if we have the right autoconf to build samba from git" >&2 + exit 1 +fi ## ## Look for autoheader ## diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c index 0b5994bb88..5bed28b00c 100644 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -514,7 +514,7 @@ static int kludge_acl_init(struct ldb_module *module) ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, - "partition: Unable to register control with rootdse!\n"); + "kludge_acl: Unable to register control with rootdse!\n"); return LDB_ERR_OPERATIONS_ERROR; } diff --git a/source4/dsdb/samdb/ldb_modules/show_deleted.c b/source4/dsdb/samdb/ldb_modules/show_deleted.c index d619558c21..b4f52d7cde 100644 --- a/source4/dsdb/samdb/ldb_modules/show_deleted.c +++ b/source4/dsdb/samdb/ldb_modules/show_deleted.c @@ -145,7 +145,7 @@ static int show_deleted_init(struct ldb_module *module) ret = ldb_mod_register_control(module, LDB_CONTROL_SHOW_DELETED_OID); if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_ERROR, - "extended_dn: Unable to register control with rootdse!\n"); + "show_deleted: Unable to register control with rootdse!\n"); return LDB_ERR_OPERATIONS_ERROR; } diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 1fdb744a84..585285795f 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -38,6 +38,7 @@ #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" #include "librpc/gen_ndr/netlogon.h" +#include "libcli/security/security.h" #include "auth/auth.h" #include "auth/credentials/credentials.h" #include "auth/auth_sam.h" @@ -499,7 +500,9 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, struct hdb_ldb_private *p; NTTIME acct_expiry; + NTSTATUS status; + uint32_t rid; struct ldb_message_element *objectclasses; struct ldb_val computer_val; const char *samAccountName = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); @@ -580,49 +583,70 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, /* First try and figure out the flags based on the userAccountControl */ entry_ex->entry.flags = uf2HDBFlags(context, userAccountControl, ent_type); - if (ent_type == HDB_SAMBA4_ENT_TYPE_KRBTGT) { - entry_ex->entry.flags.invalid = 0; - entry_ex->entry.flags.server = 1; - entry_ex->entry.flags.forwardable = 1; - entry_ex->entry.flags.ok_as_delegate = 1; - } - /* Windows 2008 seems to enforce this (very sensible) rule by * default - don't allow offline attacks on a user's password * by asking for a ticket to them as a service (encrypted with * their probably patheticly insecure password) */ - if (lp_parm_bool(lp_ctx, NULL, "kdc", "require spn for service", true)) { + if (entry_ex->entry.flags.server + && lp_parm_bool(lp_ctx, NULL, "kdc", "require spn for service", true)) { if (!is_computer && !ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL)) { entry_ex->entry.flags.server = 0; } } - /* use 'whenCreated' */ - entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); - /* use '???' */ - entry_ex->entry.created_by.principal = NULL; + { + /* These (created_by, modified_by) parts of the entry are not relevant for Samba4's use + * of the Heimdal KDC. They are stored in a the traditional + * DB for audit purposes, and still form part of the structure + * we must return */ + + /* use 'whenCreated' */ + entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); + /* use '???' */ + entry_ex->entry.created_by.principal = NULL; + + entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event)); + if (entry_ex->entry.modified_by == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + /* use 'whenChanged' */ + entry_ex->entry.modified_by->time = ldb_msg_find_krb5time_ldap_time(msg, "whenChanged", 0); + /* use '???' */ + entry_ex->entry.modified_by->principal = NULL; + } - entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event)); - if (entry_ex->entry.modified_by == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; + + /* The lack of password controls etc applies to krbtgt by + * virtue of being that particular RID */ + status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, msg, "objectSid"), NULL, &rid); + + if (!NT_STATUS_IS_OK(status)) { + ret = EINVAL; goto out; } - /* use 'whenChanged' */ - entry_ex->entry.modified_by->time = ldb_msg_find_krb5time_ldap_time(msg, "whenChanged", 0); - /* use '???' */ - entry_ex->entry.modified_by->principal = NULL; + if (rid == DOMAIN_RID_KRBTGT) { + entry_ex->entry.valid_end = NULL; + entry_ex->entry.pw_end = NULL; - entry_ex->entry.valid_start = NULL; + entry_ex->entry.flags.invalid = 0; + entry_ex->entry.flags.server = 1; + entry_ex->entry.flags.change_pw = 1; + entry_ex->entry.flags.client = 0; + entry_ex->entry.flags.forwardable = 1; + entry_ex->entry.flags.ok_as_delegate = 1; + } else if (entry_ex->entry.flags.server && ent_type == HDB_SAMBA4_ENT_TYPE_SERVER) { + /* The account/password expiry only applies when the account is used as a + * client (ie password login), not when used as a server */ - /* The account/password expiry only applies when the account is used as a - * client (ie password login), not when used as a server */ - if (ent_type == HDB_SAMBA4_ENT_TYPE_KRBTGT || ent_type == HDB_SAMBA4_ENT_TYPE_SERVER) { /* Make very well sure we don't use this for a client, - * it could bypass the above password restrictions */ + * it could bypass the password restrictions */ entry_ex->entry.flags.client = 0; + entry_ex->entry.valid_end = NULL; entry_ex->entry.pw_end = NULL; @@ -653,7 +677,9 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db, *entry_ex->entry.valid_end = nt_time_to_unix(acct_expiry); } } - + + entry_ex->entry.valid_start = NULL; + entry_ex->entry.max_life = NULL; entry_ex->entry.max_renew = NULL; diff --git a/source4/lib/events/tevent_s4.c b/source4/lib/events/tevent_s4.c index 06bfbf61ed..1898269c2c 100644 --- a/source4/lib/events/tevent_s4.c +++ b/source4/lib/events/tevent_s4.c @@ -42,7 +42,7 @@ static void ev_wrap_debug(void *context, enum tevent_debug_level level, samba_level = 2; break; case TEVENT_DEBUG_TRACE: - samba_level = 10; + samba_level = 50; break; }; diff --git a/source4/lib/ldb/common/ldb_controls.c b/source4/lib/ldb/common/ldb_controls.c index 0c587e0905..6f127d8c39 100644 --- a/source4/lib/ldb/common/ldb_controls.c +++ b/source4/lib/ldb/common/ldb_controls.c @@ -39,7 +39,6 @@ struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char { int i; - /* check if there's a paged request control */ if (req->controls != NULL) { for (i = 0; req->controls[i]; i++) { if (strcmp(oid, req->controls[i]->oid) == 0) { @@ -59,7 +58,6 @@ struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid { int i; - /* check if there's a paged request control */ if (rep->controls != NULL) { for (i = 0; rep->controls[i]; i++) { if (strcmp(oid, rep->controls[i]->oid) == 0) { @@ -75,7 +73,7 @@ struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid /* saves the current controls list into the "saver" and replace the one in req with a new one excluding the "exclude" control */ -/* returns False on error */ +/* returns 0 on error */ int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver) { struct ldb_control **lcs; diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c index 475b609e41..dd5afd868c 100644 --- a/source4/lib/ldb/modules/asq.c +++ b/source4/lib/ldb/modules/asq.c @@ -351,7 +351,7 @@ static int asq_search(struct ldb_module *module, struct ldb_request *req) ldb = ldb_module_get_ctx(module); - /* check if there's a paged request control */ + /* check if there's an ASQ control */ control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID); if (control == NULL) { /* not found go on */ diff --git a/source4/lib/ldb/modules/paged_results.c b/source4/lib/ldb/modules/paged_results.c index 2a06c5e6c5..f2692305d5 100644 --- a/source4/lib/ldb/modules/paged_results.c +++ b/source4/lib/ldb/modules/paged_results.c @@ -408,7 +408,7 @@ static int paged_request_init(struct ldb_module *module) ret = ldb_mod_register_control(module, LDB_CONTROL_PAGED_RESULTS_OID); if (ret != LDB_SUCCESS) { ldb_debug(ldb, LDB_DEBUG_WARNING, - "paged_request:" + "paged_results:" "Unable to register control with rootdse!\n"); } diff --git a/source4/lib/ldb/modules/sort.c b/source4/lib/ldb/modules/sort.c index 309101c32b..b4f76e1007 100644 --- a/source4/lib/ldb/modules/sort.c +++ b/source4/lib/ldb/modules/sort.c @@ -255,7 +255,7 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req ldb = ldb_module_get_ctx(module); - /* check if there's a paged request control */ + /* check if there's a server sort control */ control = ldb_request_get_control(req, LDB_CONTROL_SERVER_SORT_OID); if (control == NULL) { /* not found go on */ diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 8d6ea04dc8..8c1a73b681 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -164,8 +164,11 @@ static void continue_socket(struct composite_context *creq) struct smbcli_socket *sock; struct smb2_transport *transport; struct smb2_request *req; - uint16_t dialects[3] = { SMB2_DIALECT_REVISION, SMB21_DIALECT_REVISION, - SMB2_LONGHORN_BETA_DIALECT_REVISION }; + uint16_t dialects[3] = { + SMB2_DIALECT_REVISION_000, + SMB2_DIALECT_REVISION_202, + SMB2_DIALECT_REVISION_210 + }; c->status = smbcli_sock_connect_recv(creq, state, &sock); if (!composite_is_ok(c)) return; diff --git a/source4/libcli/smb2/smb2_constants.h b/source4/libcli/smb2/smb2_constants.h index 86dfbfedbe..48f30972dc 100644 --- a/source4/libcli/smb2/smb2_constants.h +++ b/source4/libcli/smb2/smb2_constants.h @@ -68,10 +68,11 @@ #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */ -/* the dialects we support */ -#define SMB2_DIALECT_REVISION 0x202 -#define SMB21_DIALECT_REVISION 0x210 -#define SMB2_LONGHORN_BETA_DIALECT_REVISION 0x0 /* early beta dialect */ +/* SMB2 negotiate dialects */ +#define SMB2_DIALECT_REVISION_000 0x0000 /* early beta dialect */ +#define SMB2_DIALECT_REVISION_202 0x0202 +#define SMB2_DIALECT_REVISION_210 0x0210 +#define SMB2_DIALECT_REVISION_2FF 0x02FF /* SMB2 negotiate security_mode */ #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 @@ -79,9 +80,14 @@ /* SMB2 capabilities - only 1 so far. I'm sure more will be added */ #define SMB2_CAP_DFS 0x00000001 +#define SMB2_CAP_LEASING 0x00000002 /* only in dialect 0x210 */ /* so we can spot new caps as added */ #define SMB2_CAP_ALL SMB2_CAP_DFS +/* SMB2 session flags */ +#define SMB2_SESSION_FLAG_IS_GUEST 0x0001 +#define SMB2_SESSION_FLAG_IS_NULL 0x0002 + /* SMB2 share flags */ #define SMB2_SHAREFLAG_MANUAL_CACHING 0x0000 #define SMB2_SHAREFLAG_AUTO_CACHING 0x0010 diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 17b5450a3e..454a9d144c 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -36,14 +36,14 @@ class SamDB(samba.Ldb): """The SAM database.""" def __init__(self, url=None, session_info=None, credentials=None, - modules_dir=None, lp=None): + modules_dir=None, lp=None, options=None): """Open the Sam Database. :param url: URL of the database. """ self.lp = lp super(SamDB, self).__init__(session_info=session_info, credentials=credentials, - modules_dir=modules_dir, lp=lp) + modules_dir=modules_dir, lp=lp, options=options) glue.dsdb_set_global_schema(self) if url: self.connect(url) diff --git a/source4/smb_server/smb/negprot.c b/source4/smb_server/smb/negprot.c index c3399fdd48..5ac5624745 100644 --- a/source4/smb_server/smb/negprot.c +++ b/source4/smb_server/smb/negprot.c @@ -469,7 +469,6 @@ static const struct { int protocol_level; } supported_protocols[] = { {"SMB 2.002", "SMB2", reply_smb2, PROTOCOL_SMB2}, - {"SMB 2.001", "SMB2", reply_smb2, PROTOCOL_SMB2}, {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index 0b65a19634..f915392ffa 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -97,14 +97,21 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 NTSTATUS status; struct timeval current_time; struct timeval boot_time; + uint16_t i; + uint16_t dialect = 0; /* we only do one dialect for now */ if (io->in.dialect_count < 1) { return NT_STATUS_NOT_SUPPORTED; } - if (io->in.dialects[0] != 0 && - io->in.dialects[0] != SMB2_DIALECT_REVISION) { - DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0])); + for (i=0; i < io->in.dialect_count; i++) { + dialect = io->in.dialects[i]; + if (dialect == SMB2_DIALECT_REVISION_202) { + break; + } + } + if (dialect != SMB2_DIALECT_REVISION_202) { + DEBUG(0,("Got unexpected SMB2 dialect %u\n", dialect)); return NT_STATUS_NOT_SUPPORTED; } @@ -128,7 +135,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 req->smb_conn->smb2_signing_required = true; break; } - io->out.dialect_revision = SMB2_DIALECT_REVISION; + io->out.dialect_revision = dialect; io->out.capabilities = 0; io->out.max_transact_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, "smb2", "max transaction size", 0x10000); @@ -281,7 +288,7 @@ void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req) SSVAL(req->in.body, 0x02, 1); memset(req->in.body+0x04, 0, 32); - SSVAL(req->in.body, 0x24, 0); + SSVAL(req->in.body, 0x24, SMB2_DIALECT_REVISION_202); smb2srv_negprot_recv(req); return; |