diff options
author | Gerald Carter <jerry@samba.org> | 2007-05-21 21:17:21 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2007-05-21 21:17:21 +0000 |
commit | 34059e63c8a644b10cf9a59cca5e67a45053d16e (patch) | |
tree | b0751d47f93023938656df3c6173618dfef4f1e5 /source | |
parent | c3f0e56c057f6be60bd3721485f013ed63defa6a (diff) | |
download | samba-34059e63c8a644b10cf9a59cca5e67a45053d16e.tar.gz samba-34059e63c8a644b10cf9a59cca5e67a45053d16e.tar.xz samba-34059e63c8a644b10cf9a59cca5e67a45053d16e.zip |
r23052: sync with SAMBA_3_0_25 and start updating release notes
Diffstat (limited to 'source')
32 files changed, 1430 insertions, 193 deletions
diff --git a/source/Makefile.in b/source/Makefile.in index 02396b56437..0da9a8bbc93 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -1349,11 +1349,16 @@ bin/rid.@SHLIBEXT@: proto_exists nsswitch/idmap_rid.o @$(SHLD) $(LDSHFLAGS) -o $@ nsswitch/idmap_rid.o \ @SONAMEFLAG@`basename $@` -bin/ad.@SHLIBEXT@: nsswitch/idmap_ad.o +bin/ad.@SHLIBEXT@: proto_exists nsswitch/idmap_ad.o @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ nsswitch/idmap_ad.o \ @SONAMEFLAG@`basename $@` +bin/ldap.@SHLIBEXT@: proto_exists nsswitch/idmap_ldap.o + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ nsswitch/idmap_ldap.o \ + @SONAMEFLAG@`basename $@` + bin/weird.@SHLIBEXT@: proto_exists $(DEVEL_HELP_WEIRD_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ) \ @@ -1500,7 +1505,7 @@ bin/gpfs.@SHLIBEXT@: $(VFS_GPFS_OBJ) bin/notify_fam.@SHLIBEXT@: $(VFS_NOTIFY_FAM_OBJ) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_NOTIFY_FAM_OBJ) \ - @SONAMEFLAG@`basename $@` + @SONAMEFLAG@`basename $@` @SMB_FAM_LIBS@ bin/readahead.@SHLIBEXT@: $(VFS_READAHEAD_OBJ) @echo "Building plugin $@" diff --git a/source/VERSION b/source/VERSION index 301986c5f1e..824f9d54a97 100644 --- a/source/VERSION +++ b/source/VERSION @@ -36,7 +36,7 @@ SAMBA_VERSION_RELEASE=25 # e.g. SAMBA_VERSION_REVISION=a # # -> "2.2.8a" # ######################################################## -SAMBA_VERSION_REVISION= +SAMBA_VERSION_REVISION=a ######################################################## # For 'pre' releases the version will be # diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c index c7243e8468b..3e29c246491 100644 --- a/source/auth/auth_server.c +++ b/source/auth/auth_server.c @@ -230,17 +230,6 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; BOOL locally_made_cli = False; - /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. - */ - - if(is_myname(user_info->domain)) { - DEBUG(3,("check_smbserver_security: Requested domain was for this machine.\n")); - return nt_status; - } - cli = (struct cli_state *)my_private_data; if (cli) { diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index 009d2a6e73f..2e48a42aafe 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -621,6 +621,7 @@ static int parse_options(char ** optionsp, int * filesys_flags) nocopy: data = next_keyword; } + free(*optionsp); *optionsp = out; return 0; } @@ -882,8 +883,8 @@ int main(int argc, char ** argv) char * ipaddr = NULL; char * uuid = NULL; char * mountpoint = NULL; - char * options; - char * resolved_path; + char * options = NULL; + char * resolved_path = NULL; char * temp; int rc; int rsize = 0; @@ -1079,12 +1080,15 @@ int main(int argc, char ** argv) get_password_from_file(0, getenv("PASSWD_FILE")); } - if (orgoptions && parse_options(&orgoptions, &flags)) - return -1; + if (orgoptions && parse_options(&orgoptions, &flags)) { + rc = -1; + goto mount_exit; + } ipaddr = parse_server(&share_name); if((ipaddr == NULL) && (got_ip == 0)) { printf("No ip address specified and hostname not found\n"); - return -1; + rc = -1; + goto mount_exit; } /* BB save off path and pop after mount returns? */ @@ -1098,17 +1102,20 @@ int main(int argc, char ** argv) } if(chdir(mountpoint)) { printf("mount error: can not change directory into mount target %s\n",mountpoint); - return -1; + rc = -1; + goto mount_exit; } if(stat (".", &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); - return -1; + rc = -1; + goto mount_exit; } if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); - return -1; + rc = -1; + goto mount_exit; } if((getuid() != 0) && (geteuid() == 0)) { @@ -1154,6 +1161,8 @@ mount_retry: optlen += strlen(ipaddr) + 4; if(mountpassword) optlen += strlen(mountpassword) + 6; + if(options) + free(options); options = (char *)malloc(optlen + 10 + 64 /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); if(options == NULL) { @@ -1236,14 +1245,11 @@ mount_retry: } } default: - printf("mount error %d = %s\n",errno,strerror(errno)); } printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n"); - if(mountpassword) { - memset(mountpassword,0,64); - } - return -1; + rc = -1; + goto mount_exit; } else { pmntfile = setmntent(MOUNTED, "a+"); if(pmntfile) { @@ -1273,7 +1279,7 @@ mount_retry: strcat(mountent.mnt_opts,",user="); strcat(mountent.mnt_opts,mount_user); } - free(mount_user); + /* free(mount_user); do not free static mem */ } } mountent.mnt_freq = 0; @@ -1286,6 +1292,8 @@ mount_retry: printf("could not update mount table\n"); } } + rc = 0; +mount_exit: if(mountpassword) { int len = strlen(mountpassword); memset(mountpassword,0,len); @@ -1308,6 +1316,6 @@ mount_retry: if(free_share_name) { free(share_name); } - return 0; + return rc; } diff --git a/source/configure.in b/source/configure.in index fd728289d7b..f16766e0510 100644 --- a/source/configure.in +++ b/source/configure.in @@ -1936,6 +1936,14 @@ if test x"$samba_cv_compiler_supports_ll" = x"yes"; then fi +AC_CACHE_CHECK([for 64 bit time_t],samba_cv_SIZEOF_TIME_T,[ +AC_TRY_RUN([#include <time.h> +main() { exit((sizeof(time_t) == 8) ? 0 : 1); }], +samba_cv_SIZEOF_TIME_T=yes,samba_cv_SIZEOF_TIME_T=no,samba_cv_SIZEOF_TIME_T=cross)]) +if test x"$samba_cv_SIZEOF_TIME_T" = x"yes"; then + AC_DEFINE(SIZEOF_TIME_T,8,[The size of the 'time_t' type]) +fi + AC_CACHE_CHECK([for 64 bit off_t],samba_cv_SIZEOF_OFF_T,[ AC_TRY_RUN([#include <stdio.h> #include <sys/stat.h> @@ -2107,13 +2115,13 @@ if test x"$samba_cv_HAVE_FUNCTION_MACRO" = x"yes"; then fi AC_CACHE_CHECK([if gettimeofday takes tz argument],samba_cv_HAVE_GETTIMEOFDAY_TZ,[ -AC_TRY_RUN([ +AC_TRY_LINK([ #include <sys/time.h> -#include <unistd.h> -main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}], - samba_cv_HAVE_GETTIMEOFDAY_TZ=yes,samba_cv_HAVE_GETTIMEOFDAY_TZ=no,samba_cv_HAVE_GETTIMEOFDAY_TZ=cross)]) +#include <unistd.h>], [struct timeval tv; return gettimeofday(&tv, NULL);], + samba_cv_HAVE_GETTIMEOFDAY_TZ=yes, + samba_cv_HAVE_GETTIMEOFDAY_TZ=no)]) if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then - AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) + AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday takes a tz argument]) fi if test x"$samba_cv_WITH_PROFILE" = x"yes"; then @@ -2538,13 +2546,13 @@ if test x$enable_fam != xno; then # On IRIX, libfam requires libC, but other FAM implementations # might not need it. AC_CHECK_LIB(fam, FAMOpen2, - [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam"], + [samba_cv_HAVE_LIBFAM=yes; SMB_FAM_LIBS="-lfam"], [samba_cv_HAVE_LIBFAM=no]) if test x"$samba_cv_HAVE_LIBFAM" = x"no" ; then samba_fam_xtra=-lC AC_CHECK_LIB_EXT(fam, samba_fam_xtra, FAMOpen2, - [samba_cv_HAVE_LIBFAM=yes; samba_fam_libs="-lfam -lC"], + [samba_cv_HAVE_LIBFAM=yes; SMB_FAM_LIBS="-lfam -lC"], [samba_cv_HAVE_LIBFAM=no]) unset samba_fam_xtra fi @@ -2564,6 +2572,8 @@ if test x$enable_fam != xno; then fi fi +AC_SUBST(SMB_FAM_LIBS) + ################################################# # Check for DMAPI interfaces in libdm/libjfsdm/libxsdm @@ -5140,6 +5150,7 @@ AC_ARG_WITH(acl-support, AC_MSG_RESULT(Using FreeBSD posix ACLs) AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether FreeBSD POSIX ACLs are available]) AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) + default_static_modules="$default_static_modules vfs_posixacl" ;; *linux*) AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"]) @@ -6203,7 +6214,7 @@ AC_SUBST(builddir) # Stuff the smbd-only libraries at the end of the smbd link # path (if we have them). -SMBD_LIBS="$samba_fam_libs $samba_dmapi_libs" +SMBD_LIBS="$samba_dmapi_libs" AC_SUBST(SMBD_LIBS) AC_OUTPUT(include/stamp-h Makefile script/findsmb smbadduser script/gen-8bit-gap.sh script/installbin.sh script/uninstallbin.sh) diff --git a/source/include/ads.h b/source/include/ads.h index 29df0d2f353..40942d339f8 100644 --- a/source/include/ads.h +++ b/source/include/ads.h @@ -321,4 +321,4 @@ typedef struct { int val; int critical; } ads_control; -#endif +#endif /* _INCLUDE_ADS_H_ */ diff --git a/source/include/ads_cldap.h b/source/include/ads_cldap.h index fd227c895db..77ab19a5f2f 100644 --- a/source/include/ads_cldap.h +++ b/source/include/ads_cldap.h @@ -58,4 +58,4 @@ struct cldap_netlogon_reply { #define ADS_GOOD_TIMESERV 0x00000200 /* DC has hardware clock (and running time) */ #define ADS_NDNC 0x00000400 /* DomainName is non-domain NC serviced by LDAP server */ -#endif /* _INCLUDE_CLDAP_H_ */ +#endif /* _INCLUDE_ADS_CLDAP_H_ */ diff --git a/source/lib/replace/dlfcn.m4 b/source/lib/replace/dlfcn.m4 index 2d5b2c5141a..d42409ac630 100644 --- a/source/lib/replace/dlfcn.m4 +++ b/source/lib/replace/dlfcn.m4 @@ -2,17 +2,18 @@ dnl dummies provided by dlfcn.c if not available save_LIBS="$LIBS" LIBS="" +libreplace_cv_dlfcn=no AC_SEARCH_LIBS(dlopen, dl) -if test "$ac_cv_search_dlopen" != no; then +if test x"${ac_cv_search_dlopen}" = x"no"; then + libreplace_cv_dlfcn=yes +else AC_CHECK_HEADERS(dlfcn.h) - - libreplace_cv_dlfcn=no AC_CHECK_FUNCS([dlopen dlsym dlerror dlclose],[],[libreplace_cv_dlfcn=yes]) +fi - if test x"${libreplace_cv_dlfcn}" = x"yes";then - LIBREPLACEOBJ="${LIBREPLACEOBJ} dlfcn.o" - fi +if test x"${libreplace_cv_dlfcn}" = x"yes";then + LIBREPLACEOBJ="${LIBREPLACEOBJ} dlfcn.o" fi LIBDL="$LIBS" diff --git a/source/lib/time.c b/source/lib/time.c index e98f8232abc..ee44f5eb134 100644 --- a/source/lib/time.c +++ b/source/lib/time.c @@ -95,7 +95,13 @@ void unix_to_nt_time(NTTIME *nt, time_t t) if (t == (time_t)-1) { *nt = (NTTIME)-1LL; return; - } + } + + if (t == TIME_T_MAX) { + *nt = 0x7fffffffffffffffLL; + return; + } + if (t == 0) { *nt = 0; return; @@ -301,7 +307,9 @@ char *http_timestring(time_t t) static fstring buf; struct tm *tm = localtime(&t); - if (!tm) { + if (t == TIME_T_MAX) { + slprintf(buf,sizeof(buf)-1,"never"); + } else if (!tm) { slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t); } else { #ifndef HAVE_STRFTIME @@ -554,6 +562,37 @@ NTTIME timeval_to_nttime(const struct timeval *tv) ((TIME_FIXUP_CONSTANT_INT + (uint64_t)tv->tv_sec) * 1000000)); } +/************************************************************** + Handle conversions between time_t and uint32, taking care to + preserve the "special" values. +**************************************************************/ + +uint32 convert_time_t_to_uint32(time_t t) +{ +#if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8)) + /* time_t is 64-bit. */ + if (t == 0x8000000000000000LL) { + return 0x80000000; + } else if (t == 0x7FFFFFFFFFFFFFFFLL) { + return 0x7FFFFFFF; + } +#endif + return (uint32)t; +} + +time_t convert_uint32_to_time_t(uint32 u) +{ +#if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8)) + /* time_t is 64-bit. */ + if (u == 0x80000000) { + return (time_t)0x8000000000000000LL; + } else if (u == 0x7FFFFFFF) { + return (time_t)0x7FFFFFFFFFFFFFFFLL; + } +#endif + return (time_t)u; +} + /******************************************************************* Yield the difference between *A and *B, in seconds, ignoring leap seconds. ********************************************************************/ diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c index e305409b87c..e04a6385a07 100644 --- a/source/libsmb/libsmbclient.c +++ b/source/libsmb/libsmbclient.c @@ -500,7 +500,7 @@ static int smbc_check_server(SMBCCTX * context, SMBCSRV * server) { - size_t size; + socklen_t size; struct sockaddr addr; /* @@ -4556,7 +4556,7 @@ cacl_get(SMBCCTX *context, return -1; } n = strlen(p); - } else { + } else if (sidstr[0] != '\0') { n = snprintf(buf, bufsize, ",OWNER:%s", sidstr); } @@ -4601,7 +4601,7 @@ cacl_get(SMBCCTX *context, return -1; } n = strlen(p); - } else { + } else if (sidstr[0] != '\0') { n = snprintf(buf, bufsize, ",GROUP:%s", sidstr); } @@ -4709,7 +4709,7 @@ cacl_get(SMBCCTX *context, ace->access_mask); } } - if (n > bufsize) { + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; } @@ -5327,7 +5327,9 @@ smbc_setxattr_ctx(SMBCCTX *context, ipc_srv = smbc_attr_server(context, server, share, workgroup, user, password, &pol); - srv->no_nt_session = True; + if (! ipc_srv) { + srv->no_nt_session = True; + } } else { ipc_srv = NULL; } @@ -5752,7 +5754,9 @@ smbc_removexattr_ctx(SMBCCTX *context, ipc_srv = smbc_attr_server(context, server, share, workgroup, user, password, &pol); - srv->no_nt_session = True; + if (! ipc_srv) { + srv->no_nt_session = True; + } } else { ipc_srv = NULL; } diff --git a/source/locking/brlock.c b/source/locking/brlock.c index 5da76a1782d..e2afa968061 100644 --- a/source/locking/brlock.c +++ b/source/locking/brlock.c @@ -313,7 +313,7 @@ static int lock_compare(const struct lock_struct *lck1, ****************************************************************************/ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, - const struct lock_struct *plock, BOOL blocking_lock) + struct lock_struct *plock, BOOL blocking_lock) { unsigned int i; files_struct *fsp = br_lck->fsp; @@ -322,6 +322,8 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, for (i=0; i < br_lck->num_locks; i++) { /* Do any Windows or POSIX locks conflict ? */ if (brl_conflict(&locks[i], plock)) { + /* Remember who blocked us. */ + plock->context.smbpid = locks[i].context.smbpid; return brl_lock_failed(fsp,plock,blocking_lock); } #if ZERO_ZERO @@ -346,6 +348,10 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck, locks, br_lck->num_locks, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { return NT_STATUS_FILE_LOCK_CONFLICT; } else { @@ -585,7 +591,7 @@ OR ****************************************************************************/ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, - const struct lock_struct *plock) + struct lock_struct *plock) { unsigned int i, count; struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data; @@ -629,6 +635,8 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, if (brl_conflict(curr_lock, plock)) { /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } /* Just copy the Windows lock into the new array. */ @@ -640,6 +648,8 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, /* Can't block ourselves with POSIX locks. */ /* No games with error messages. */ SAFE_FREE(tp); + /* Remember who blocked us. */ + plock->context.smbpid = curr_lock->context.smbpid; return NT_STATUS_FILE_LOCK_CONFLICT; } @@ -669,6 +679,10 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck, plock->size, plock->lock_type, &errno_ret)) { + + /* We don't know who blocked us. */ + plock->context.smbpid = 0xFFFFFFFF; + if (errno_ret == EACCES || errno_ret == EAGAIN) { SAFE_FREE(tp); return NT_STATUS_FILE_LOCK_CONFLICT; @@ -729,7 +743,8 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, br_off size, enum brl_type lock_type, enum brl_flavour lock_flav, - BOOL blocking_lock) + BOOL blocking_lock, + uint32 *psmbpid) { NTSTATUS ret; struct lock_struct lock; @@ -760,6 +775,10 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck, qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare); #endif + /* If we're returning an error, return who blocked us. */ + if (!NT_STATUS_IS_OK(ret) && psmbpid) { + *psmbpid = lock.context.smbpid; + } return ret; } diff --git a/source/locking/locking.c b/source/locking/locking.c index 2181fca4085..f304037bcce 100644 --- a/source/locking/locking.c +++ b/source/locking/locking.c @@ -187,7 +187,8 @@ struct byte_range_lock *do_lock(files_struct *fsp, enum brl_type lock_type, enum brl_flavour lock_flav, BOOL blocking_lock, - NTSTATUS *perr) + NTSTATUS *perr, + uint32 *plock_pid) { struct byte_range_lock *br_lck = NULL; @@ -220,7 +221,8 @@ struct byte_range_lock *do_lock(files_struct *fsp, count, lock_type, lock_flav, - blocking_lock); + blocking_lock, + plock_pid); /* blocking ie. pending, locks also count here, * as this is an efficiency counter to avoid checking diff --git a/source/modules/vfs_hpuxacl.c b/source/modules/vfs_hpuxacl.c index aeb078c32dc..3885758523b 100644 --- a/source/modules/vfs_hpuxacl.c +++ b/source/modules/vfs_hpuxacl.c @@ -1,101 +1,1182 @@ /* - Unix SMB/Netbios implementation. - VFS module to get and set hpux acls - Copyright (C) Michael Adam 2006 + * Unix SMB/Netbios implementation. + * VFS module to get and set HP-UX ACLs + * Copyright (C) Michael Adam 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ - 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 2 of the License, or - (at your option) any later version. +/* + * This module supports JFS (POSIX) ACLs on VxFS (Veritas * Filesystem). + * These are available on HP-UX 11.00 if JFS 3.3 is installed. + * On HP-UX 11i (11.11 and above) these ACLs are supported out of + * the box. + * + * There is another form of ACLs on HFS. These ACLs have a + * completely different API and their own set of userland tools. + * Since HFS seems to be considered deprecated, HFS acls + * are not supported. (They could be supported through a separate + * vfs-module if there is demand.) + */ - 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. +/* ================================================================= + * NOTE: + * + * The original hpux-acl code in lib/sysacls.c was based upon the + * solaris acl code in the same file. Now for the new modularized + * acl implementation, I have taken the code from vfs_solarisacls.c + * and did similar adaptations as were done before, essentially + * reusing the original internal aclsort functions. + * The check for the presence of the acl() call has been adopted, and + * a check for the presence of the aclsort() call has been added. + * + * Michael Adam <obnox@samba.org> + * + * ================================================================= */ - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ #include "includes.h" -/* prototypes for private functions first - for clarity */ +/* + * including standard header <sys/aclv.h> + * + * included here as a quick hack for the special HP-UX-situation: + * + * The problem is that, on HP-UX, jfs/posix acls are + * defined in <sys/aclv.h>, while the deprecated hfs acls + * are defined inside <sys/acl.h>. + * + */ +/* GROUP is defined somewhere else so undef it here... */ +#undef GROUP +#include <sys/aclv.h> +/* dl.h: needed to check for acl call via shl_findsym */ +#include <dl.h> + +typedef struct acl HPUX_ACE_T; +typedef struct acl *HPUX_ACL_T; +typedef int HPUX_ACL_TAG_T; /* the type of an ACL entry */ +typedef ushort HPUX_PERM_T; + +/* Structure to capture the count for each type of ACE. + * (for hpux_internal_aclsort */ +struct hpux_acl_types { + int n_user; + int n_def_user; + int n_user_obj; + int n_def_user_obj; + + int n_group; + int n_def_group; + int n_group_obj; + int n_def_group_obj; + + int n_other; + int n_other_obj; + int n_def_other_obj; + + int n_class_obj; + int n_def_class_obj; + + int n_illegal_obj; +}; + +/* for convenience: check if hpux acl entry is a default entry? */ +#define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT) +#define _IS_OF_TYPE(ace, type) ( \ + (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \ + || \ + (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \ +) + + +/* prototypes for private functions */ + +static HPUX_ACL_T hpux_acl_init(int count); +static BOOL smb_acl_to_hpux_acl(SMB_ACL_T smb_acl, + HPUX_ACL_T *solariacl, int *count, + SMB_ACL_TYPE_T type); +static SMB_ACL_T hpux_acl_to_smb_acl(HPUX_ACL_T hpuxacl, int count, + SMB_ACL_TYPE_T type); +static HPUX_ACL_TAG_T smb_tag_to_hpux_tag(SMB_ACL_TAG_T smb_tag); +static SMB_ACL_TAG_T hpux_tag_to_smb_tag(HPUX_ACL_TAG_T hpux_tag); +static BOOL hpux_add_to_acl(HPUX_ACL_T *hpux_acl, int *count, + HPUX_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type); +static BOOL hpux_acl_get_file(const char *name, HPUX_ACL_T *hpuxacl, + int *count); +static SMB_ACL_PERM_T hpux_perm_to_smb_perm(const HPUX_PERM_T perm); +static HPUX_PERM_T smb_perm_to_hpux_perm(const SMB_ACL_PERM_T perm); +#if 0 +static BOOL hpux_acl_check(HPUX_ACL_T hpux_acl, int count); +#endif +/* aclsort (internal) and helpers: */ +static BOOL hpux_acl_sort(HPUX_ACL_T acl, int count); +static int hpux_internal_aclsort(int acl_count, int calclass, HPUX_ACL_T aclp); +static void hpux_count_obj(int acl_count, HPUX_ACL_T aclp, + struct hpux_acl_types *acl_type_count); +static void hpux_swap_acl_entries(HPUX_ACE_T *aclp0, HPUX_ACE_T *aclp1); +static BOOL hpux_prohibited_duplicate_type(int acl_type); + +static BOOL hpux_acl_call_present(void); +static BOOL hpux_aclsort_call_present(void); + /* public functions - the api */ SMB_ACL_T hpuxacl_sys_acl_get_file(vfs_handle_struct *handle, - const char *path_p, - SMB_ACL_TYPE_T type) + const char *path_p, + SMB_ACL_TYPE_T type) { - errno = ENOTSUP; - return NULL; + SMB_ACL_T result = NULL; + int count; + HPUX_ACL_T hpux_acl; + + DEBUG(10, ("hpuxacl_sys_acl_get_file called for file '%s'.\n", + path_p)); + + if(hpux_acl_call_present() == False) { + /* Looks like we don't have the acl() system call on HPUX. + * May be the system doesn't have the latest version of JFS. + */ + goto done; + } + + if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { + DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type)); + errno = EINVAL; + goto done; + } + + DEBUGADD(10, ("getting %s acl\n", + ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default"))); + + if (!hpux_acl_get_file(path_p, &hpux_acl, &count)) { + goto done; + } + result = hpux_acl_to_smb_acl(hpux_acl, count, type); + if (result == NULL) { + DEBUG(10, ("conversion hpux_acl -> smb_acl failed (%s).\n", + strerror(errno))); + } + + done: + DEBUG(10, ("hpuxacl_sys_acl_get_file %s.\n", + ((result == NULL) ? "failed" : "succeeded" ))); + SAFE_FREE(hpux_acl); + return result; } + +/* + * get the access ACL of a file referred to by a fd + */ SMB_ACL_T hpuxacl_sys_acl_get_fd(vfs_handle_struct *handle, - files_struct *fsp, - int fd) + files_struct *fsp, + int fd) { - errno = ENOTSUP; - return NULL; + /* + * HPUX doesn't have the facl call. Fake it using the path.... JRA. + */ + /* For all I see, the info should already be in the fsp + * parameter, but get it again to be safe --- necessary? */ + files_struct *file_struct_p = file_find_fd(fd); + if (file_struct_p == NULL) { + errno = EBADF; + return NULL; + } + /* + * We know we're in the same conn context. So we + * can use the relative path. + */ + DEBUG(10, ("redirecting call of hpuxacl_sys_acl_get_fd to " + "hpuxacl_sys_acl_get_file (no facl syscall on HPUX).\n")); + + return hpuxacl_sys_acl_get_file(handle, file_struct_p->fsp_name, + SMB_ACL_TYPE_ACCESS); } + int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, - const char *name, - SMB_ACL_TYPE_T type, - SMB_ACL_T theacl) + const char *name, + SMB_ACL_TYPE_T type, + SMB_ACL_T theacl) { - errno = ENOTSUP; - return -1; + int ret = -1; + SMB_STRUCT_STAT s; + HPUX_ACL_T hpux_acl; + int count; + + DEBUG(10, ("hpuxacl_sys_acl_set_file called for file '%s'\n", + name)); + + + if(hpux_acl_call_present() == False) { + /* Looks like we don't have the acl() system call on HPUX. + * May be the system doesn't have the latest version of JFS. + */ + goto done; + } + + if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) { + errno = EINVAL; + DEBUG(10, ("invalid smb acl type given (%d).\n", type)); + goto done; + } + DEBUGADD(10, ("setting %s acl\n", + ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default"))); + + if(!smb_acl_to_hpux_acl(theacl, &hpux_acl, &count, type)) { + DEBUG(10, ("conversion smb_acl -> hpux_acl failed (%s).\n", + strerror(errno))); + goto done; + } + + /* + * if the file is a directory, there is extra work to do: + * since the hpux acl call stores both the access acl and + * the default acl as provided, we have to get the acl part + * that has _not_ been specified in "type" from the file first + * and concatenate it with the acl provided. + */ + if (SMB_VFS_STAT(handle->conn, name, &s) != 0) { + DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); + goto done; + } + if (S_ISDIR(s.st_mode)) { + HPUX_ACL_T other_acl; + int other_count; + SMB_ACL_TYPE_T other_type; + + other_type = (type == SMB_ACL_TYPE_ACCESS) + ? SMB_ACL_TYPE_DEFAULT + : SMB_ACL_TYPE_ACCESS; + DEBUGADD(10, ("getting acl from filesystem\n")); + if (!hpux_acl_get_file(name, &other_acl, &other_count)) { + DEBUG(10, ("error getting acl from directory\n")); + goto done; + } + DEBUG(10, ("adding %s part of fs acl to given acl\n", + ((other_type == SMB_ACL_TYPE_ACCESS) + ? "access" + : "default"))); + if (!hpux_add_to_acl(&hpux_acl, &count, other_acl, + other_count, other_type)) + { + DEBUG(10, ("error adding other acl.\n")); + SAFE_FREE(other_acl); + goto done; + } + SAFE_FREE(other_acl); + } + else if (type != SMB_ACL_TYPE_ACCESS) { + errno = EINVAL; + goto done; + } + + if (!hpux_acl_sort(hpux_acl, count)) { + DEBUG(10, ("resulting acl is not valid!\n")); + goto done; + } + DEBUG(10, ("resulting acl is valid.\n")); + + ret = acl(CONST_DISCARD(char *, name), ACL_SET, count, hpux_acl); + if (ret != 0) { + DEBUG(0, ("ERROR calling acl: %s\n", strerror(errno))); + } + + done: + DEBUG(10, ("hpuxacl_sys_acl_set_file %s.\n", + ((ret != 0) ? "failed" : "succeeded"))); + SAFE_FREE(hpux_acl); + return ret; } +/* + * set the access ACL on the file referred to by a fd + */ int hpuxacl_sys_acl_set_fd(vfs_handle_struct *handle, - files_struct *fsp, - int fd, SMB_ACL_T theacl) + files_struct *fsp, + int fd, SMB_ACL_T theacl) { - errno = ENOTSUP; - return -1; + /* + * HPUX doesn't have the facl call. Fake it using the path.... JRA. + */ + /* For all I see, the info should already be in the fsp + * parameter, but get it again to be safe --- necessary? */ + files_struct *file_struct_p = file_find_fd(fd); + if (file_struct_p == NULL) { + errno = EBADF; + return -1; + } + /* + * We know we're in the same conn context. So we + * can use the relative path. + */ + DEBUG(10, ("redirecting call of hpuxacl_sys_acl_set_fd to " + "hpuxacl_sys_acl_set_file (no facl syscall on HPUX)\n")); + + return hpuxacl_sys_acl_set_file(handle, file_struct_p->fsp_name, + SMB_ACL_TYPE_ACCESS, theacl); } + +/* + * delete the default ACL of a directory + * + * This is achieved by fetching the access ACL and rewriting it + * directly, via the hpux system call: the ACL_SET call on + * directories writes both the access and the default ACL as provided. + * + * XXX: posix acl_delete_def_file returns an error if + * the file referred to by path is not a directory. + * this function does not complain but the actions + * have no effect on a file other than a directory. + * But sys_acl_delete_default_file is only called in + * smbd/posixacls.c after having checked that the file + * is a directory, anyways. So implementing the extra + * check is considered unnecessary. --- Agreed? XXX + */ int hpuxacl_sys_acl_delete_def_file(vfs_handle_struct *handle, - const char *path) + const char *path) +{ + SMB_ACL_T smb_acl; + int ret = -1; + HPUX_ACL_T hpux_acl; + int count; + + DEBUG(10, ("entering hpuxacl_sys_acl_delete_def_file.\n")); + + smb_acl = hpuxacl_sys_acl_get_file(handle, path, + SMB_ACL_TYPE_ACCESS); + if (smb_acl == NULL) { + DEBUG(10, ("getting file acl failed!\n")); + goto done; + } + if (!smb_acl_to_hpux_acl(smb_acl, &hpux_acl, &count, + SMB_ACL_TYPE_ACCESS)) + { + DEBUG(10, ("conversion smb_acl -> hpux_acl failed.\n")); + goto done; + } + if (!hpux_acl_sort(hpux_acl, count)) { + DEBUG(10, ("resulting acl is not valid!\n")); + goto done; + } + ret = acl(CONST_DISCARD(char *, path), ACL_SET, count, hpux_acl); + if (ret != 0) { + DEBUG(10, ("settinge file acl failed!\n")); + } + + done: + DEBUG(10, ("hpuxacl_sys_acl_delete_def_file %s.\n", + ((ret != 0) ? "failed" : "succeeded" ))); + SAFE_FREE(smb_acl); + return ret; +} + + +/* + * private functions + */ + +static HPUX_ACL_T hpux_acl_init(int count) { - errno = ENOTSUP; - return -1; + HPUX_ACL_T hpux_acl = + (HPUX_ACL_T)SMB_MALLOC(sizeof(HPUX_ACE_T) * count); + if (hpux_acl == NULL) { + errno = ENOMEM; + } + return hpux_acl; } -/* private functions */ +/* + * Convert the SMB acl to the ACCESS or DEFAULT part of a + * hpux ACL, as desired. + */ +static BOOL smb_acl_to_hpux_acl(SMB_ACL_T smb_acl, + HPUX_ACL_T *hpux_acl, int *count, + SMB_ACL_TYPE_T type) +{ + BOOL ret = False; + int i; + int check_which, check_rc; + + DEBUG(10, ("entering smb_acl_to_hpux_acl\n")); + + *hpux_acl = NULL; + *count = 0; + + for (i = 0; i < smb_acl->count; i++) { + const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]); + HPUX_ACE_T hpux_entry; + + ZERO_STRUCT(hpux_entry); + + hpux_entry.a_type = smb_tag_to_hpux_tag(smb_entry->a_type); + if (hpux_entry.a_type == 0) { + DEBUG(10, ("smb_tag to hpux_tag failed\n")); + goto fail; + } + switch(hpux_entry.a_type) { + case USER: + DEBUG(10, ("got tag type USER with uid %d\n", + smb_entry->uid)); + hpux_entry.a_id = (uid_t)smb_entry->uid; + break; + case GROUP: + DEBUG(10, ("got tag type GROUP with gid %d\n", + smb_entry->gid)); + hpux_entry.a_id = (uid_t)smb_entry->gid; + break; + default: + break; + } + if (type == SMB_ACL_TYPE_DEFAULT) { + DEBUG(10, ("adding default bit to hpux ace\n")); + hpux_entry.a_type |= ACL_DEFAULT; + } + + hpux_entry.a_perm = + smb_perm_to_hpux_perm(smb_entry->a_perm); + DEBUG(10, ("assembled the following hpux ace:\n")); + DEBUGADD(10, (" - type: 0x%04x\n", hpux_entry.a_type)); + DEBUGADD(10, (" - id: %d\n", hpux_entry.a_id)); + DEBUGADD(10, (" - perm: o%o\n", hpux_entry.a_perm)); + if (!hpux_add_to_acl(hpux_acl, count, &hpux_entry, + 1, type)) + { + DEBUG(10, ("error adding acl entry\n")); + goto fail; + } + DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i)); + DEBUG(10, ("test, if entry has been copied into acl:\n")); + DEBUGADD(10, (" - type: 0x%04x\n", + (*hpux_acl)[(*count)-1].a_type)); + DEBUGADD(10, (" - id: %d\n", + (*hpux_acl)[(*count)-1].a_id)); + DEBUGADD(10, (" - perm: o%o\n", + (*hpux_acl)[(*count)-1].a_perm)); + } + + ret = True; + goto done; + + fail: + SAFE_FREE(*hpux_acl); + done: + DEBUG(10, ("smb_acl_to_hpux_acl %s\n", + ((ret == True) ? "succeeded" : "failed"))); + return ret; +} + +/* + * convert either the access or the default part of a + * soaris acl to the SMB_ACL format. + */ +static SMB_ACL_T hpux_acl_to_smb_acl(HPUX_ACL_T hpux_acl, int count, + SMB_ACL_TYPE_T type) +{ + SMB_ACL_T result; + int i; + + if ((result = sys_acl_init(0)) == NULL) { + DEBUG(10, ("error allocating memory for SMB_ACL\n")); + goto fail; + } + for (i = 0; i < count; i++) { + SMB_ACL_ENTRY_T smb_entry; + SMB_ACL_PERM_T smb_perm; + + if (!_IS_OF_TYPE(hpux_acl[i], type)) { + continue; + } + result = SMB_REALLOC(result, + sizeof(struct smb_acl_t) + + (sizeof(struct smb_acl_entry) * + (result->count + 1))); + if (result == NULL) { + DEBUG(10, ("error reallocating memory for SMB_ACL\n")); + goto fail; + } + smb_entry = &result->acl[result->count]; + if (sys_acl_set_tag_type(smb_entry, + hpux_tag_to_smb_tag(hpux_acl[i].a_type)) != 0) + { + DEBUG(10, ("invalid tag type given: 0x%04x\n", + hpux_acl[i].a_type)); + goto fail; + } + /* intentionally not checking return code here: */ + sys_acl_set_qualifier(smb_entry, (void *)&hpux_acl[i].a_id); + smb_perm = hpux_perm_to_smb_perm(hpux_acl[i].a_perm); + if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) { + DEBUG(10, ("invalid permset given: %d\n", + hpux_acl[i].a_perm)); + goto fail; + } + result->count += 1; + } + goto done; + + fail: + SAFE_FREE(result); + done: + DEBUG(10, ("hpux_acl_to_smb_acl %s\n", + ((result == NULL) ? "failed" : "succeeded"))); + return result; +} + + + +static HPUX_ACL_TAG_T smb_tag_to_hpux_tag(SMB_ACL_TAG_T smb_tag) +{ + HPUX_ACL_TAG_T hpux_tag = 0; + + DEBUG(10, ("smb_tag_to_hpux_tag\n")); + DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag)); + + switch (smb_tag) { + case SMB_ACL_USER: + hpux_tag = USER; + break; + case SMB_ACL_USER_OBJ: + hpux_tag = USER_OBJ; + break; + case SMB_ACL_GROUP: + hpux_tag = GROUP; + break; + case SMB_ACL_GROUP_OBJ: + hpux_tag = GROUP_OBJ; + break; + case SMB_ACL_OTHER: + hpux_tag = OTHER_OBJ; + break; + case SMB_ACL_MASK: + hpux_tag = CLASS_OBJ; + break; + default: + DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag)); + break; + } + + DEBUGADD(10, (" --> determined hpux tag 0x%04x\n", hpux_tag)); + + return hpux_tag; +} + +static SMB_ACL_TAG_T hpux_tag_to_smb_tag(HPUX_ACL_TAG_T hpux_tag) +{ + SMB_ACL_TAG_T smb_tag = 0; + + DEBUG(10, ("hpux_tag_to_smb_tag:\n")); + DEBUGADD(10, (" --> got hpux tag 0x%04x\n", hpux_tag)); + + hpux_tag &= ~ACL_DEFAULT; + + switch (hpux_tag) { + case USER: + smb_tag = SMB_ACL_USER; + break; + case USER_OBJ: + smb_tag = SMB_ACL_USER_OBJ; + break; + case GROUP: + smb_tag = SMB_ACL_GROUP; + break; + case GROUP_OBJ: + smb_tag = SMB_ACL_GROUP_OBJ; + break; + case OTHER_OBJ: + smb_tag = SMB_ACL_OTHER; + break; + case CLASS_OBJ: + smb_tag = SMB_ACL_MASK; + break; + default: + DEBUGADD(10, (" !!! unknown hpux tag type: 0x%04x\n", + hpux_tag)); + break; + } + + DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag)); + + return smb_tag; +} + + +/* + * The permission bits used in the following two permission conversion + * functions are same, but the functions make us independent of the concrete + * permission data types. + */ +static SMB_ACL_PERM_T hpux_perm_to_smb_perm(const HPUX_PERM_T perm) +{ + SMB_ACL_PERM_T smb_perm = 0; + smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0); + smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0); + smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return smb_perm; +} + + +static HPUX_PERM_T smb_perm_to_hpux_perm(const SMB_ACL_PERM_T perm) +{ + HPUX_PERM_T hpux_perm = 0; + hpux_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0); + hpux_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0); + hpux_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); + return hpux_perm; +} + + +static BOOL hpux_acl_get_file(const char *name, HPUX_ACL_T *hpux_acl, + int *count) +{ + BOOL result = False; + static HPUX_ACE_T dummy_ace; + + DEBUG(10, ("hpux_acl_get_file called for file '%s'\n", name)); + + /* + * The original code tries some INITIAL_ACL_SIZE + * and only did the ACL_CNT call upon failure + * (for performance reasons). + * For the sake of simplicity, I skip this for now. + * + * NOTE: There is a catch here on HP-UX: acl with cmd parameter + * ACL_CNT fails with errno EINVAL when called with a NULL + * pointer as last argument. So we need to use a dummy acl + * struct here (we make it static so it does not need to be + * instantiated or malloced each time this function is + * called). Btw: the count parameter does not seem to matter... + */ + *count = acl(CONST_DISCARD(char *, name), ACL_CNT, 0, &dummy_ace); + if (*count < 0) { + DEBUG(10, ("acl ACL_CNT failed: %s\n", strerror(errno))); + goto done; + } + *hpux_acl = hpux_acl_init(*count); + if (*hpux_acl == NULL) { + DEBUG(10, ("error allocating memory for hpux acl...\n")); + goto done; + } + *count = acl(CONST_DISCARD(char *, name), ACL_GET, *count, *hpux_acl); + if (*count < 0) { + DEBUG(10, ("acl ACL_GET failed: %s\n", strerror(errno))); + goto done; + } + result = True; + + done: + DEBUG(10, ("hpux_acl_get_file %s.\n", + ((result == True) ? "succeeded" : "failed" ))); + return result; +} + + + + +/* + * Add entries to a hpux ACL. + * + * Entries are directly added to the hpuxacl parameter. + * if memory allocation fails, this may result in hpuxacl + * being NULL. if the resulting acl is to be checked and is + * not valid, it is kept in hpuxacl but False is returned. + * + * The type of ACEs (access/default) to be added to the ACL can + * be selected via the type parameter. + * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS + * is defined as "0", this means that one can only add either + * access or default ACEs from the given ACL, not both at the same + * time. If it should become necessary to add all of an ACL, one + * would have to replace this parameter by another type. + */ +static BOOL hpux_add_to_acl(HPUX_ACL_T *hpux_acl, int *count, + HPUX_ACL_T add_acl, int add_count, + SMB_ACL_TYPE_T type) +{ + int i; + + if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) + { + DEBUG(10, ("invalid acl type given: %d\n", type)); + errno = EINVAL; + return False; + } + for (i = 0; i < add_count; i++) { + if (!_IS_OF_TYPE(add_acl[i], type)) { + continue; + } + ADD_TO_ARRAY(NULL, HPUX_ACE_T, add_acl[i], + hpux_acl, count); + if (hpux_acl == NULL) { + DEBUG(10, ("error enlarging acl.\n")); + errno = ENOMEM; + return False; + } + } + return True; +} + + +/* + * sort the ACL and check it for validity + * + * [original comment from lib/sysacls.c:] + * + * if it's a minimal ACL with only 4 entries then we + * need to recalculate the mask permissions to make + * sure that they are the same as the GROUP_OBJ + * permissions as required by the UnixWare acl() system call. + * + * (note: since POSIX allows minimal ACLs which only contain + * 3 entries - ie there is no mask entry - we should, in theory, + * check for this and add a mask entry if necessary - however + * we "know" that the caller of this interface always specifies + * a mask, so in practice "this never happens" (tm) - if it *does* + * happen aclsort() will fail and return an error and someone will + * have to fix it...) + */ +static BOOL hpux_acl_sort(HPUX_ACL_T hpux_acl, int count) +{ + int fixmask = (count <= 4); + + if (hpux_internal_aclsort(count, fixmask, hpux_acl) != 0) { + errno = EINVAL; + return False; + } + return True; +} + + +/* + * Helpers for hpux_internal_aclsort: + * - hpux_count_obj + * - hpux_swap_acl_entries + * - hpux_prohibited_duplicate_type + * - hpux_get_needed_class_perm + */ + +/* hpux_count_obj: + * Counts the different number of objects in a given array of ACL + * structures. + * Inputs: + * + * acl_count - Count of ACLs in the array of ACL strucutres. + * aclp - Array of ACL structures. + * acl_type_count - Pointer to acl_types structure. Should already be + * allocated. + * Output: + * + * acl_type_count - This structure is filled up with counts of various + * acl types. + */ + +static void hpux_count_obj(int acl_count, HPUX_ACL_T aclp, struct hpux_acl_types *acl_type_count) +{ + int i; + + memset(acl_type_count, 0, sizeof(struct hpux_acl_types)); + + for(i=0;i<acl_count;i++) { + switch(aclp[i].a_type) { + case USER: + acl_type_count->n_user++; + break; + case USER_OBJ: + acl_type_count->n_user_obj++; + break; + case DEF_USER_OBJ: + acl_type_count->n_def_user_obj++; + break; + case GROUP: + acl_type_count->n_group++; + break; + case GROUP_OBJ: + acl_type_count->n_group_obj++; + break; + case DEF_GROUP_OBJ: + acl_type_count->n_def_group_obj++; + break; + case OTHER_OBJ: + acl_type_count->n_other_obj++; + break; + case DEF_OTHER_OBJ: + acl_type_count->n_def_other_obj++; + break; + case CLASS_OBJ: + acl_type_count->n_class_obj++; + break; + case DEF_CLASS_OBJ: + acl_type_count->n_def_class_obj++; + break; + case DEF_USER: + acl_type_count->n_def_user++; + break; + case DEF_GROUP: + acl_type_count->n_def_group++; + break; + default: + acl_type_count->n_illegal_obj++; + break; + } + } +} + +/* hpux_swap_acl_entries: Swaps two ACL entries. + * + * Inputs: aclp0, aclp1 - ACL entries to be swapped. + */ + +static void hpux_swap_acl_entries(HPUX_ACE_T *aclp0, HPUX_ACE_T *aclp1) +{ + HPUX_ACE_T temp_acl; + + temp_acl.a_type = aclp0->a_type; + temp_acl.a_id = aclp0->a_id; + temp_acl.a_perm = aclp0->a_perm; + + aclp0->a_type = aclp1->a_type; + aclp0->a_id = aclp1->a_id; + aclp0->a_perm = aclp1->a_perm; + + aclp1->a_type = temp_acl.a_type; + aclp1->a_id = temp_acl.a_id; + aclp1->a_perm = temp_acl.a_perm; +} + +/* hpux_prohibited_duplicate_type + * Identifies if given ACL type can have duplicate entries or + * not. + * + * Inputs: acl_type - ACL Type. + * + * Outputs: + * + * Return.. + * + * True - If the ACL type matches any of the prohibited types. + * False - If the ACL type doesn't match any of the prohibited types. + */ + +static BOOL hpux_prohibited_duplicate_type(int acl_type) +{ + switch(acl_type) { + case USER: + case GROUP: + case DEF_USER: + case DEF_GROUP: + return True; + default: + return False; + } +} + +/* hpux_get_needed_class_perm + * Returns the permissions of a ACL structure only if the ACL + * type matches one of the pre-determined types for computing + * CLASS_OBJ permissions. + * + * Inputs: aclp - Pointer to ACL structure. + */ + +static int hpux_get_needed_class_perm(struct acl *aclp) +{ + switch(aclp->a_type) { + case USER: + case GROUP_OBJ: + case GROUP: + case DEF_USER_OBJ: + case DEF_USER: + case DEF_GROUP_OBJ: + case DEF_GROUP: + case DEF_CLASS_OBJ: + case DEF_OTHER_OBJ: + return aclp->a_perm; + default: + return 0; + } +} + +/* hpux_internal_aclsort: aclsort for HPUX. + * + * -> The aclsort() system call is availabe on the latest HPUX General + * -> Patch Bundles. So for HPUX, we developed our version of aclsort + * -> function. Because, we don't want to update to a new + * -> HPUX GR bundle just for aclsort() call. + * + * aclsort sorts the array of ACL structures as per the description in + * aclsort man page. Refer to aclsort man page for more details + * + * Inputs: + * + * acl_count - Count of ACLs in the array of ACL structures. + * calclass - If this is not zero, then we compute the CLASS_OBJ + * permissions. + * aclp - Array of ACL structures. + * + * Outputs: + * + * aclp - Sorted array of ACL structures. + * + * Outputs: + * + * Returns 0 for success -1 for failure. Prints a message to the Samba + * debug log in case of failure. + */ + +static int hpux_internal_aclsort(int acl_count, int calclass, HPUX_ACL_T aclp) +{ + struct hpux_acl_types acl_obj_count; + int n_class_obj_perm = 0; + int i, j; + + DEBUG(10,("Entering hpux_internal_aclsort. (calclass = %d)\n", calclass)); + + if (hpux_aclsort_call_present()) { + DEBUG(10, ("calling hpux aclsort\n")); + return aclsort(acl_count, calclass, aclp); + } + + DEBUG(10, ("using internal aclsort\n")); + + if(!acl_count) { + DEBUG(10,("Zero acl count passed. Returning Success\n")); + return 0; + } + + if(aclp == NULL) { + DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n")); + return -1; + } + + /* Count different types of ACLs in the ACLs array */ + + hpux_count_obj(acl_count, aclp, &acl_obj_count); + + /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, + * CLASS_OBJ and OTHER_OBJ + */ + + if ( (acl_obj_count.n_user_obj != 1) || + (acl_obj_count.n_group_obj != 1) || + (acl_obj_count.n_class_obj != 1) || + (acl_obj_count.n_other_obj != 1) ) + { + DEBUG(0,("hpux_internal_aclsort: More than one entry or no entries for \ +USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n")); + return -1; + } + + /* If any of the default objects are present, there should be only + * one of them each. + */ + + if ( (acl_obj_count.n_def_user_obj > 1) || + (acl_obj_count.n_def_group_obj > 1) || + (acl_obj_count.n_def_other_obj > 1) || + (acl_obj_count.n_def_class_obj > 1) ) + { + DEBUG(0,("hpux_internal_aclsort: More than one entry for DEF_CLASS_OBJ \ +or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n")); + return -1; + } + + /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl + * structures. + * + * Sorting crieteria - First sort by ACL type. If there are multiple entries of + * same ACL type, sort by ACL id. + * + * I am using the trival kind of sorting method here because, performance isn't + * really effected by the ACLs feature. More over there aren't going to be more + * than 17 entries on HPUX. + */ + + for(i=0; i<acl_count;i++) { + for (j=i+1; j<acl_count; j++) { + if( aclp[i].a_type > aclp[j].a_type ) { + /* ACL entries out of order, swap them */ + hpux_swap_acl_entries((aclp+i), (aclp+j)); + } else if ( aclp[i].a_type == aclp[j].a_type ) { + /* ACL entries of same type, sort by id */ + if(aclp[i].a_id > aclp[j].a_id) { + hpux_swap_acl_entries((aclp+i), (aclp+j)); + } else if (aclp[i].a_id == aclp[j].a_id) { + /* We have a duplicate entry. */ + if(hpux_prohibited_duplicate_type(aclp[i].a_type)) { + DEBUG(0, ("hpux_internal_aclsort: Duplicate entry: Type(hex): %x Id: %d\n", + aclp[i].a_type, aclp[i].a_id)); + return -1; + } + } + } + } + } + + /* set the class obj permissions to the computed one. */ + if(calclass) { + int n_class_obj_index = -1; + + for(i=0;i<acl_count;i++) { + n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i)); + + if(aclp[i].a_type == CLASS_OBJ) + n_class_obj_index = i; + } + aclp[n_class_obj_index].a_perm = n_class_obj_perm; + } + + return 0; +} + + +/* + * hpux_acl_call_present: + * + * This checks if the POSIX ACL system call is defined + * which basically corresponds to whether JFS 3.3 or + * higher is installed. If acl() was called when it + * isn't defined, it causes the process to core dump + * so it is important to check this and avoid acl() + * calls if it isn't there. + */ + +static BOOL hpux_acl_call_present(void) +{ + + shl_t handle = NULL; + void *value; + int ret_val=0; + static BOOL already_checked = False; + + if(already_checked) + return True; + + errno = 0; + + ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); + + if(ret_val != 0) { + DEBUG(5, ("hpux_acl_call_present: shl_findsym() returned %d, errno = %d, error %s\n", + ret_val, errno, strerror(errno))); + DEBUG(5,("hpux_acl_call_present: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); + errno = ENOSYS; + return False; + } + + DEBUG(10,("hpux_acl_call_present: acl() system call is present. We have JFS 3.3 or above \n")); + + already_checked = True; + return True; +} + +/* + * runtime check for presence of aclsort library call. + * same code as for acl call. if there are more of these, + * a dispatcher function could be handy... + */ + +static BOOL hpux_aclsort_call_present(void) +{ + shl_t handle = NULL; + void *value; + int ret_val = 0; + static BOOL already_checked = False; + + if (already_checked) { + return True; + } + + errno = 0; + ret_val = shl_findsym(&handle, "aclsort", TYPE_PROCEDURE, &value); + if (ret_val != 0) { + DEBUG(5, ("hpux_aclsort_call_present: shl_findsym " + "returned %d, errno = %d, error %s", + ret_val, errno, strerror(errno))); + DEBUG(5, ("hpux_aclsort_call_present: " + "aclsort() function not available.\n")); + return False; + } + DEBUG(10,("hpux_aclsort_call_present: aclsort() function present.\n")); + already_checked = True; + return True; +} + +#if 0 +/* + * acl check function: + * unused at the moment but could be used to get more + * concrete error messages for debugging... + * (acl sort just says that the acl is invalid...) + */ +static BOOL hpux_acl_check(HPUX_ACL_T hpux_acl, int count) +{ + int check_rc; + int check_which; + + check_rc = aclcheck(hpux_acl, count, &check_which); + if (check_rc != 0) { + DEBUG(10, ("acl is not valid:\n")); + DEBUGADD(10, (" - return code: %d\n", check_rc)); + DEBUGADD(10, (" - which: %d\n", check_which)); + if (check_which != -1) { + DEBUGADD(10, (" - invalid entry:\n")); + DEBUGADD(10, (" * type: %d:\n", + hpux_acl[check_which].a_type)); + DEBUGADD(10, (" * id: %d\n", + hpux_acl[check_which].a_id)); + DEBUGADD(10, (" * perm: 0o%o\n", + hpux_acl[check_which].a_perm)); + } + return False; + } + return True; +} +#endif /* VFS operations structure */ static vfs_op_tuple hpuxacl_op_tuples[] = { /* Disk operations */ - {SMB_VFS_OP(hpuxacl_sys_acl_get_file), - SMB_VFS_OP_SYS_ACL_GET_FILE, - SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(hpuxacl_sys_acl_get_file), + SMB_VFS_OP_SYS_ACL_GET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(hpuxacl_sys_acl_get_fd), - SMB_VFS_OP_SYS_ACL_GET_FD, - SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(hpuxacl_sys_acl_get_fd), + SMB_VFS_OP_SYS_ACL_GET_FD, + SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(hpuxacl_sys_acl_set_file), - SMB_VFS_OP_SYS_ACL_SET_FILE, - SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(hpuxacl_sys_acl_set_file), + SMB_VFS_OP_SYS_ACL_SET_FILE, + SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(hpuxacl_sys_acl_set_fd), - SMB_VFS_OP_SYS_ACL_SET_FD, - SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(hpuxacl_sys_acl_set_fd), + SMB_VFS_OP_SYS_ACL_SET_FD, + SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(hpuxacl_sys_acl_delete_def_file), - SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, - SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(hpuxacl_sys_acl_delete_def_file), + SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, + SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(NULL), - SMB_VFS_OP_NOOP, - SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), + SMB_VFS_OP_NOOP, + SMB_VFS_LAYER_NOOP} }; -NTSTATUS vfs_hpuxacl_init(void); NTSTATUS vfs_hpuxacl_init(void) { return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "hpuxacl", diff --git a/source/modules/vfs_posixacl.c b/source/modules/vfs_posixacl.c index 191c4a7cb0e..109c1e20b2e 100644 --- a/source/modules/vfs_posixacl.c +++ b/source/modules/vfs_posixacl.c @@ -200,9 +200,15 @@ static BOOL smb_ace_to_internal(acl_entry_t posix_ace, return False; } ace->a_perm = 0; +#ifdef HAVE_ACL_GET_PERM_NP + ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0); + ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0); + ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); +#else ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0); ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0); ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); +#endif return True; } diff --git a/source/modules/vfs_tru64acl.c b/source/modules/vfs_tru64acl.c index 6aa9557c28c..0c2de36911f 100644 --- a/source/modules/vfs_tru64acl.c +++ b/source/modules/vfs_tru64acl.c @@ -28,8 +28,8 @@ static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace, static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl); static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag); static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag); -static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset); -static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset); +static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset); +static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset); /* public functions - the api */ @@ -201,7 +201,7 @@ static BOOL tru64_ace_to_smb_ace(acl_entry_t tru64_ace, acl_tag_t tru64_tag; acl_permset_t permset; SMB_ACL_TAG_T smb_tag_type; - smb_acl_permset_t smb_permset; + SMB_ACL_PERM_T smb_permset; void *qualifier; if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) { @@ -437,7 +437,7 @@ static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag) return smb_tag_type; } -static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset) +static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset) { /* originally, I thought that acl_clear_perm was the * proper way to reset the permset to 0. but without @@ -456,9 +456,9 @@ static acl_perm_t smb_permset_to_tru64(smb_acl_permset_t smb_permset) return tru64_permset; } -static smb_acl_permset_t tru64_permset_to_smb(const acl_perm_t tru64_permset) +static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset) { - smb_acl_permset_t smb_permset = 0; + SMB_ACL_PERM_T smb_permset = 0; smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0); smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0); smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index 1bd00869231..c7baecfbaa6 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -902,7 +902,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state) { struct getent_state *ent; struct winbindd_gr *group_list = NULL; - int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0; + int num_groups, group_list_ndx, gr_mem_list_len = 0; char *gr_mem_list = NULL; DEBUG(3, ("[%5lu]: getgrent\n", (unsigned long)state->pid)); @@ -916,6 +916,11 @@ void winbindd_getgrent(struct winbindd_cli_state *state) num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries); + if (num_groups == 0) { + request_error(state); + return; + } + if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) { request_error(state); return; @@ -938,7 +943,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state) /* Start sending back groups */ - for (i = 0; i < num_groups; i++) { + for (group_list_ndx = 0; group_list_ndx < num_groups; ) { struct acct_info *name_list = NULL; fstring domain_group_name; uint32 result; diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c index 6ee548292cc..589f4839e0b 100644 --- a/source/nsswitch/winbindd_pam.c +++ b/source/nsswitch/winbindd_pam.c @@ -288,7 +288,7 @@ struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, } else { return domain; } - } + } return find_our_domain(); } @@ -579,6 +579,14 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain, http_timestring(ticket_lifetime), (int)ticket_lifetime, http_timestring(renewal_until), (int)renewal_until)); + /* we cannot continue with krb5 when UF_DONT_REQUIRE_PREAUTH is set, + * in that case fallback to NTLM - gd */ + + if ((ticket_lifetime == 0) && (renewal_until == 0)) { + result = NT_STATUS_INVALID_LOGON_TYPE; + goto failed; + } + client_princ = talloc_strdup(state->mem_ctx, global_myname()); if (client_princ == NULL) { result = NT_STATUS_NO_MEMORY; diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c index ce677198fff..18797772dd4 100644 --- a/source/nsswitch/winbindd_user.c +++ b/source/nsswitch/winbindd_user.c @@ -631,7 +631,7 @@ void winbindd_getpwent(struct winbindd_cli_state *state) { struct getent_state *ent; struct winbindd_pw *user_list; - int num_users, user_list_ndx = 0, i; + int num_users, user_list_ndx; DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)state->pid)); @@ -645,6 +645,11 @@ void winbindd_getpwent(struct winbindd_cli_state *state) /* Allocate space for returning a chunk of users */ num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries); + + if (num_users == 0) { + request_error(state); + return; + } if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) { request_error(state); @@ -666,7 +671,7 @@ void winbindd_getpwent(struct winbindd_cli_state *state) /* Start sending back users */ - for (i = 0; i < num_users; i++) { + for (user_list_ndx = 0; user_list_ndx < num_users; ) { struct getpwent_user *name_list = NULL; uint32 result; @@ -709,8 +714,6 @@ void winbindd_getpwent(struct winbindd_cli_state *state) name_list[ent->sam_entry_index].shell, &user_list[user_list_ndx]); - ent->sam_entry_index++; - /* Add user to return list */ if (result) { @@ -723,6 +726,9 @@ void winbindd_getpwent(struct winbindd_cli_state *state) } else DEBUG(1, ("could not lookup domain user %s\n", name_list[ent->sam_entry_index].name)); + + ent->sam_entry_index++; + } /* Out of domains */ diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c index 9025f287036..37285f01d23 100644 --- a/source/passdb/lookup_sid.c +++ b/source/passdb/lookup_sid.c @@ -1209,12 +1209,6 @@ static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid) enum lsa_SidType type; uint32 rid; - if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) { - uid_t uid = rid; - *puid = uid; - goto done; - } - if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) { union unid_t id; BOOL ret; @@ -1260,12 +1254,6 @@ static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid) union unid_t id; enum lsa_SidType type; - if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) { - gid_t gid = rid; - *pgid = gid; - goto done; - } - if ((sid_check_is_in_builtin(psid) || sid_check_is_in_wellknown_domain(psid))) { BOOL ret; @@ -1329,7 +1317,6 @@ void uid_to_sid(DOM_SID *psid, uid_t uid) if (!winbind_uid_to_sid(psid, uid)) { if (!winbind_ping()) { - DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n")); legacy_uid_to_sid(psid, uid); return; } @@ -1359,7 +1346,6 @@ void gid_to_sid(DOM_SID *psid, gid_t gid) if (!winbind_gid_to_sid(psid, gid)) { if (!winbind_ping()) { - DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n")); legacy_gid_to_sid(psid, gid); return; } @@ -1382,6 +1368,7 @@ void gid_to_sid(DOM_SID *psid, gid_t gid) BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid) { + uint32 rid; gid_t gid; if (fetch_uid_from_cache(puid, psid)) @@ -1391,9 +1378,20 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid) return False; } + /* Optimize for the Unix Users Domain + * as the conversion is straightforward */ + if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) { + uid_t uid = rid; + *puid = uid; + + /* return here, don't cache */ + DEBUG(10,("sid %s -> uid %u\n", sid_string_static(psid), + (unsigned int)*puid )); + return True; + } + if (!winbind_sid_to_uid(puid, psid)) { if (!winbind_ping()) { - DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n")); return legacy_sid_to_uid(psid, puid); } @@ -1419,6 +1417,7 @@ BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid) BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid) { + uint32 rid; uid_t uid; if (fetch_gid_from_cache(pgid, psid)) @@ -1427,12 +1426,23 @@ BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid) if (fetch_uid_from_cache(&uid, psid)) return False; + /* Optimize for the Unix Groups Domain + * as the conversion is straightforward */ + if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) { + gid_t gid = rid; + *pgid = gid; + + /* return here, don't cache */ + DEBUG(10,("sid %s -> gid %u\n", sid_string_static(psid), + (unsigned int)*pgid )); + return True; + } + /* Ask winbindd if it can map this sid to a gid. * (Idmap will check it is a valid SID and of the right type) */ if ( !winbind_sid_to_gid(pgid, psid) ) { if (!winbind_ping()) { - DEBUG(2, ("WARNING: Winbindd not running, mapping ids with legacy code\n")); return legacy_sid_to_gid(psid, pgid); } diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index be5d8e4ca64..c073cc9a40d 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -914,13 +914,13 @@ BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen) goto done; } - pdb_set_logon_time(sampass, logon_time, PDB_SET); - pdb_set_logoff_time(sampass, logoff_time, PDB_SET); - pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); - pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET); - pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); - pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET); - pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); + pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET); + pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET); + pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET); + pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET); + pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET); + pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET); + pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET); pdb_set_username(sampass, username, PDB_SET); pdb_set_domain(sampass, domain, PDB_SET); @@ -1102,13 +1102,13 @@ uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_onl *buf = NULL; buflen = 0; - logon_time = (uint32)pdb_get_logon_time(sampass); - logoff_time = (uint32)pdb_get_logoff_time(sampass); - kickoff_time = (uint32)pdb_get_kickoff_time(sampass); - bad_password_time = (uint32)pdb_get_bad_password_time(sampass); - pass_can_change_time = (uint32)pdb_get_pass_can_change_time_noncalc(sampass); - pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass); - pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass); + logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass)); + logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass)); + kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass)); + bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass)); + pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass)); + pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass)); + pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass)); user_rid = pdb_get_user_rid(sampass); group_rid = pdb_get_group_rid(sampass); @@ -1392,7 +1392,7 @@ BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated) LastBadPassword = pdb_get_bad_password_time(sampass); DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n", (uint32) LastBadPassword, resettime, (uint32)time(NULL))); - if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){ + if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); if (updated) { @@ -1445,7 +1445,7 @@ bad password time. Leaving locked out.\n", return True; } - if ((time(NULL) > (LastBadPassword + (time_t) duration * 60))) { + if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) { pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK, PDB_CHANGED); diff --git a/source/python/setup.py b/source/python/setup.py index ce417710b30..1efe5938e11 100755 --- a/source/python/setup.py +++ b/source/python/setup.py @@ -67,6 +67,8 @@ for lib in string.split(samba_libs): libraries.append(lib[2:]) elif lib[0:8] == ("-pthread"): pass # Skip linker flags + elif lib[0:4] == ("-pie"): + pass # Skip linker flags elif lib[0:2] == "-L": library_dirs.append(lib[2:]) elif lib[0:2] in ("-W","-s"): diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c index 8ed67872430..f4e0e84d85a 100644 --- a/source/rpc_parse/parse_srv.c +++ b/source/rpc_parse/parse_srv.c @@ -2404,7 +2404,7 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps if(!prs_uint32("num_locks ", ps, depth, &fl3->num_locks)) return False; - uni_p = fl3->path ? (uint32)fl3->path : 0; + uni_p = fl3->path ? 1 : 0; if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; if (UNMARSHALLING(ps)) { @@ -2413,7 +2413,7 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps } } - uni_p = fl3->user ? (uint32)fl3->user : 0; + uni_p = fl3->user ? 1 : 0; if(!prs_uint32("ptr", ps, depth, &uni_p)) return False; if (UNMARSHALLING(ps)) { diff --git a/source/rpc_server/srv_lsa_ds_nt.c b/source/rpc_server/srv_lsa_ds_nt.c index f387bec9b6d..17543a38ef6 100644 --- a/source/rpc_server/srv_lsa_ds_nt.c +++ b/source/rpc_server/srv_lsa_ds_nt.c @@ -84,16 +84,16 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN basic->dnsname_ptr = 1; init_unistr2( &basic->dns_domain, dnsdomain, UNI_STR_TERMINATE); + + /* FIXME!! We really should fill in the correct forest + name. Should get this information from winbindd. */ basic->forestname_ptr = 1; init_unistr2( &basic->forest_domain, dnsdomain, UNI_STR_TERMINATE); } else { - get_mydnsdomname(dnsdomain); - strlower_m(dnsdomain); - - basic->dnsname_ptr = 1; - init_unistr2( &basic->dns_domain, dnsdomain, UNI_FLAGS_NONE); - basic->forestname_ptr = 1; - init_unistr2( &basic->forest_domain, dnsdomain, UNI_FLAGS_NONE); + /* security = domain should not fill in the dns or + forest name */ + basic->dnsname_ptr = 0; + basic->forestname_ptr = 0; } *info = basic; diff --git a/source/script/tests/gdb_backtrace b/source/script/tests/gdb_backtrace index b19a5b2f4b7..826381e9008 100644 --- a/source/script/tests/gdb_backtrace +++ b/source/script/tests/gdb_backtrace @@ -33,7 +33,7 @@ case "${UNAME}" in esac for DB in ${DB_LIST}; do - DB_BIN=`which ${DB} 2>/dev/null` + DB_BIN=`which ${DB} 2>/dev/null | grep '^/'` test x"${DB_BIN}" != x"" && { break } diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c index 70b2d30aaba..66baf4022a0 100644 --- a/source/smbd/blocking.c +++ b/source/smbd/blocking.c @@ -39,6 +39,7 @@ typedef struct _blocking_lock_record { SMB_BIG_UINT offset; SMB_BIG_UINT count; uint32 lock_pid; + uint32 blocking_pid; /* PID that blocks us. */ enum brl_flavour lock_flav; enum brl_type lock_type; char *inbuf; @@ -86,7 +87,9 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, uint32 lock_pid, enum brl_type lock_type, enum brl_flavour lock_flav, - SMB_BIG_UINT offset, SMB_BIG_UINT count) + SMB_BIG_UINT offset, + SMB_BIG_UINT count, + uint32 blocking_pid) { static BOOL set_lock_msg; blocking_lock_record *blr; @@ -127,6 +130,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, } blr->lock_num = lock_num; blr->lock_pid = lock_pid; + blr->blocking_pid = blocking_pid; blr->lock_flav = lock_flav; blr->lock_type = lock_type; blr->offset = offset; @@ -142,7 +146,8 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck, count, lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK, blr->lock_flav, - lock_timeout ? True : False); /* blocking_lock. */ + lock_timeout ? True : False, /* blocking_lock. */ + NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); @@ -380,7 +385,8 @@ static BOOL process_lockingX(blocking_lock_record *blr) READ_LOCK : WRITE_LOCK), WINDOWS_LOCK, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); @@ -440,7 +446,8 @@ static BOOL process_trans2(blocking_lock_record *blr) blr->lock_type, blr->lock_flav, True, - &status); + &status, + &blr->blocking_pid); TALLOC_FREE(br_lck); if (!NT_STATUS_IS_OK(status)) { @@ -598,7 +605,7 @@ unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms) { unsigned int timeout_ms = default_timeout_ms; struct timeval tv_curr; - SMB_BIG_INT min_tv_dif_us = 0x7FFFFFFF; /* A large +ve number. */ + SMB_BIG_INT min_tv_dif_us = default_timeout_ms * 1000; blocking_lock_record *blr = blocking_lock_queue; /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */ @@ -612,6 +619,15 @@ unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms) SMB_BIG_INT tv_dif_us; if (timeval_is_zero(&blr->expire_time)) { + /* + * If we're blocked on pid 0xFFFFFFFF this is + * a POSIX lock, so calculate a timeout of + * 10 seconds. + */ + if (blr->blocking_pid == 0xFFFFFFFF) { + tv_dif_us = 10 * 1000 * 1000; + min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us); + } continue; /* Never timeout. */ } diff --git a/source/smbd/close.c b/source/smbd/close.c index a123a542fd2..6a496f16a6e 100644 --- a/source/smbd/close.c +++ b/source/smbd/close.c @@ -287,6 +287,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, status = map_nt_error_from_unix(errno); } + notify_fname(conn, NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + fsp->fsp_name); + /* As we now have POSIX opens which can unlink * with other open files we may have taken * this code path with more than one share mode diff --git a/source/smbd/reply.c b/source/smbd/reply.c index b8d201328b5..37a49756e38 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -2421,7 +2421,8 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); if (NT_STATUS_V(status)) { @@ -3426,7 +3427,8 @@ int reply_lock(connection_struct *conn, WRITE_LOCK, WINDOWS_LOCK, False, /* Non-blocking lock. */ - &status); + &status, + NULL); TALLOC_FREE(br_lck); @@ -5524,6 +5526,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, BOOL blocking_lock = lock_timeout ? True : False; BOOL defer_lock = False; struct byte_range_lock *br_lck; + uint32 block_smbpid; br_lck = do_lock(fsp, lock_pid, @@ -5532,7 +5535,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* Windows internal resolution for blocking locks seems @@ -5569,7 +5573,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, lock_type, WINDOWS_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); END_PROFILE(SMBlockingX); return -1; diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 2ac90beba98..952aff953d2 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -4671,6 +4671,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, offset, POSIX_LOCK); } else { + uint32 block_smbpid; + struct byte_range_lock *br_lck = do_lock(fsp, lock_pid, count, @@ -4678,7 +4680,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, blocking_lock, - &status); + &status, + &block_smbpid); if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { /* @@ -4695,7 +4698,8 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, lock_type, POSIX_LOCK, offset, - count)) { + count, + block_smbpid)) { TALLOC_FREE(br_lck); return status; } diff --git a/source/smbd/uid.c b/source/smbd/uid.c index 85885803222..c6d4e3329c8 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -156,7 +156,9 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) char group_c; BOOL must_free_token = False; NT_USER_TOKEN *token = NULL; - + int num_groups = 0; + gid_t *group_list = NULL; + if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); @@ -195,14 +197,14 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; - current_user.ut.groups = conn->groups; - current_user.ut.ngroups = conn->ngroups; + group_list = conn->groups; + num_groups = conn->ngroups; token = conn->nt_user_token; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; - current_user.ut.ngroups = vuser->n_groups; - current_user.ut.groups = vuser->groups; + num_groups = vuser->n_groups; + group_list = vuser->groups; token = vuser->nt_user_token; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " @@ -235,8 +237,8 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) */ int i; - for (i = 0; i < current_user.ut.ngroups; i++) { - if (current_user.ut.groups[i] == conn->gid) { + for (i = 0; i < num_groups; i++) { + if (group_list[i] == conn->gid) { gid = conn->gid; gid_to_sid(&token->user_sids[1], gid); break; @@ -248,6 +250,12 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) } } + /* Now set current_user since we will immediately also call + set_sec_ctx() */ + + current_user.ut.ngroups = num_groups; + current_user.ut.groups = group_list; + set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token); diff --git a/source/utils/net_rap.c b/source/utils/net_rap.c index 9084122d680..54e59673b80 100644 --- a/source/utils/net_rap.c +++ b/source/utils/net_rap.c @@ -435,10 +435,14 @@ int net_rap_server(int argc, const char **argv) int ret; if (argc > 0) { - if (!strequal(argv[0], "name")) { + if (strequal(argv[0], "name")) { + return net_rap_server_name(argc, argv); + } + /* smb4k uses 'net [rap|rpc] server domain' to query servers in a domain */ + /* Fall through for 'domain', any other forms will cause to show usage message */ + if (!strequal(argv[0], "domain")) { return net_rap_server_usage(argc-1, argv+1); } - return net_rap_server_name(argc, argv); } if (!(cli = net_make_ipc_connection(0))) diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index 56aee3be91a..c300a7171ce 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -3113,7 +3113,7 @@ static void display_share_info_1(SRV_SHARE_INFO_1 *info1) if (opt_long_list_entries) { d_printf("%-12s %-8.8s %-50s\n", - netname, share_type[info1->info_1.type], remark); + netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark); } else { d_printf("%s\n", netname); } diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c index d1a87260fa9..078eae71ac2 100644 --- a/source/utils/pdbedit.c +++ b/source/utils/pdbedit.c @@ -96,7 +96,7 @@ static int export_database (struct pdb_methods *in, return 1; } - printf("Importing accout for %s...", user->username); + printf("Importing account for %s...", user->username); if ( !NT_STATUS_IS_OK(out->getsampwnam( out, account, user->username )) ) { status = out->add_sam_account(out, user); } else { @@ -285,14 +285,14 @@ static int print_sam_info (struct samu *sam_pwent, BOOL verbosity, BOOL smbpwdst lm_passwd, nt_passwd, pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), - (uint32)pdb_get_pass_last_set_time(sam_pwent)); + (uint32)convert_time_t_to_uint32(pdb_get_pass_last_set_time(sam_pwent))); } else { uid = nametouid(pdb_get_username(sam_pwent)); printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, pdb_get_fullname(sam_pwent)); } - return 0; + return 0; } /********************************************************* |