summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-01-13 17:55:43 +0000
committerGerald Carter <jerry@samba.org>2004-01-13 17:55:43 +0000
commit0c9adb69858c7572320d18c0fd187dd6e885f17d (patch)
treed58b1ad6bbc5ca0e9f71d17ebdaa9905268fa1d4
parent60079bd15bee7fe71dd43cb131f6198ca28f74eb (diff)
downloadsamba-0c9adb69858c7572320d18c0fd187dd6e885f17d.tar.gz
samba-0c9adb69858c7572320d18c0fd187dd6e885f17d.tar.bz2
samba-0c9adb69858c7572320d18c0fd187dd6e885f17d.zip
sync HEAD with recent changes in 3.0
(This used to be commit c98399e3c9d74e19b7c9d806ca8028b48866931e)
-rw-r--r--source3/Makefile.in26
-rw-r--r--source3/auth/auth_domain.c4
-rw-r--r--source3/bin/.cvsignore6
-rwxr-xr-xsource3/client/mount.cifs.c680
-rw-r--r--source3/configure.in101
-rw-r--r--source3/include/printing.h2
-rw-r--r--source3/include/samba_linux_quota.h336
-rw-r--r--source3/include/samba_xfs_quota.h165
-rw-r--r--source3/include/sysquotas.h152
-rw-r--r--source3/intl/lang_tdb.c3
-rw-r--r--source3/lib/charcnv.c4
-rw-r--r--source3/lib/sysquotas.c529
-rw-r--r--source3/lib/sysquotas_4A.c318
-rw-r--r--source3/lib/sysquotas_linux.c485
-rw-r--r--source3/lib/sysquotas_xfs.c306
-rw-r--r--source3/lib/talloctort.c4
-rw-r--r--source3/lib/time.c5
-rw-r--r--source3/lib/util_str.c6
-rw-r--r--source3/libads/sasl.c17
-rw-r--r--source3/libsmb/cliconnect.c46
-rw-r--r--source3/libsmb/clikrb5.c24
-rw-r--r--source3/libsmb/clispnego.c17
-rw-r--r--source3/libsmb/namequery.c86
-rw-r--r--source3/locking/locking.c4
-rw-r--r--source3/nmbd/nmbd_processlogon.c2
-rw-r--r--source3/nsswitch/wbinfo.c26
-rw-r--r--source3/nsswitch/winbind_nss_freebsd.c81
-rw-r--r--source3/nsswitch/winbindd.c2
-rw-r--r--source3/nsswitch/winbindd.h3
-rw-r--r--source3/nsswitch/winbindd_ads.c2
-rw-r--r--source3/nsswitch/winbindd_cache.c6
-rw-r--r--source3/nsswitch/winbindd_cm.c103
-rw-r--r--source3/nsswitch/winbindd_group.c62
-rw-r--r--source3/nsswitch/winbindd_misc.c16
-rw-r--r--source3/nsswitch/winbindd_nss.h3
-rw-r--r--source3/nsswitch/winbindd_rpc.c13
-rw-r--r--source3/nsswitch/winbindd_sid.c8
-rw-r--r--source3/nsswitch/winbindd_user.c52
-rw-r--r--source3/nsswitch/winbindd_util.c45
-rw-r--r--source3/nsswitch/wins.c4
-rw-r--r--source3/param/loadparm.c18
-rw-r--r--source3/passdb/secrets.c38
-rw-r--r--source3/printing/notify.c1
-rw-r--r--source3/printing/print_cups.c1
-rw-r--r--source3/printing/print_generic.c1
-rw-r--r--source3/printing/printing.c1
-rw-r--r--source3/printing/printing_db.c1
-rw-r--r--source3/rpc_client/cli_lsarpc.c89
-rw-r--r--source3/rpc_server/srv_samr_nt.c17
-rw-r--r--source3/rpcclient/cmd_lsarpc.c30
-rw-r--r--source3/rpcclient/cmd_spoolss.c2
-rwxr-xr-xsource3/script/installswat.sh2
-rw-r--r--source3/script/mkbuildoptions.awk16
-rw-r--r--source3/smbd/chgpasswd.c81
-rw-r--r--source3/smbd/quotas.c159
-rw-r--r--source3/tdb/tdb.c2
-rw-r--r--source3/tests/crack.c5
-rw-r--r--source3/utils/net_rpc.c40
-rw-r--r--source3/utils/ntlm_auth.c15
-rw-r--r--source3/utils/smbcontrol.c2
-rw-r--r--source3/utils/smbget.c574
61 files changed, 3485 insertions, 1364 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 923f4dbd5b..68aead0fc2 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -85,7 +85,6 @@ PRIVATEDIR = @privatedir@
SMB_PASSWD_FILE = $(PRIVATEDIR)/smbpasswd
PRIVATE_DIR = $(PRIVATEDIR)
-DATADIR = @datadir@
# This is where SWAT images and help files go
SWATDIR = @swatdir@
@@ -202,11 +201,11 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o param/modconf.o
-KRBCLIENT_OBJ = libads/kerberos.o
+KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o
LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
libads/krb5_setpw.o libads/ldap_user.o \
- libads/ads_struct.o libads/ads_status.o \
+ libads/ads_struct.o \
libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
libads/ads_ldap.o libads/authdata.o
@@ -362,8 +361,9 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
smbd/process.o smbd/service.o smbd/error.o \
- printing/printfsp.o \
- lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \
+ printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
+ lib/sysquotas_xfs.o lib/sysquotas_4A.o \
+ smbd/change_trust_pw.o smbd/fake_file.o \
smbd/quotas.o smbd/ntquotas.o lib/afs.o \
$(MANGLE_OBJ) @VFS_STATIC@
@@ -450,6 +450,8 @@ PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \
$(POPT_LIB_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o
+SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ) $(SECRETS_OBJ)
+
RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \
rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \
@@ -730,6 +732,12 @@ MAKEDIR = || exec false; \
-o $@
@BROKEN_CC@ -mv `echo $@ | sed 's%^.*/%%g'` $@
+# this adds support for precompiled headers. To use it, install a snapshot
+# of gcc-3.4 and run 'make pch' before you do the main build.
+pch:
+ rm -f $(srcdir)/include/includes.h.gch
+ $(CC) -I. -I$(srcdir) $(FLAGS) -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch
+
# These dependencies are only approximately correct: we want to make
# sure Samba's paths are updated if ./configure is re-run. Really it
# would be nice if "make prefix=/opt/samba all" also rebuilt things,
@@ -746,7 +754,7 @@ dynconfig.@PICSUFFIX@: dynconfig.c Makefile
@echo Compiling $*.c with @PICFLAGS@
@$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@
@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
-@POBAD_CC@ @mv $*.@PICSUFFIX@.o $@
+@POBAD_CC@ -@mv $*.@PICSUFFIX@.o $@
lib/version.o: lib/version.c include/version.h
@echo Compiling $*.c
@@ -870,6 +878,10 @@ bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS)
+bin/smbget@EXEEXT@: $(SMBGET_OBJ) @BUILD_POPT@ bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+
bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(KRB5LIBS) $(LDAP_LIBS)
@@ -1034,7 +1046,7 @@ bin/librpc_epmapper.@SHLIBEXT@: $(RPC_EPMAPPER_OBJ)
bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@echo "Linking $@"
- @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
# libraries. Add to the appropriate PICOBJ variable instead.
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 31ffd88083..0bf2031a37 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -33,10 +33,10 @@ extern BOOL global_machine_password_needs_changing;
* @param server either a machine name or text IP address to
* connect to.
* @param setup_creds_as domain account to setup credentials as
- * @param sec_chan switch value to distinguish between domain
+ * @param sec_chan a switch value to distinguish between domain
* member and interdomain authentication
* @param trust_passwd the trust password to establish the
- * credentials
+ * credentials with.
*
**/
diff --git a/source3/bin/.cvsignore b/source3/bin/.cvsignore
index 013a5ba6c1..aad6091960 100644
--- a/source3/bin/.cvsignore
+++ b/source3/bin/.cvsignore
@@ -5,6 +5,7 @@ debug2html
editreg
locktest
locktest2
+log2pcap
make_printerdef
make_smbcodepage
make_unicodemap
@@ -28,6 +29,7 @@ smbcquotas
smbd
smbfilter
smbgroupedit
+smbiconv
smbmnt
smbmount
smbpasswd
@@ -37,7 +39,6 @@ smbstatus
smbtorture
smbtree
smbumount
-smbiconv
swat
t_push_ucs2
t_snprintf
@@ -45,11 +46,10 @@ t_strcmp
t_stringoverflow
talloctort
tdbbackup
+tdbdump
testparm
testprns
vfstest
-log2pcap
wbinfo
winbindd
wrepld
-tdbdump
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index 43b20e9d50..8c23cc2212 100755
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -1,6 +1,27 @@
+/*
+ Mount helper utility for Linux CIFS VFS (virtual filesystem) client
+ Copyright (C) 2003 Steve French (sfrench@us.ibm.com)
+
+ 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. */
+
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#include <stdlib.h>
+#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
@@ -14,10 +35,14 @@
#include <netdb.h>
#include <string.h>
#include <mntent.h>
+#include <fcntl.h>
-#define MOUNT_CIFS_VERSION "1"
+#define MOUNT_CIFS_VERSION_MAJOR "1"
+#define MOUNT_CIFS_VERSION_MINOR "0"
-extern char *getusername(void);
+#ifndef MOUNT_CIFS_VENDOR_SUFFIX
+#define MOUNT_CIFS_VENDOR_SUFFIX ""
+#endif
char * thisprogram;
int verboseflag = 0;
@@ -41,17 +66,20 @@ char * mountpassword = NULL;
BB end finish BB */
-void mount_cifs_usage()
+static void mount_cifs_usage(void)
{
- printf("\nUsage: %s remotetarget dir\n", thisprogram);
- printf("\nMount the remotetarget, specified as either a UNC name or ");
- printf(" CIFS URL, to the local directory, dir.\n");
-
+ printf("\nUsage: %s <remotetarget> <dir> -o <options>\n", thisprogram);
+ printf("\nMount the remote target, specified as a UNC name,");
+ printf(" to a local directory.\n");
+ if(mountpassword) {
+ memset(mountpassword,0,64);
+ free(mountpassword);
+ }
exit(1);
}
/* caller frees username if necessary */
-char * getusername() {
+static char * getusername(void) {
char *username = NULL;
struct passwd *password = getpwuid(getuid());
@@ -61,25 +89,185 @@ char * getusername() {
return username;
}
-char * parse_cifs_url(unc_name)
+char * parse_cifs_url(char * unc_name)
{
printf("\ncifs url %s\n",unc_name);
+ return NULL;
+}
+
+static int open_cred_file(char * file_name)
+{
+ char * line_buf;
+ char * temp_val;
+ FILE * fs;
+ int i, length;
+ fs = fopen(file_name,"r");
+ if(fs == NULL)
+ return errno;
+ line_buf = malloc(4096);
+ if(line_buf == NULL)
+ return -ENOMEM;
+
+ while(fgets(line_buf,4096,fs)) {
+ /* parse line from credential file */
+
+ /* eat leading white space */
+ for(i=0;i<4096;i++) {
+ if(line_buf[i] == '\0')
+ break;
+ else if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
+ break;
+ line_buf++;
+ }
+
+ if (strncasecmp("username",line_buf,8) == 0) {
+ temp_val = strchr(line_buf + i,'=');
+ if(temp_val) {
+ /* go past equals sign */
+ temp_val++;
+ length = strlen(temp_val);
+ if(length > 4086) {
+ printf("cifs.mount failed due to malformed username in credentials file");
+ memset(line_buf,0,4096);
+ if(mountpassword) {
+ memset(mountpassword,0,64);
+ }
+ exit(1);
+ } else {
+ got_user = 1;
+ user_name = calloc(1 + length,1);
+ /* BB adding free of user_name string before exit,
+ not really necessary but would be cleaner */
+ strncpy(user_name,temp_val, length);
+ }
+ }
+ } else if (strncasecmp("password",line_buf,8) == 0) {
+ temp_val = strchr(line_buf+i,'=');
+ if(temp_val) {
+ /* go past equals sign */
+ temp_val++;
+ length = strlen(temp_val);
+ if(length > 64) {
+ printf("cifs.mount failed: password in credentials file too long\n");
+ memset(line_buf,0, 4096);
+ if(mountpassword) {
+ memset(mountpassword,0,64);
+ }
+ exit(1);
+ } else {
+ if(mountpassword == NULL) {
+ mountpassword = calloc(65,1);
+ }
+ if(mountpassword) {
+ strncpy(mountpassword,temp_val,64);
+ got_password = 1;
+ }
+ }
+ }
+ }
+ }
+ fclose(fs);
+ if(line_buf) {
+ memset(line_buf,0,4096);
+ free(line_buf);
+ }
+ return 0;
}
-int parse_options(char * options)
+static int get_password_from_file(int file_descript, char * filename)
+{
+ int rc = 0;
+ int i;
+ char c;
+
+ if(mountpassword == NULL)
+ mountpassword = calloc(65,1);
+ else
+ memset(mountpassword, 0, 64);
+
+ if(filename != NULL) {
+ file_descript = open(filename, O_RDONLY);
+ if(file_descript < 0) {
+ printf("cifs.mount failed. %s attempting to open password file %s\n",
+ strerror(errno),filename);
+ exit(1);
+ }
+ }
+ /* else file already open and fd provided */
+
+ for(i=0;i<64;i++) {
+ rc = read(file_descript,&c,1);
+ if(rc < 0) {
+ printf("cifs.mount failed. Error %s reading password file\n",strerror(errno));
+ memset(mountpassword,0,64);
+ if(filename != NULL)
+ close(file_descript);
+ exit(1);
+ } else if(rc == 0) {
+ if(mountpassword[0] == 0) {
+ if(verboseflag)
+ printf("\nWarning: null password used since cifs password file empty");
+ }
+ break;
+ } else /* read valid character */ {
+ if((c == 0) || (c == '\n')) {
+ break;
+ } else
+ mountpassword[i] = c;
+ }
+ }
+ if((i == 64) && (verboseflag)) {
+ printf("\nWarning: password longer than 64 characters specified in cifs password file");
+ }
+ got_password = 1;
+ if(filename != NULL) {
+ close(file_descript);
+ }
+
+ return rc;
+}
+
+static int parse_options(char * options)
{
char * data;
+ char * percent_char = 0;
char * value = 0;
+ char * next_keyword = 0;
+ int rc = 0;
if (!options)
return 1;
+ else
+ data = options;
+
+ if(verboseflag)
+ printf("\n parsing options: %s", options);
- while ((data = strsep(&options, ",")) != NULL) {
- if (!*data)
- continue;
+/* while ((data = strsep(&options, ",")) != NULL) { */
+ while(data != NULL) {
+ /* check if ends with trailing comma */
+ if(*data == 0)
+ break;
+
+ /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
+ /* data = next keyword */
+ /* value = next value ie stuff after equal sign */
+
+ next_keyword = strchr(data,',');
+
+ /* temporarily null terminate end of keyword=value pair */
+ if(next_keyword)
+ *next_keyword = 0;
+
+ /* if (!*data)
+ continue; */
+
+ /* temporarily null terminate keyword to make keyword and value distinct */
if ((value = strchr(data, '=')) != NULL) {
- *value++ = '\0';
+ *value = '\0';
+ value++;
}
+
if (strncmp(data, "user", 4) == 0) {
if (!value || !*value) {
printf("invalid or missing username\n");
@@ -87,113 +275,142 @@ int parse_options(char * options)
}
if (strnlen(value, 260) < 260) {
got_user=1;
- /* BB add check for format user%pass */
- /* if(strchr(username%passw) got_password = 1) */
+ percent_char = strchr(value,'%');
+ if(percent_char) {
+ *percent_char = ',';
+ if(mountpassword == NULL)
+ mountpassword = calloc(65,1);
+ if(mountpassword) {
+ if(got_password)
+ printf("\ncifs.mount warning - password specified twice\n");
+ got_password = 1;
+ percent_char++;
+ strncpy(mountpassword, percent_char,64);
+ /* remove password from username */
+ while(*percent_char != 0) {
+ *percent_char = ',';
+ percent_char++;
+ }
+ }
+ }
} else {
printf("username too long\n");
return 1;
}
- } else if (strncmp(data, "pass", 4) == 0) {
- if (!value || !*value) {
- if(got_password) {
- printf("password specified twice, ignoring second\n");
- } else
+ } else if (strncmp(data, "pass", 4) == 0) {
+ if (!value || !*value) {
+ if(got_password) {
+ printf("\npassword specified twice, ignoring second\n");
+ } else
+ got_password = 1;
+ } else if (strnlen(value, 17) < 17) {
+ if(got_password)
+ printf("\ncifs.mount warning - password specified twice\n");
got_password = 1;
- } else if (strnlen(value, 17) < 17) {
- got_password = 1;
- } else {
- printf("password too long\n");
- return 1;
- }
- } else if (strncmp(data, "ip", 2) == 0) {
- if (!value || !*value) {
- printf("target ip address argument missing");
- } else if (strnlen(value, 35) < 35) {
- got_ip = 1;
- } else {
- printf("ip address too long\n");
- return 1;
- }
- } else if ((strncmp(data, "unc", 3) == 0)
+ } else {
+ printf("password too long\n");
+ return 1;
+ }
+ } else if (strncmp(data, "ip", 2) == 0) {
+ if (!value || !*value) {
+ printf("target ip address argument missing");
+ } else if (strnlen(value, 35) < 35) {
+ got_ip = 1;
+ } else {
+ printf("ip address too long\n");
+ return 1;
+ }
+ } else if ((strncmp(data, "unc", 3) == 0)
|| (strncmp(data, "target", 6) == 0)
|| (strncmp(data, "path", 4) == 0)) {
- if (!value || !*value) {
- printf("invalid path to network resource\n");
- return 1; /* needs_arg; */
- } else if(strnlen(value,5) < 5) {
- printf("UNC name too short");
- }
+ if (!value || !*value) {
+ printf("invalid path to network resource\n");
+ return 1; /* needs_arg; */
+ } else if(strnlen(value,5) < 5) {
+ printf("UNC name too short");
+ }
- if (strnlen(value, 300) < 300) {
- got_unc = 1;
- if (strncmp(value, "//", 2) == 0) {
- if(got_unc)
- printf("unc name specified twice, ignoring second\n");
- else
- got_unc = 1;
- } else if (strncmp(value, "\\\\", 2) != 0) {
- printf("UNC Path does not begin with // or \\\\ \n");
+ if (strnlen(value, 300) < 300) {
+ got_unc = 1;
+ if (strncmp(value, "//", 2) == 0) {
+ if(got_unc)
+ printf("unc name specified twice, ignoring second\n");
+ else
+ got_unc = 1;
+ } else if (strncmp(value, "\\\\", 2) != 0) {
+ printf("UNC Path does not begin with // or \\\\ \n");
+ return 1;
+ } else {
+ if(got_unc)
+ printf("unc name specified twice, ignoring second\n");
+ else
+ got_unc = 1;
+ }
+ } else {
+ printf("CIFS: UNC name too long\n");
return 1;
+ }
+ } else if ((strncmp(data, "domain", 3) == 0)
+ || (strncmp(data, "workgroup", 5) == 0)) {
+ if (!value || !*value) {
+ printf("CIFS: invalid domain name\n");
+ return 1; /* needs_arg; */
+ }
+ if (strnlen(value, 65) < 65) {
+ got_domain = 1;
} else {
- if(got_unc)
- printf("unc name specified twice, ignoring second\n");
- else
- got_unc = 1;
+ printf("domain name too long\n");
+ return 1;
+ }
+ } else if (strncmp(data, "cred", 4) == 0) {
+ if (value && *value) {
+ rc = open_cred_file(value);
+ if(rc) {
+ printf("error %d opening credential file %s",rc, value);
+ return 1;
+ }
+ } else {
+ printf("invalid credential file name specified\n");
+ return 1;
+ }
+ } else if (strncmp(data, "uid", 3) == 0) {
+ if (value && *value) {
+ got_uid = 1;
+ }
+ } else if (strncmp(data, "gid", 3) == 0) {
+ if (value && *value) {
+ got_gid = 1;
}
- } else {
- printf("CIFS: UNC name too long\n");
- return 1;
- }
- } else if ((strncmp(data, "domain", 3) == 0)
- || (strncmp(data, "workgroup", 5) == 0)) {
- if (!value || !*value) {
- printf("CIFS: invalid domain name\n");
- return 1; /* needs_arg; */
- }
- if (strnlen(value, 65) < 65) {
- got_domain = 1;
- } else {
- printf("domain name too long\n");
- return 1;
- }
- } else if (strncmp(data, "uid", 3) == 0) {
- if (value && *value) {
- got_uid = 1;
- }
- } else if (strncmp(data, "gid", 3) == 0) {
- if (value && *value) {
- got_gid = 1;
- }
/* fmask and dmask synonyms for people used to smbfs syntax */
- } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
- if (!value || !*value) {
- printf ("Option '%s' requires a numerical argument\n", data);
- return 1;
- }
+ } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
+ if (!value || !*value) {
+ printf ("Option '%s' requires a numerical argument\n", data);
+ return 1;
+ }
- if (value[0] != '0') {
- printf ("WARNING: '%s' not expressed in octal.\n", data);
- }
+ if (value[0] != '0') {
+ printf ("WARNING: '%s' not expressed in octal.\n", data);
+ }
+
+ if (strcmp (data, "fmask") == 0) {
+ printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
+ data = "file_mode";
+ }
+ } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
+ if (!value || !*value) {
+ printf ("Option '%s' requires a numerical argument\n", data);
+ return 1;
+ }
+
+ if (value[0] != '0') {
+ printf ("WARNING: '%s' not expressed in octal.\n", data);
+ }
- if (strcmp (data, "fmask") == 0) {
- printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
- data = "file_mode";
- }
- } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
- if (!value || !*value) {
- printf ("Option '%s' requires a numerical argument\n", data);
- return 1;
- }
-
- if (value[0] != '0') {
- printf ("WARNING: '%s' not expressed in octal.\n", data);
- }
-
- if (strcmp (data, "dmask") == 0) {
- printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
- data = "dir_mode";
- }
- } /* else if (strnicmp(data, "port", 4) == 0) {
+ if (strcmp (data, "dmask") == 0) {
+ printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
+ data = "dir_mode";
+ }
+ } /* else if (strnicmp(data, "port", 4) == 0) {
if (value && *value) {
vol->port =
simple_strtoul(value, &value, 0);
@@ -214,6 +431,22 @@ int parse_options(char * options)
} else
printf("CIFS: Unknown mount option %s\n",data); */
+
+ /* move to next option */
+ data = next_keyword+1;
+
+ /* put overwritten equals sign back */
+ if(value) {
+ value--;
+ *value = '=';
+ }
+
+ /* put previous overwritten comma back */
+ if(next_keyword)
+ *next_keyword = ',';
+ else
+ data = 0;
+
}
return 0;
}
@@ -226,8 +459,7 @@ char * parse_server(char * unc_name)
char * ipaddress_string = NULL;
struct hostent * host_entry;
struct in_addr server_ipaddr;
- int rc,j;
- char temp[64];
+ int rc;
if(length > 1023) {
printf("mount error: UNC name too long");
@@ -244,7 +476,6 @@ char * parse_server(char * unc_name)
printf("\nMounting the DFS root for domain not implemented yet");
return 0;
} else {
- /* BB add support for \\\\ not just // */
if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
printf("mount error: improperly formatted UNC name.");
printf(" %s does not begin with \\\\ or //\n",unc_name);
@@ -300,21 +531,19 @@ static struct option longopts[] = {
{ "rw", 0, 0, 'w' },
{ "options", 1, 0, 'o' },
{ "types", 1, 0, 't' },
- { "replace", 0, 0, 129 },
- { "after", 0, 0, 130 },
- { "before", 0, 0, 131 },
- { "over", 0, 0, 132 },
- { "move", 0, 0, 133 },
- { "rsize",1, 0, 136 },
- { "wsize",1, 0, 137 },
- { "uid", 1, 0, 138},
- { "gid", 1, 0, 139},
+ { "rsize",1, 0, 'R' },
+ { "wsize",1, 0, 'W' },
+ { "uid", 1, 0, '1'},
+ { "gid", 1, 0, '2'},
{ "uuid",1,0,'U' },
- { "user",1,0,140},
- { "username",1,0,140},
- { "dom",1,0,141},
- { "domain",1,0,141},
- { "password",1,0,142},
+ { "user",1,0,'u'},
+ { "username",1,0,'u'},
+ { "dom",1,0,'d'},
+ { "domain",1,0,'d'},
+ { "password",1,0,'p'},
+ { "pass",1,0,'p'},
+ { "credentials",1,0,'c'},
+ { "port",1,0,'P'},
{ NULL, 0, 0, 0 }
};
@@ -330,13 +559,14 @@ int main(int argc, char ** argv)
char * mountpoint;
char * options;
char * temp;
- int rc,i;
+ int rc;
int rsize = 0;
int wsize = 0;
int nomtab = 0;
int uid = 0;
int gid = 0;
int optlen = 0;
+ int orgoptlen = 0;
struct stat statbuf;
struct utsname sysinfo;
struct mntent mountent;
@@ -354,56 +584,40 @@ int main(int argc, char ** argv)
uname(&sysinfo);
/* BB add workstation name and domain and pass down */
-/*#ifdef _GNU_SOURCE
- printf(" node: %s machine: %s\n", sysinfo.nodename,sysinfo.machine);
-#endif*/
- if(argc < 3)
- mount_cifs_usage();
+
+/* #ifdef _GNU_SOURCE
+ printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
+#endif */
+
share_name = argv[1];
mountpoint = argv[2];
+
/* add sharename in opts string as unc= parm */
while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
longopts, NULL)) != -1) {
switch (c) {
-/* case 'a':
- ++mount_all;
- break;
- case 'f':
- ++fake;
- break;
- case 'F':
- ++optfork;
- break; */
- case 'h': /* help */
- mount_cifs_usage ();
- break;
-/* case 'i':
- external_allowed = 0;
- break;
- case 'l':
+/* No code to do the following options yet */
+/* case 'l':
list_with_volumelabel = 1;
break;
case 'L':
volumelabel = optarg;
break; */
- case 'n':
- ++nomtab;
- break;
- case 'o':
- if (orgoptions) {
- orgoptions = strcat(orgoptions, ",");
- orgoptions = strcat(orgoptions,optarg);
- } else
- orgoptions = strdup(optarg);
- break;
+/* case 'a':
+ ++mount_all;
+ break; */
-/* case 'O':
- if (test_opts)
- test_opts = xstrconcat3(test_opts, ",", optarg);
- else
- test_opts = xstrdup(optarg);
- break;*/
+ case '?':
+ case 'h': /* help */
+ mount_cifs_usage ();
+ exit(1);
+ case 'n':
+ ++nomtab;
+ break;
+ case 'o':
+ orgoptions = strdup(optarg);
+ break;
case 'r': /* mount readonly */
flags |= MS_RDONLY;
break;
@@ -413,68 +627,78 @@ int main(int argc, char ** argv)
case 'v':
++verboseflag;
break;
-/* case 'V':
- printf ("mount: %s\n", version);
- exit (0);*/
+ case 'V':
+ printf ("mount.cifs version: %s.%s%s\n",
+ MOUNT_CIFS_VERSION_MAJOR,
+ MOUNT_CIFS_VERSION_MINOR,
+ MOUNT_CIFS_VENDOR_SUFFIX);
+ if(mountpassword) {
+ memset(mountpassword,0,64);
+ }
+ exit (0);
case 'w':
flags &= ~MS_RDONLY;
break;
-/* case 0:
- break;
-
- case 128:
- mounttype = MS_BIND;
- break;
- case 129:
- mounttype = MS_REPLACE;
- break;
- case 130:
- mounttype = MS_AFTER;
- break;
- case 131:
- mounttype = MS_BEFORE;
- break;
- case 132:
- mounttype = MS_OVER;
- break;
- case 133:
- mounttype = MS_MOVE;
- break;
- case 135:
- mounttype = (MS_BIND | MS_REC);
- break; */
- case 136:
+ case 'R':
rsize = atoi(optarg) ;
break;
- case 137:
+ case 'W':
wsize = atoi(optarg);
break;
- case 138:
+ case '1':
uid = atoi(optarg);
break;
- case 139:
+ case '2':
gid = atoi(optarg);
break;
- case 140:
+ case 'u':
got_user = 1;
user_name = optarg;
break;
- case 141:
+ case 'd':
domain_name = optarg;
break;
- case 142:
- got_password = 1;
- mountpassword = optarg;
+ case 'p':
+ if(mountpassword == NULL)
+ mountpassword = calloc(65,1);
+ if(mountpassword) {
+ got_password = 1;
+ strncpy(mountpassword,optarg,64);
+ }
+ break;
+ case 't':
break;
- case '?':
default:
- mount_cifs_usage ();
+ printf("unknown mount option %c\n",c);
+ mount_cifs_usage();
+ exit(1);
}
}
- /* canonicalize the path in argv[1]? */
+ if(argc < 3)
+ mount_cifs_usage();
+
+ if (getenv("PASSWD")) {
+ if(mountpassword == NULL)
+ mountpassword = calloc(65,1);
+ if(mountpassword) {
+ strncpy(mountpassword,getenv("PASSWD"),64);
+ got_password = 1;
+ }
+ } else if (getenv("PASSWD_FD")) {
+ get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
+ } else if (getenv("PASSWD_FILE")) {
+ get_password_from_file(0, getenv("PASSWD_FILE"));
+ }
+
+ ipaddr = parse_server(share_name);
+
+ if (orgoptions && parse_options(orgoptions))
+ return 1;
+
+ /* BB save off path and pop after mount returns? */
+ /* BB canonicalize the path in argv[1]? */
- /* BB save off path and pop after mount returns */
if(chdir(mountpoint)) {
printf("mount error: can not change directory into mount target %s\n",mountpoint);
}
@@ -490,44 +714,26 @@ int main(int argc, char ** argv)
}
if((getuid() != 0) && (geteuid() == 0)) {
- if((statbuf.st_uid == getuid()) && (S_IRWXU == statbuf.st_mode & S_IRWXU)) {
+ if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
printf("setuid mount allowed\n");
} else {
- printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n");
+ printf("mount error: permission denied or not superuser and cifs.mount not installed SUID\n");
return -1;
}
}
- ipaddr = parse_server(share_name);
-/* if(share_name == NULL)
- return 1; */
- if (orgoptions && parse_options(strdup(orgoptions)))
- return 1;
-
if(got_user == 0)
user_name = getusername();
-/* check username for user%password format */
-
if(got_password == 0) {
- if (getenv("PASSWD")) {
- mountpassword = malloc(33);
- if(mountpassword) {
- strncpy(mountpassword,getenv("PASSWD"),32);
- got_password = 1;
- }
-/* } else if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
- get_password_file();
- got_password = 1;*/ /* BB add missing function */
- } else {
- mountpassword = getpass("Password: "); /* BB obsolete */
- got_password = 1;
- }
+ mountpassword = getpass("Password: "); /* BB obsolete */
+ got_password = 1;
}
/* FIXME launch daemon (handles dfs name resolution and credential change)
remember to clear parms and overwrite password field before launching */
if(orgoptions) {
optlen = strlen(orgoptions);
+ orgoptlen = optlen;
} else
optlen = 0;
if(share_name)
@@ -560,19 +766,20 @@ int main(int argc, char ** argv)
strcat(options,mountpassword);
}
strncat(options,",ver=",5);
- strcat(options,MOUNT_CIFS_VERSION);
+ strcat(options,MOUNT_CIFS_VERSION_MAJOR);
if(orgoptions) {
strcat(options,",");
strcat(options,orgoptions);
}
- /* printf("\noptions %s \n",options);*/
+ if(verboseflag)
+ printf("\ncifs.mount kernel mount options %s \n",options);
if(mount(share_name, mountpoint, "cifs", flags, options)) {
/* remember to kill daemon on error */
switch (errno) {
case 0:
printf("mount failed but no error number set\n");
- return 0;
+ break;
case ENODEV:
printf("mount error: cifs filesystem not supported by the system\n");
break;
@@ -580,6 +787,9 @@ int main(int argc, char ** argv)
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;
} else {
pmntfile = setmntent(MOUNTED, "a+");
@@ -596,6 +806,20 @@ int main(int argc, char ** argv)
printf("could not update mount table\n");
}
}
+ if(mountpassword) {
+ memset(mountpassword,0,64);
+ free(mountpassword);
+ }
+
+ if(options) {
+ memset(options,0,optlen);
+ free(options);
+ }
+
+ if(orgoptions) {
+ memset(orgoptions,0,orgoptlen);
+ free(orgoptions);
+ }
return 0;
}
diff --git a/source3/configure.in b/source3/configure.in
index 1121551efc..821ab3a1ea 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -187,7 +187,6 @@ AC_SUBST(CONFIG_LIBS)
AC_ARG_ENABLE(debug,
[ --enable-debug Turn on compiler debugging information (default=no)],
[if eval "test x$enable_debug = xyes"; then
- echo "DEBUGGING TURNED ON!!!!"
CFLAGS="${CFLAGS} -g"
fi])
@@ -1636,9 +1635,8 @@ for i in $LOOK_DIRS ; do
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$i/include"
dnl This is here to handle -withval stuff for --with-libiconv
- if test x"$ICONV_PATH_SPEC" = "xyes" ; then
- LDFLAGS="-L$i/lib"
- fi
+dnl Perhaps we should always add a -L
+ LDFLAGS="$LDFLAGS -L$i/lib"
LIBS=
export LDFLAGS LIBS CPPFLAGS
dnl Try to find iconv(3)
@@ -1715,7 +1713,7 @@ dnl ])
LIBS="$ic_save_LIBS"
if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then
CPPFLAGS=$save_CPPFLAGS
- CFLAGS_ADD_DIR(CPPFLAGS, "$i/include")
+ LDFLAGS=$save_LDFLAGS
LIBS=$save_LIBS
if test x"$jm_cv_lib_iconv" != x; then
LIBS="$LIBS -l$jm_cv_lib_iconv"
@@ -2640,6 +2638,7 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
LIBS="$LIBS $KRB5_LIBS"
@@ -3056,6 +3055,7 @@ samba_cv_TRY_QUOTAS=no
samba_cv_RUN_QUOTA_TESTS=auto
samba_cv_WITH_SYS_QUOTAS=auto
samba_cv_TRY_SYS_QUOTAS=no
+samba_cv_SYSQUOTA_FOUND=no;
AC_MSG_CHECKING(whether to try disk-quotas support)
AC_ARG_WITH(quotas,
@@ -3125,6 +3125,11 @@ AC_MSG_CHECKING(whether to try the lib/sysquotas.c interface on ${host_os})
AC_MSG_RESULT(yes)
samba_cv_TRY_SYS_QUOTAS=yes
samba_cv_RUN_QUOTA_TESTS=yes
+ samba_cv_SYSQUOTA_FOUND=yes
+ AC_DEFINE(HAVE_QUOTACTL_LINUX,1,[Whether Linux quota support is available])
+ samba_cv_sysquotas_file="lib/sysquotas_linux.c"
+ AC_DEFINE(HAVE_LINUX_XFS_QUOTAS,1,[Whether Linux xfs quota support is available])
+ samba_cv_found_xfs_header=yes
;;
*)
AC_MSG_RESULT(no)
@@ -3137,21 +3142,21 @@ fi
# only check for quota stuff if --with-quotas
if test x"$samba_cv_RUN_QUOTA_TESTS" != x"no"; then
+# some broken header files need this
+AC_CHECK_HEADER(asm/types.h,[
+ AC_DEFINE(HAVE_ASM_TYPES_H,1,[check for <asm/types.h>])
+ AC_ADD_INCLUDE(<asm/types.h>)
+ ])
+
# For quotas on Veritas VxFS filesystems
AC_CHECK_HEADERS(sys/fs/vx_quota.h)
# For sys/quota.h and linux/quota.h
AC_CHECK_HEADERS(sys/quota.h)
-AC_CHECK_HEADERS(asm/types.h linux/quota.h)
-
-# For quotas on Linux XFS filesystems
-AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
-AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)
-# For linux > 2.5.56
-AC_CHECK_HEADERS(linux/dqblk_xfs.h)
-# if we have struct if_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct if_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_IF_DQBLK, [
+if test x"$samba_cv_found_xfs_header" != x"yes"; then
+# if we have xfs quota support <sys/quota.h> (IRIX) we should use it
+AC_CACHE_CHECK([for XFS QUOTA in <sys/quota.h>],samba_cv_HAVE_SYS_QUOTA_XFS, [
AC_TRY_COMPILE([
#include "confdefs.h"
#ifdef HAVE_SYS_TYPES_H
@@ -3160,28 +3165,12 @@ AC_TRY_COMPILE([
#ifdef HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif
-#include <linux/quota.h>
-],[struct if_dqblk D;],
-samba_cv_HAVE_STRUCT_IF_DQBLK=yes,samba_cv_HAVE_STRUCT_IF_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_IF_DQBLK"x = "yes"x; then
- AC_DEFINE(HAVE_STRUCT_IF_DQBLK,1,[struct if_dqblk])
+#include <sys/quota.h>
+],[int i = Q_XGETQUOTA;],
+samba_cv_HAVE_SYS_QUOTA_XFS=yes,samba_cv_HAVE_SYS_QUOTA_XFS=no)])
+if test "$samba_cv_HAVE_SYS_QUOTA_XFS"x = "yes"x; then
+ samba_cv_found_xfs_header=yes
fi
-
-# if we have struct mem_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct mem_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_MEM_DQBLK, [
-AC_TRY_COMPILE([
-#include "confdefs.h"
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-#include <linux/quota.h>
-],[struct mem_dqblk D;],
-samba_cv_HAVE_STRUCT_MEM_DQBLK=yes,samba_cv_HAVE_STRUCT_MEM_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_MEM_DQBLK"x = "yes"x; then
- AC_DEFINE(HAVE_STRUCT_MEM_DQBLK,1,[struct mem_dqblk])
fi
# if we have struct dqblk .dqb_fsoftlimit instead of .dqb_isoftlimit on IRIX
@@ -3201,7 +3190,6 @@ fi
##################
# look for a working quota system
-samba_cv_SYSQUOTA_FOUND=no;
if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then
AC_CACHE_CHECK([for long quotactl(int cmd, char *special, qid_t id, caddr_t addr)],samba_cv_HAVE_QUOTACTL_4A,[
@@ -3212,7 +3200,9 @@ AC_TRY_RUN_STRICT([
#include "${srcdir-.}/tests/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS],
samba_cv_HAVE_QUOTACTL_4A=yes,samba_cv_HAVE_QUOTACTL_4A=no,samba_cv_HAVE_QUOTACTL_4A=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_4A" = x"yes"; then
- samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+ samba_cv_sysquotas_file="lib/sysquotas_4A.c"
fi
fi
@@ -3226,7 +3216,9 @@ AC_TRY_RUN_STRICT([
samba_cv_HAVE_QUOTACTL_4B=yes,samba_cv_HAVE_QUOTACTL_4B=no,samba_cv_HAVE_QUOTACTL_4B=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_4B" = x"yes"; then
echo "int quotactl(const char *path, int cmd, int id, char *addr) is not reworked for the new sys_quota api"
-# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+ samba_cv_sysquotas_file="lib/sysquotas_4B.c"
fi
fi
@@ -3240,7 +3232,9 @@ AC_TRY_RUN_STRICT([
samba_cv_HAVE_QUOTACTL_3=yes,samba_cv_HAVE_QUOTACTL_3=no,samba_cv_HAVE_QUOTACTL_3=cross)])
if test x"$samba_cv_HAVE_QUOTACTL_3" = x"yes"; then
echo "CRAY int quotactl (char *spec, int request, char *arg) is NOT reworked for the sys_quota api"
-# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+ samba_cv_SYSQUOTA_FOUND=yes;
+ AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+ samba_cv_sysquotas_file="lib/sysquotas_3.c"
fi
fi
@@ -3299,6 +3293,27 @@ AC_MSG_CHECKING(whether to use the new lib/sysquotas.c interface)
fi
fi
+if test x"$samba_cv_SYSQUOTA_FOUND" != x"no" -a x"$samba_cv_found_xfs_header" = x"yes"; then
+AC_CACHE_CHECK([whether the sys_quota interface works with XFS],samba_cv_SYSQUOTA_WORKS_XFS,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch"
+AC_TRY_COMPILE([
+#include "confdefs.h"
+#define NO_PROTO_H 1
+#define NO_CONFIG_H 1
+#define HAVE_SYS_QUOTAS 1
+#define HAVE_XFS_QUOTAS 1
+#include "${srcdir-.}/lib/sysquotas_xfs.c"
+],[],samba_cv_SYSQUOTA_WORKS_XFS=yes,samba_cv_SYSQUOTA_WORKS_XFS=no)
+CPPFLAGS="$SAVE_CPPFLAGS"
+])
+if test x"$samba_cv_SYSQUOTA_WORKS_XFS" = x"yes"; then
+ if test x"$samba_cv_WE_USE_SYS_QUOTAS" = x"yes"; then
+ AC_DEFINE(HAVE_XFS_QUOTAS,1,[Whether xfs quota support is available])
+ fi
+fi
+fi
+
AC_CACHE_CHECK([whether the old quota support works],samba_cv_QUOTA_WORKS,[
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch"
@@ -4021,9 +4036,15 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
case "$host_os" in
- *linux*|*freebsd*)
+ *linux*)
WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o"
;;
+ *freebsd5*)
+ # FreeBSD winbind client is implemented as a wrapper around
+ # the Linux version.
+ WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_freebsd.o \
+ nsswitch/winbind_nss_linux.o"
+ ;;
*irix*)
# IRIX has differently named shared libraries
WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o"
diff --git a/source3/include/printing.h b/source3/include/printing.h
index 1d658a0768..bf7c61b251 100644
--- a/source3/include/printing.h
+++ b/source3/include/printing.h
@@ -21,8 +21,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "includes.h"
-
/*
This file defines the low-level printing system interfaces used by the
SAMBA printing subsystem.
diff --git a/source3/include/samba_linux_quota.h b/source3/include/samba_linux_quota.h
new file mode 100644
index 0000000000..02b3e5169b
--- /dev/null
+++ b/source3/include/samba_linux_quota.h
@@ -0,0 +1,336 @@
+#ifndef _SAMBA_LINUX_QUOTA_H_
+#define _SAMBA_LINUX_QUOTA_H_
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Andrew Tridgell 1994-2002
+
+ 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 file is needed because Quota support on Linux has
+ been broken since Linus kernel 2.4.x. It will only get
+ better (and this file be removed) when all the distributions
+ ship a glibc with a working quota.h file. This is very
+ bad. JRA.
+
+ Original file came from Christoph Hellwig <hch@infradead.org>.
+ Massaged into one nasty include file (to stop us having to
+ add multiple files into Samba just for Linux braindamage)
+ by JRA.
+*/
+
+#undef QUOTABLOCK_SIZE
+
+#ifndef _QUOTAIO_LINUX_V1
+#define _QUOTAIO_LINUX_V1
+
+/*
+ * Headerfile for old quotafile format
+ */
+
+#include <sys/types.h>
+
+#define V1_DQBLK_SIZE_BITS 10
+#define V1_DQBLK_SIZE (1 << V1_DQBLK_SIZE_BITS) /* Size of one quota block in bytes in old format */
+
+#define V1_DQOFF(__id) ((loff_t) ((__id) * sizeof(struct v1_disk_dqblk)))
+
+/* Structure of quota on disk */
+struct v1_disk_dqblk {
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_curblocks; /* current block count */
+ u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred limit on inodes */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive files */
+} __attribute__ ((packed));
+
+/* Structure used for communication with kernel */
+struct v1_kern_dqblk {
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_curblocks; /* current block count */
+ u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive files */
+};
+
+struct v1_dqstats {
+ u_int32_t lookups;
+ u_int32_t drops;
+ u_int32_t reads;
+ u_int32_t writes;
+ u_int32_t cache_hits;
+ u_int32_t allocated_dquots;
+ u_int32_t free_dquots;
+ u_int32_t syncs;
+};
+
+#ifndef Q_V1_GETQUOTA
+#define Q_V1_GETQUOTA 0x300
+#endif
+#ifndef Q_V1_SETQUOTA
+#define Q_V1_SETQUOTA 0x400
+#endif
+
+#endif /* _QUOTAIO_LINUX_V1 */
+
+/*
+ *
+ * Header file for disk format of new quotafile format
+ *
+ */
+
+#ifndef _QUOTAIO_LINUX_V2
+#define _QUOTAIO_LINUX_V2
+
+#include <sys/types.h>
+
+#ifndef _QUOTA_LINUX
+#define _QUOTA_LINUX
+
+#include <sys/types.h>
+
+typedef u_int32_t qid_t; /* Type in which we store ids in memory */
+typedef u_int64_t qsize_t; /* Type in which we store size limitations */
+
+#define MAXQUOTAS 2
+#define USRQUOTA 0 /* element used for user quotas */
+#define GRPQUOTA 1 /* element used for group quotas */
+
+/*
+ * Definitions for the default names of the quotas files.
+ */
+#define INITQFNAMES { \
+ "user", /* USRQUOTA */ \
+ "group", /* GRPQUOTA */ \
+ "undefined", \
+}
+
+/*
+ * Definitions of magics and versions of current quota files
+ */
+#define INITQMAGICS {\
+ 0xd9c01f11, /* USRQUOTA */\
+ 0xd9c01927 /* GRPQUOTA */\
+}
+
+/* Size of blocks in which are counted size limits in generic utility parts */
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+
+/* Conversion routines from and to quota blocks */
+#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
+#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
+#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
+
+/*
+ * Command definitions for the 'quotactl' system call.
+ * The commands are broken into a main command defined below
+ * and a subcommand that is used to convey the type of
+ * quota that is being manipulated (see above).
+ */
+#define SUBCMDMASK 0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_6_5_QUOTAON 0x0100 /* enable quotas */
+#define Q_6_5_QUOTAOFF 0x0200 /* disable quotas */
+#define Q_6_5_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
+
+#define Q_SYNC 0x800001 /* sync disk copy of a filesystems quotas */
+#define Q_QUOTAON 0x800002 /* turn quotas on */
+#define Q_QUOTAOFF 0x800003 /* turn quotas off */
+#define Q_GETFMT 0x800004 /* get quota format used on given filesystem */
+#define Q_GETINFO 0x800005 /* get information about quota files */
+#define Q_SETINFO 0x800006 /* set information about quota files */
+#define Q_GETQUOTA 0x800007 /* get user quota structure */
+#define Q_SETQUOTA 0x800008 /* set user quota structure */
+
+/*
+ * Quota structure used for communication with userspace via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define QIF_BLIMITS 1
+#define QIF_SPACE 2
+#define QIF_ILIMITS 4
+#define QIF_INODES 8
+#define QIF_BTIME 16
+#define QIF_ITIME 32
+#define QIF_LIMITS (QIF_BLIMITS | QIF_ILIMITS)
+#define QIF_USAGE (QIF_SPACE | QIF_INODES)
+#define QIF_TIMES (QIF_BTIME | QIF_ITIME)
+#define QIF_ALL (QIF_LIMITS | QIF_USAGE | QIF_TIMES)
+
+struct if_dqblk {
+ u_int64_t dqb_bhardlimit;
+ u_int64_t dqb_bsoftlimit;
+ u_int64_t dqb_curspace;
+ u_int64_t dqb_ihardlimit;
+ u_int64_t dqb_isoftlimit;
+ u_int64_t dqb_curinodes;
+ u_int64_t dqb_btime;
+ u_int64_t dqb_itime;
+ u_int32_t dqb_valid;
+};
+
+/*
+ * Structure used for setting quota information about file via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define IIF_BGRACE 1
+#define IIF_IGRACE 2
+#define IIF_FLAGS 4
+#define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
+
+struct if_dqinfo {
+ u_int64_t dqi_bgrace;
+ u_int64_t dqi_igrace;
+ u_int32_t dqi_flags;
+ u_int32_t dqi_valid;
+};
+
+/* Quota format identifiers */
+#define QFMT_VFS_OLD 1
+#define QFMT_VFS_V0 2
+
+/* Flags supported by kernel */
+#define V1_DQF_RSQUASH 1
+
+/* Ioctl for getting quota size */
+#include <sys/ioctl.h>
+#ifndef FIOQSIZE
+ #if defined(__alpha__) || defined(__powerpc__) || defined(__sh__) || defined(__sparc__) || defined(__sparc64__)
+ #define FIOQSIZE _IOR('f', 128, loff_t)
+ #elif defined(__arm__) || defined(__mc68000__) || defined(__s390__)
+ #define FIOQSIZE 0x545E
+ #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__ia64__) || defined(__parisc__) || defined(__cris__) || defined(__hppa__)
+ #define FIOQSIZE 0x5460
+ #elif defined(__mips__) || defined(__mips64__)
+ #define FIOQSIZE 0x6667
+ #endif
+#endif
+
+long quotactl __P((int, const char *, qid_t, caddr_t));
+
+#endif /* _QUOTA_LINUX */
+
+#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
+#define V2_DQBLKSIZE_BITS 10
+#define V2_DQBLKSIZE (1 << V2_DQBLKSIZE_BITS) /* Size of block with quota structures */
+#define V2_DQTREEOFF 1 /* Offset of tree in file in blOcks */
+#define V2_DQTREEDEPTH 4 /* Depth of quota tree */
+#define V2_DQSTRINBLK ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk)) /* Number of entries in one blocks */
+#define V2_GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
+#define V2_GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)(buf)) + sizeof(struct v2_disk_dqdbheader)))
+#define INIT_V2_VERSIONS { 0, 0}
+
+struct v2_disk_dqheader {
+ u_int32_t dqh_magic; /* Magic number identifying file */
+ u_int32_t dqh_version; /* File version */
+} __attribute__ ((packed));
+
+/* Flags for version specific files */
+#define V2_DQF_MASK 0x0000 /* Mask for all valid ondisk flags */
+
+/* Header with type and version specific information */
+struct v2_disk_dqinfo {
+ u_int32_t dqi_bgrace; /* Time before block soft limit becomes hard limit */
+ u_int32_t dqi_igrace; /* Time before inode soft limit becomes hard limit */
+ u_int32_t dqi_flags; /* Flags for quotafile (DQF_*) */
+ u_int32_t dqi_blocks; /* Number of blocks in file */
+ u_int32_t dqi_free_blk; /* Number of first free block in the list */
+ u_int32_t dqi_free_entry; /* Number of block with at least one free entry */
+} __attribute__ ((packed));
+
+/*
+ * Structure of header of block with quota structures. It is padded to 16 bytes so
+ * there will be space for exactly 18 quota-entries in a block
+ */
+struct v2_disk_dqdbheader {
+ u_int32_t dqdh_next_free; /* Number of next block with free entry */
+ u_int32_t dqdh_prev_free; /* Number of previous block with free entry */
+ u_int16_t dqdh_entries; /* Number of valid entries in block */
+ u_int16_t dqdh_pad1;
+ u_int32_t dqdh_pad2;
+} __attribute__ ((packed));
+
+/* Structure of quota for one user on disk */
+struct v2_disk_dqblk {
+ u_int32_t dqb_id; /* id this quota applies to */
+ u_int32_t dqb_ihardlimit; /* absolute limit on allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+ u_int64_t dqb_curspace; /* current space occupied (in bytes) */
+ u_int64_t dqb_btime; /* time limit for excessive disk use */
+ u_int64_t dqb_itime; /* time limit for excessive inode use */
+} __attribute__ ((packed));
+
+/* Structure of quota for communication with kernel */
+struct v2_kern_dqblk {
+ unsigned int dqb_ihardlimit;
+ unsigned int dqb_isoftlimit;
+ unsigned int dqb_curinodes;
+ unsigned int dqb_bhardlimit;
+ unsigned int dqb_bsoftlimit;
+ qsize_t dqb_curspace;
+ time_t dqb_btime;
+ time_t dqb_itime;
+};
+
+/* Structure of quotafile info for communication with kernel */
+struct v2_kern_dqinfo {
+ unsigned int dqi_bgrace;
+ unsigned int dqi_igrace;
+ unsigned int dqi_flags;
+ unsigned int dqi_blocks;
+ unsigned int dqi_free_blk;
+ unsigned int dqi_free_entry;
+};
+
+/* Structure with gathered statistics from kernel */
+struct v2_dqstats {
+ u_int32_t lookups;
+ u_int32_t drops;
+ u_int32_t reads;
+ u_int32_t writes;
+ u_int32_t cache_hits;
+ u_int32_t allocated_dquots;
+ u_int32_t free_dquots;
+ u_int32_t syncs;
+ u_int32_t version;
+};
+
+#ifndef Q_V2_GETQUOTA
+#define Q_V2_GETQUOTA 0x0D00
+#endif
+#ifndef Q_V2_SETQUOTA
+#define Q_V2_SETQUOTA 0x0E00
+#endif
+
+#endif /* _QUOTAIO_LINUX_V2 */
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE 1024
+#endif
+
+#endif /* _SAMBA_LINUX_QUOTA_H_ */
diff --git a/source3/include/samba_xfs_quota.h b/source3/include/samba_xfs_quota.h
new file mode 100644
index 0000000000..1db435064a
--- /dev/null
+++ b/source3/include/samba_xfs_quota.h
@@ -0,0 +1,165 @@
+#ifndef _SAMBA_LINUX_XFS_H_
+#define _SAMBA_LINUX_XFS_H_
+
+#ifndef _QUOTAIO_LINUX_XFS
+#define _QUOTAIO_LINUX_XFS
+
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/types.h>
+
+#define XQM_CMD(cmd) ( ('X'<<8)+(cmd) )
+#define IS_XQM_CMD(cmd) ( ((int)(cmd)>>8) == 'X' )
+
+/*
+ * Disk quota - quotactl(2) commands for XFS Quota Manager (XQM).
+ */
+#define Q_XQUOTAON XQM_CMD(0x1) /* enable quota accounting/enforcement */
+#define Q_XQUOTAOFF XQM_CMD(0x2) /* disable quota accounting/enforcement */
+#define Q_XGETQUOTA XQM_CMD(0x3) /* get disk limits & usage */
+#define Q_XSETQLIM XQM_CMD(0x4) /* set disk limits only */
+#define Q_XGETQSTAT XQM_CMD(0x5) /* returns fs_quota_stat_t struct */
+#define Q_XQUOTARM XQM_CMD(0x6) /* free quota files' space */
+
+/*
+ * fs_disk_quota structure:
+ *
+ * This contains the current quota information regarding a user/proj/group.
+ * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of
+ * 512 bytes.
+ */
+#define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */
+typedef struct fs_disk_quota {
+ u_int8_t d_version; /* version of this structure */
+ u_int8_t d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */
+ u_int16_t d_fieldmask; /* field specifier */
+ u_int32_t d_id; /* user, project, or group ID */
+ u_int64_t d_blk_hardlimit; /* absolute limit on disk blks */
+ u_int64_t d_blk_softlimit; /* preferred limit on disk blks */
+ u_int64_t d_ino_hardlimit; /* maximum # allocated inodes */
+ u_int64_t d_ino_softlimit; /* preferred inode limit */
+ u_int64_t d_bcount; /* # disk blocks owned by the user */
+ u_int64_t d_icount; /* # inodes owned by the user */
+ int32_t d_itimer; /* zero if within inode limits */
+ /* if not, we refuse service */
+ int32_t d_btimer; /* similar to above; for disk blocks */
+ u_int16_t d_iwarns; /* # warnings issued wrt num inodes */
+ u_int16_t d_bwarns; /* # warnings issued wrt disk blocks */
+ int32_t d_padding2; /* padding2 - for future use */
+ u_int64_t d_rtb_hardlimit; /* absolute limit on realtime blks */
+ u_int64_t d_rtb_softlimit; /* preferred limit on RT disk blks */
+ u_int64_t d_rtbcount; /* # realtime blocks owned */
+ int32_t d_rtbtimer; /* similar to above; for RT disk blks */
+ u_int16_t d_rtbwarns; /* # warnings issued wrt RT disk blks */
+ int16_t d_padding3; /* padding3 - for future use */
+ char d_padding4[8]; /* yet more padding */
+} fs_disk_quota_t;
+
+/*
+ * These fields are sent to Q_XSETQLIM to specify fields that need to change.
+ */
+#define FS_DQ_ISOFT (1<<0)
+#define FS_DQ_IHARD (1<<1)
+#define FS_DQ_BSOFT (1<<2)
+#define FS_DQ_BHARD (1<<3)
+#define FS_DQ_RTBSOFT (1<<4)
+#define FS_DQ_RTBHARD (1<<5)
+#define FS_DQ_LIMIT_MASK (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \
+ FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD)
+/*
+ * These timers can only be set in super user's dquot. For others, timers are
+ * automatically started and stopped. Superusers timer values set the limits
+ * for the rest. In case these values are zero, the DQ_{F,B}TIMELIMIT values
+ * defined below are used.
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BTIMER (1<<6)
+#define FS_DQ_ITIMER (1<<7)
+#define FS_DQ_RTBTIMER (1<<8)
+#define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
+
+/*
+ * The following constants define the default amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure). These may be modified by the quotactl(2)
+ * system call with the Q_XSETQLIM command.
+ */
+#define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */
+#define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */
+
+/*
+ * Various flags related to quotactl(2). Only relevant to XFS filesystems.
+ */
+#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */
+#define XFS_QUOTA_UDQ_ENFD (1<<1) /* user quota limits enforcement */
+#define XFS_QUOTA_GDQ_ACCT (1<<2) /* group quota accounting */
+#define XFS_QUOTA_GDQ_ENFD (1<<3) /* group quota limits enforcement */
+
+#define XFS_USER_QUOTA (1<<0) /* user quota type */
+#define XFS_PROJ_QUOTA (1<<1) /* (IRIX) project quota type */
+#define XFS_GROUP_QUOTA (1<<2) /* group quota type */
+
+/*
+ * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system.
+ * Provides a centralized way to get meta infomation about the quota subsystem.
+ * eg. space taken up for user and group quotas, number of dquots currently
+ * incore.
+ */
+#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */
+
+/*
+ * Some basic infomation about 'quota files'.
+ */
+typedef struct fs_qfilestat {
+ u_int64_t qfs_ino; /* inode number */
+ u_int64_t qfs_nblks; /* number of BBs 512-byte-blks */
+ u_int32_t qfs_nextents; /* number of extents */
+} fs_qfilestat_t;
+
+typedef struct fs_quota_stat {
+ u_int8_t qs_version; /* version number for future changes */
+ u_int16_t qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
+ u_int8_t qs_pad; /* unused */
+ fs_qfilestat_t qs_uquota; /* user quota storage information */
+ fs_qfilestat_t qs_gquota; /* group quota storage information */
+ u_int32_t qs_incoredqs; /* number of dquots incore */
+ int32_t qs_btimelimit; /* limit for blks timer */
+ int32_t qs_itimelimit; /* limit for inodes timer */
+ int32_t qs_rtbtimelimit; /* limit for rt blks timer */
+ u_int16_t qs_bwarnlimit; /* limit for num warnings */
+ u_int16_t qs_iwarnlimit; /* limit for num warnings */
+} fs_quota_stat_t;
+
+#endif /* _QUOTAIO_LINUX_XFS */
+
+#endif /* _SAMBA_LINUX_XFS_H_ */
diff --git a/source3/include/sysquotas.h b/source3/include/sysquotas.h
index b803e6277a..bfb9466b39 100644
--- a/source3/include/sysquotas.h
+++ b/source3/include/sysquotas.h
@@ -23,150 +23,6 @@
#ifdef HAVE_SYS_QUOTAS
-/* Sometimes we need this on linux for linux/quota.h */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-/*
- * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
- */
-#ifdef HAVE_LINUX_QUOTA_H
-#include <linux/quota.h>
-#elif defined(HAVE_SYS_QUOTA_H)
-#include <sys/quota.h>
-#endif
-
-#if defined(HAVE_STRUCT_IF_DQBLK)
-# define SYS_DQBLK if_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#elif defined(HAVE_STRUCT_MEM_DQBLK)
-# define SYS_DQBLK mem_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#else /* STRUCT_DQBLK */
-# define SYS_DQBLK dqblk
-#endif
-
-#ifndef Q_SETQLIM
-#define Q_SETQLIM Q_SETQUOTA
-#endif
-
-/*********************************************
- check for XFS QUOTA MANAGER
- *********************************************/
-/* on linux */
-#ifdef HAVE_LINUX_XQM_H
-# include <linux/xqm.h>
-# define HAVE_XFS_QUOTA
-#else
-# ifdef HAVE_XFS_XQM_H
-# include <xfs/xqm.h>
-# define HAVE_XFS_QUOTA
-# else
-# ifdef HAVE_LINUX_DQBLK_XFS_H
-# include <linux/dqblk_xfs.h>
-# define HAVE_XFS_QUOTA
-# endif
-# endif
-#endif
-/* on IRIX */
-#ifdef Q_XGETQUOTA
-# ifndef HAVE_XFS_QUOTA
-# define HAVE_XFS_QUOTA
-# ifndef Q_XQUOTAON
-# define Q_XQUOTAON Q_QUOTAON
-# endif /* Q_XQUOTAON */
-# ifndef Q_XQUOTAOFF
-# define Q_XQUOTAOFF Q_QUOTAOFF
-# endif /* Q_XQUOTAOFF */
-# ifndef Q_XGETQSTAT
-# define Q_XGETQSTAT Q_GETQSTAT
-# endif /* Q_XGETQSTAT */
-# endif /* HAVE_XFS_QUOTA */
-#endif /* Q_XGETQUOTA */
-
-#ifdef HAVE_XFS_QUOTA
-/* Linux has BBSIZE in <linux/xfs_fs.h>
- * or <xfs/xfs_fs.h>
- * IRIX has BBSIZE in <sys/param.h>
- */
-#ifdef HAVE_LINUX_XFS_FS_H
-#include <linux/xfs_fs.h>
-#elif defined(HAVE_XFS_XFS_FS_H)
-#include <xfs/xfs_fs.h>
-#endif /* *_XFS_FS_H */
-
-#ifndef BBSHIFT
-#define BBSHIFT 9
-#endif /* BBSHIFT */
-#ifndef BBSIZE
-#define BBSIZE (1<<BBSHIFT)
-#endif /* BBSIZE */
-
-#endif /* HAVE_XFS_QUOTA */
-
-#ifdef LINUX
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE 1024
-# endif
-/* end LINUX */
-#elif defined(IRIX6)
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE BBSIZE
-# endif
-/* end IRIX6 */
-#else /* HPUP,... */
-# ifndef QUOTABLOCK_SIZE
-# define QUOTABLOCK_SIZE DEV_BSIZE
-# endif
-#endif /* HPUP,... */
-
-#if !defined(QUOTAFILENAME) && defined(QFILENAME)
-#define QUOTAFILENAME QFILENAME
-#endif
-
-#ifdef INITQFNAMES
-#define USERQUOTAFILE_EXTENSION ".user"
-#else
-#define USERQUOTAFILE_EXTENSION ""
-#endif
-
-/* this check should be before the QCMD fake! */
-#if defined(QCMD)&&defined(GRPQUOTA)
-#define HAVE_GROUP_QUOTA
-#endif
-
-/* on some systems we have to fake this up ...*/
-#ifndef QCMD
-#define QCMD(cmd,type) (cmd)
-#endif /* QCMD */
-
-
-#ifdef HAVE_DQB_FSOFTLIMIT
-#define dqb_isoftlimit dqb_fsoftlimit
-#define dqb_ihardlimit dqb_fhardlimit
-#define dqb_curinodes dqb_curfiles
-#endif
-
-/* maybe we can add a configure test for HAVE_CADDR_T,
- * but it's not needed
- */
-#ifdef HAVE_CADDR_T
-#define CADDR_T caddr_t
-#else /* CADDR_T */
-#define CADDR_T void*
-#endif /* CADDR_T */
-
#if defined(HAVE_MNTENT_H)&&defined(HAVE_SETMNTENT)&&defined(HAVE_GETMNTENT)&&defined(HAVE_ENDMNTENT)
#include <mntent.h>
#define HAVE_MNTENT 1
@@ -178,10 +34,6 @@
#endif /* HAVE_SYS_QUOTAS */
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
-
/**************************************************
Some stuff for the sys_quota api.
**************************************************/
@@ -217,4 +69,8 @@ typedef struct _SMB_DISK_QUOTA {
uint32 qflags;
} SMB_DISK_QUOTA;
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE 1024
+#endif
+
#endif /*_SYSQUOTAS_H */
diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c
index b98e5734cb..fe2ad5b2fc 100644
--- a/source3/intl/lang_tdb.c
+++ b/source3/intl/lang_tdb.c
@@ -176,7 +176,8 @@ BOOL lang_tdb_init(const char *lang)
const char *lang_msg(const char *msgid)
{
TDB_DATA key, data;
- char *p, *q, *msgid_quoted;
+ const char *p;
+ char *q, *msgid_quoted;
int count;
lang_tdb_init(NULL);
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index 7903dfd3f6..1c6058a43e 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -192,7 +192,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
i_len=srclen;
o_len=destlen;
- retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
+ retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
if(retval==(size_t)-1) {
const char *reason="unknown error";
switch(errno) {
@@ -426,7 +426,7 @@ convert:
i_len = srclen;
o_len = destlen;
retval = smb_iconv(descriptor,
- &inbuf, &i_len,
+ (char **)&inbuf, &i_len,
&outbuf, &o_len);
if(retval == (size_t)-1) {
const char *reason="unknown error";
diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c
index 3223ecb580..6883444e00 100644
--- a/source3/lib/sysquotas.c
+++ b/source3/lib/sysquotas.c
@@ -24,255 +24,6 @@
#ifdef HAVE_SYS_QUOTAS
#if defined(HAVE_QUOTACTL_4A)
-/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
-/* this is used by: linux,HPUX,IRIX */
-
-/****************************************************************************
- Abstract out the old and new Linux quota get calls.
-****************************************************************************/
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- struct SYS_DQBLK D;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(D);
- ZERO_STRUCT(*dp);
- dp->qtype = qtype;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
- return ret;
- }
-
- if ((D.dqb_curblocks==0)&&
- (D.dqb_bsoftlimit==0)&&
- (D.dqb_bhardlimit==0)) {
- /* the upper layer functions don't want empty quota records...*/
- return -1;
- }
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
- return ret;
- }
-
- if ((D.dqb_curblocks==0)&&
- (D.dqb_bsoftlimit==0)&&
- (D.dqb_bhardlimit==0)) {
- /* the upper layer functions don't want empty quota records...*/
- return -1;
- }
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- id.uid = getuid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
- qflags |= QUOTAS_DENY_DISK;
- }
-
- ret = 0;
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- id.gid = getgid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
- qflags |= QUOTAS_DENY_DISK;
- }
-
- ret = 0;
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- dp->bsize = bsize;
- dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
- dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
- dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
- dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
- dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
- dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-
-
- dp->qflags = qflags;
-
- return ret;
-}
-
-/****************************************************************************
- Abstract out the old and new Linux quota set calls.
-****************************************************************************/
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- uint32 oldqflags = 0;
- struct SYS_DQBLK D;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(D);
-
- if (bsize == dp->bsize) {
- D.dqb_bsoftlimit = dp->softlimit;
- D.dqb_bhardlimit = dp->hardlimit;
- D.dqb_ihardlimit = dp->ihardlimit;
- D.dqb_isoftlimit = dp->isoftlimit;
- } else {
- D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
- D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
- D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
- D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
- }
-
- qflags = dp->qflags;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- /* this stuff didn't work as it should:
- * switching on/off quota via quotactl()
- * didn't work!
- * So we just return 0
- * --metze
- *
- * On HPUX we didn't have the mount path,
- * we need to fix sys_path_to_bdev()
- *
- */
-#if 0
- id.uid = getuid();
-
- ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-
- if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
- if (ret == 0) {
- char *quota_file = NULL;
-
- asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
- if (quota_file == NULL) {
- DEBUG(0,("asprintf() failed!\n"));
- errno = ENOMEM;
- return -1;
- }
-
- ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
- } else {
- ret = 0;
- }
- } else {
- if (ret != 0) {
- /* turn off */
- ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);
- } else {
- ret = 0;
- }
- }
-
- DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
- ret,errno,strerror(errno),id.uid,bdev));
-#else
- id.uid = getuid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
- oldqflags |= QUOTAS_DENY_DISK;
- }
-
- if (oldqflags == qflags) {
- ret = 0;
- } else {
- ret = -1;
- }
-#endif
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- /* this stuff didn't work as it should:
- * switching on/off quota via quotactl()
- * didn't work!
- * So we just return 0
- * --metze
- *
- * On HPUX we didn't have the mount path,
- * we need to fix sys_path_to_bdev()
- *
- */
-#if 0
- id.gid = getgid();
-
- ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D);
-
- if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
- if (ret == 0) {
- char *quota_file = NULL;
-
- asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
- if (quota_file == NULL) {
- DEBUG(0,("asprintf() failed!\n"));
- errno = ENOMEM;
- return -1;
- }
-
- ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file);
- } else {
- ret = 0;
- }
- } else {
- if (ret != 0) {
- /* turn off */
- ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0);
- } else {
- ret = 0;
- }
- }
-
- DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
- ret,errno,strerror(errno),id.gid,bdev));
-#else
- id.gid = getgid();
-
- if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
- oldqflags |= QUOTAS_DENY_DISK;
- }
-
- if (oldqflags == qflags) {
- ret = 0;
- } else {
- ret = -1;
- }
-#endif
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- return ret;
-}
/*#endif HAVE_QUOTACTL_4A */
#elif defined(HAVE_QUOTACTL_4B)
@@ -287,30 +38,6 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_
/* #endif HAVE_QUOTACTL_3 */
#else /* NO_QUOTACTL_USED */
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
- errno = ENOSYS;
-
- return ret;
-}
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
-
- if (!path||!bdev||!dp)
- smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
- errno = ENOSYS;
-
- return ret;
-}
-
#endif /* NO_QUOTACTL_USED */
#ifdef HAVE_MNTENT
@@ -434,262 +161,6 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
}
#endif
-
-/*********************************************************
- if we have XFS QUOTAS we should use them
- *********************************************************/
-#ifdef HAVE_XFS_QUOTA
-/****************************************************************************
- Abstract out the XFS Quota Manager quota get call.
-****************************************************************************/
-static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
- struct fs_disk_quota D;
- struct fs_quota_stat F;
- ZERO_STRUCT(D);
- ZERO_STRUCT(F);
-
- if (!bdev||!dp)
- smb_panic("sys_get_xfs_quota: called with NULL pointer");
-
- ZERO_STRUCT(*dp);
- dp->qtype = qtype;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
- return ret;
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
- return ret;
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
- qflags |= QUOTAS_DENY_DISK;
- }
- else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
- qflags |= QUOTAS_ENABLED;
- }
-
- ret = 0;
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
- qflags |= QUOTAS_DENY_DISK;
- }
- else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
- qflags |= QUOTAS_ENABLED;
- }
-
- ret = 0;
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- dp->bsize = bsize;
- dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
- dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
- dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
- dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
- dp->curinodes = (SMB_BIG_UINT)D.d_icount;
- dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
- dp->qflags = qflags;
-
- return ret;
-}
-
-/****************************************************************************
- Abstract out the XFS Quota Manager quota set call.
-****************************************************************************/
-static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
- int ret = -1;
- uint32 qflags = 0;
- SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
- struct fs_disk_quota D;
- struct fs_quota_stat F;
- int q_on = 0;
- int q_off = 0;
- ZERO_STRUCT(D);
- ZERO_STRUCT(F);
-
- if (!bdev||!dp)
- smb_panic("sys_set_xfs_quota: called with NULL pointer");
-
- if (bsize == dp->bsize) {
- D.d_blk_softlimit = dp->softlimit;
- D.d_blk_hardlimit = dp->hardlimit;
- D.d_ino_hardlimit = dp->ihardlimit;
- D.d_ino_softlimit = dp->isoftlimit;
- } else {
- D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
- D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
- D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
- D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;
- }
-
- qflags = dp->qflags;
-
- switch (qtype) {
- case SMB_USER_QUOTA_TYPE:
- D.d_fieldmask |= FS_DQ_LIMIT_MASK;
- ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_QUOTA_TYPE:
- D.d_fieldmask |= FS_DQ_LIMIT_MASK;
- ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
- break;
-#endif /* HAVE_GROUP_QUOTA */
- case SMB_USER_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (qflags & QUOTAS_DENY_DISK) {
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
- q_on |= XFS_QUOTA_UDQ_ENFD;
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
-
- } else if (qflags & QUOTAS_ENABLED) {
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
-
- if (q_off != 0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
- } else {
-#if 0
- /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
- * only swittching off XFS_QUOTA_UDQ_ACCT work
- */
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
- if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
- q_off |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_off !=0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-#else
- ret = -1;
-#endif
- }
-
- break;
-#ifdef HAVE_GROUP_QUOTA
- case SMB_GROUP_FS_QUOTA_TYPE:
- quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
- if (qflags & QUOTAS_DENY_DISK) {
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
- q_on |= XFS_QUOTA_UDQ_ENFD;
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
-
- } else if (qflags & QUOTAS_ENABLED) {
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
-
- if (q_off != 0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-
- if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
- q_on |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_on != 0) {
- ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
- } else {
- ret = 0;
- }
- } else {
-#if 0
- /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
- * only swittching off XFS_QUOTA_UDQ_ACCT work
- */
- if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
- q_off |= XFS_QUOTA_UDQ_ENFD;
- if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
- q_off |= XFS_QUOTA_UDQ_ACCT;
-
- if (q_off !=0) {
- ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
- } else {
- ret = 0;
- }
-#else
- ret = -1;
-#endif
- }
-
- break;
-#endif /* HAVE_GROUP_QUOTA */
- default:
- errno = ENOSYS;
- return -1;
- }
-
- return ret;
-}
-#endif /* HAVE_XFS_QUOTA */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*********************************************************************
Now the list of all filesystem specific quota systems we have found
**********************************************************************/
diff --git a/source3/lib/sysquotas_4A.c b/source3/lib/sysquotas_4A.c
new file mode 100644
index 0000000000..66b367f099
--- /dev/null
+++ b/source3/lib/sysquotas_4A.c
@@ -0,0 +1,318 @@
+/*
+ Unix SMB/CIFS implementation.
+ System QUOTA function wrappers for QUOTACTL_4A
+ Copyright (C) Stefan (metze) Metzmacher 2003
+
+ 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.
+*/
+
+
+#include "includes.h"
+
+#ifdef HAVE_QUOTACTL_4A
+/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
+/* this is used by: HPUX,IRIX */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_QUOTA_H
+#include <sys/quota.h>
+#endif
+
+#ifndef Q_SETQLIM
+#define Q_SETQLIM Q_SETQUOTA
+#endif
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+#ifdef GRPQUOTA
+#define HAVE_GROUP_QUOTA
+#endif
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE DEV_BSIZE
+#endif
+
+#ifdef HAVE_DQB_FSOFTLIMIT
+#define dqb_isoftlimit dqb_fsoftlimit
+#define dqb_ihardlimit dqb_fhardlimit
+#define dqb_curinodes dqb_curfiles
+#endif
+
+#ifdef INITQFNAMES
+#define USERQUOTAFILE_EXTENSION ".user"
+#else
+#define USERQUOTAFILE_EXTENSION ""
+#endif
+
+#if !defined(QUOTAFILENAME) && defined(QFILENAME)
+#define QUOTAFILENAME QFILENAME
+#endif
+
+/****************************************************************************
+ Abstract out the quotactl_4A get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ struct dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+ ZERO_STRUCT(*dp);
+ dp->qtype = qtype;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ if ((D.dqb_curblocks==0)&&
+ (D.dqb_bsoftlimit==0)&&
+ (D.dqb_bhardlimit==0)) {
+ /* the upper layer functions don't want empty quota records...*/
+ return -1;
+ }
+
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ if ((D.dqb_curblocks==0)&&
+ (D.dqb_bsoftlimit==0)&&
+ (D.dqb_bhardlimit==0)) {
+ /* the upper layer functions don't want empty quota records...*/
+ return -1;
+ }
+
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ case SMB_USER_FS_QUOTA_TYPE:
+ id.uid = getuid();
+
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ ret = 0;
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ id.gid = getgid();
+
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ ret = 0;
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ dp->bsize = bsize;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+ dp->qflags = qflags;
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the quotactl_4A set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ uint32 oldqflags = 0;
+ struct dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ if (bsize == dp->bsize) {
+ D.dqb_bsoftlimit = dp->softlimit;
+ D.dqb_bhardlimit = dp->hardlimit;
+ D.dqb_ihardlimit = dp->ihardlimit;
+ D.dqb_isoftlimit = dp->isoftlimit;
+ } else {
+ D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+ D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+ D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+ D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+ }
+
+ qflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (void *)&D);
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (void *)&D);
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ case SMB_USER_FS_QUOTA_TYPE:
+ /* this stuff didn't work as it should:
+ * switching on/off quota via quotactl()
+ * didn't work!
+ * So we just return 0
+ * --metze
+ *
+ * On HPUX we didn't have the mount path,
+ * we need to fix sys_path_to_bdev()
+ *
+ */
+#if 0
+ id.uid = getuid();
+
+ ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D);
+
+ if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+ if (ret == 0) {
+ char *quota_file = NULL;
+
+ asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
+ if (quota_file == NULL) {
+ DEBUG(0,("asprintf() failed!\n"));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(void *)quota_file);
+ } else {
+ ret = 0;
+ }
+ } else {
+ if (ret != 0) {
+ /* turn off */
+ ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (void *)0);
+ } else {
+ ret = 0;
+ }
+ }
+
+ DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+ ret,errno,strerror(errno),id.uid,bdev));
+#else
+ id.uid = getuid();
+
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ if (oldqflags == qflags) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+#endif
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ /* this stuff didn't work as it should:
+ * switching on/off quota via quotactl()
+ * didn't work!
+ * So we just return 0
+ * --metze
+ *
+ * On HPUX we didn't have the mount path,
+ * we need to fix sys_path_to_bdev()
+ *
+ */
+#if 0
+ id.gid = getgid();
+
+ ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (void *)&D);
+
+ if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+ if (ret == 0) {
+ char *quota_file = NULL;
+
+ asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
+ if (quota_file == NULL) {
+ DEBUG(0,("asprintf() failed!\n"));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(void *)quota_file);
+ } else {
+ ret = 0;
+ }
+ } else {
+ if (ret != 0) {
+ /* turn off */
+ ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (void *)0);
+ } else {
+ ret = 0;
+ }
+ }
+
+ DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+ ret,errno,strerror(errno),id.gid,bdev));
+#else
+ id.gid = getgid();
+
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ if (oldqflags == qflags) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+#endif
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+#else /* HAVE_QUOTACTL_4A */
+ void dummy_sysquotas_4A(void){}
+#endif /* HAVE_QUOTACTL_4A */
diff --git a/source3/lib/sysquotas_linux.c b/source3/lib/sysquotas_linux.c
new file mode 100644
index 0000000000..be42fa23f4
--- /dev/null
+++ b/source3/lib/sysquotas_linux.c
@@ -0,0 +1,485 @@
+/*
+ Unix SMB/CIFS implementation.
+ System QUOTA function wrappers for LINUX
+ Copyright (C) Stefan (metze) Metzmacher 2003
+
+ 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.
+*/
+
+
+#include "includes.h"
+
+#ifdef HAVE_QUOTACTL_LINUX
+
+#include "samba_linux_quota.h"
+
+/****************************************************************************
+ Abstract out the v1 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ struct v1_kern_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ dp->bsize = bsize;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+ dp->qflags = qflags;
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the v1 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ uint32 oldqflags = 0;
+ struct v1_kern_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ if (bsize == dp->bsize) {
+ D.dqb_bsoftlimit = dp->softlimit;
+ D.dqb_bhardlimit = dp->hardlimit;
+ D.dqb_ihardlimit = dp->ihardlimit;
+ D.dqb_isoftlimit = dp->isoftlimit;
+ } else {
+ D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+ D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+ D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+ D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+ }
+
+ qflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ struct v2_kern_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ dp->bsize = bsize;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+ dp->qflags = qflags;
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ uint32 oldqflags = 0;
+ struct v2_kern_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ if (bsize == dp->bsize) {
+ D.dqb_bsoftlimit = dp->softlimit;
+ D.dqb_bhardlimit = dp->hardlimit;
+ D.dqb_ihardlimit = dp->ihardlimit;
+ D.dqb_isoftlimit = dp->isoftlimit;
+ } else {
+ D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+ D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+ D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+ D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+ }
+
+ qflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the generic Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ struct if_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+ return ret;
+ }
+
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ dp->bsize = bsize;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+ dp->qflags = qflags;
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the gen Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ uint32 oldqflags = 0;
+ struct if_dqblk D;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+ ZERO_STRUCT(D);
+
+ if (bsize == dp->bsize) {
+ D.dqb_bsoftlimit = dp->softlimit;
+ D.dqb_bhardlimit = dp->hardlimit;
+ D.dqb_ihardlimit = dp->ihardlimit;
+ D.dqb_isoftlimit = dp->isoftlimit;
+ } else {
+ D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+ D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+ D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+ D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+ }
+
+ qflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+ break;
+ case SMB_GROUP_QUOTA_TYPE:
+ ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+ oldqflags |= QUOTAS_DENY_DISK;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+
+ if (!path||!bdev||!dp)
+ smb_panic("sys_set_vfs_quota: called with NULL pointer");
+
+ ZERO_STRUCT(*dp);
+ dp->qtype = qtype;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ return ret;
+ }
+ }
+ }
+
+ if ((dp->curblocks==0)&&
+ (dp->softlimit==0)&&
+ (dp->hardlimit==0)) {
+ /* the upper layer functions don't want empty quota records...*/
+ return -1;
+ }
+
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ id.uid = getuid();
+
+ if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ }
+ }
+
+ ret = 0;
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ id.gid = getgid();
+
+ if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+ ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ }
+ }
+
+ ret = 0;
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 oldqflags = 0;
+
+ if (!path||!bdev||!dp)
+ smb_panic("sys_set_vfs_quota: called with NULL pointer");
+
+ oldqflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
+ return ret;
+ }
+ }
+ }
+ break;
+ case SMB_USER_FS_QUOTA_TYPE:
+ id.uid = getuid();
+
+ if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+ ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ }
+ }
+
+ if (oldqflags == dp->qflags) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ break;
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ id.gid = getgid();
+
+ if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+ if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+ ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+ }
+ }
+
+ if (oldqflags == dp->qflags) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+
+ break;
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+#else /* HAVE_QUOTACTL_LINUX */
+ void dummy_sysquotas_linux(void){}
+#endif /* HAVE_QUOTACTL_LINUX */
diff --git a/source3/lib/sysquotas_xfs.c b/source3/lib/sysquotas_xfs.c
new file mode 100644
index 0000000000..6d7d9f9e6a
--- /dev/null
+++ b/source3/lib/sysquotas_xfs.c
@@ -0,0 +1,306 @@
+/*
+ Unix SMB/CIFS implementation.
+ System QUOTA function wrappers for XFS
+ Copyright (C) Stefan (metze) Metzmacher 2003
+
+ 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.
+*/
+
+
+#include "includes.h"
+
+#ifndef HAVE_SYS_QUOTAS
+#ifdef HAVE_XFS_QUOTAS
+#undef HAVE_XFS_QUOTAS
+#endif
+#endif
+
+#ifdef HAVE_XFS_QUOTAS
+
+#ifdef HAVE_LINUX_XFS_QUOTAS
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
+#define HAVE_GROUP_QUOTA
+#else /* IRIX */
+#include <sys/quota.h>
+#endif
+
+/* on IRIX */
+#ifndef Q_XQUOTAON
+#define Q_XQUOTAON Q_QUOTAON
+#endif /* Q_XQUOTAON */
+#ifndef Q_XQUOTAOFF
+#define Q_XQUOTAOFF Q_QUOTAOFF
+#endif /* Q_XQUOTAOFF */
+#ifndef Q_XGETQSTAT
+#define Q_XGETQSTAT Q_GETQSTAT
+#endif /* Q_XGETQSTAT */
+
+/* currently doesn't support Group and Project quotas on IRIX
+ */
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+/*
+ * IRIX has BBSIZE in <sys/param.h>
+ */
+#ifndef BBSHIFT
+#define BBSHIFT 9
+#endif /* BBSHIFT */
+#ifndef BBSIZE
+#define BBSIZE (1<<BBSHIFT)
+#endif /* BBSIZE */
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota get call.
+****************************************************************************/
+int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+ struct fs_disk_quota D;
+ struct fs_quota_stat F;
+ ZERO_STRUCT(D);
+ ZERO_STRUCT(F);
+
+ if (!bdev||!dp)
+ smb_panic("sys_get_xfs_quota: called with NULL pointer");
+
+ ZERO_STRUCT(*dp);
+ dp->qtype = qtype;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D)))
+ return ret;
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_QUOTA_TYPE:
+ if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D)))
+ return ret;
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ case SMB_USER_FS_QUOTA_TYPE:
+ quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+
+ if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+ else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
+ qflags |= QUOTAS_ENABLED;
+ }
+
+ ret = 0;
+
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+
+ if (F.qs_flags & XFS_QUOTA_GDQ_ENFD) {
+ qflags |= QUOTAS_DENY_DISK;
+ }
+ else if (F.qs_flags & XFS_QUOTA_GDQ_ACCT) {
+ qflags |= QUOTAS_ENABLED;
+ }
+
+ ret = 0;
+
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ dp->bsize = bsize;
+ dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.d_icount;
+ dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
+ dp->qflags = qflags;
+
+ return ret;
+}
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota set call.
+****************************************************************************/
+int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+ int ret = -1;
+ uint32 qflags = 0;
+ SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+ struct fs_disk_quota D;
+ struct fs_quota_stat F;
+ int q_on = 0;
+ int q_off = 0;
+ ZERO_STRUCT(D);
+ ZERO_STRUCT(F);
+
+ if (!bdev||!dp)
+ smb_panic("sys_set_xfs_quota: called with NULL pointer");
+
+ if (bsize == dp->bsize) {
+ D.d_blk_softlimit = dp->softlimit;
+ D.d_blk_hardlimit = dp->hardlimit;
+ D.d_ino_hardlimit = dp->ihardlimit;
+ D.d_ino_softlimit = dp->isoftlimit;
+ } else {
+ D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
+ D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
+ D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+ D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;
+ }
+
+ qflags = dp->qflags;
+
+ switch (qtype) {
+ case SMB_USER_QUOTA_TYPE:
+ D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+ ret = quotactl(QCMD(Q_XSETQLIM,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D);
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_QUOTA_TYPE:
+ D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+ ret = quotactl(QCMD(Q_XSETQLIM,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D);
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ case SMB_USER_FS_QUOTA_TYPE:
+ quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+
+ if (qflags & QUOTAS_DENY_DISK) {
+ if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
+ q_on |= XFS_QUOTA_UDQ_ENFD;
+ if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+ q_on |= XFS_QUOTA_UDQ_ACCT;
+
+ if (q_on != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+ } else {
+ ret = 0;
+ }
+
+ } else if (qflags & QUOTAS_ENABLED) {
+ if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+ q_off |= XFS_QUOTA_UDQ_ENFD;
+
+ if (q_off != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+ } else {
+ ret = 0;
+ }
+
+ if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+ q_on |= XFS_QUOTA_UDQ_ACCT;
+
+ if (q_on != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+ } else {
+ ret = 0;
+ }
+ } else {
+#if 0
+ /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+ * only swittching off XFS_QUOTA_UDQ_ACCT work
+ */
+ if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+ q_off |= XFS_QUOTA_UDQ_ENFD;
+ if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
+ q_off |= XFS_QUOTA_UDQ_ACCT;
+
+ if (q_off !=0) {
+ ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+ } else {
+ ret = 0;
+ }
+#else
+ ret = -1;
+#endif
+ }
+
+ break;
+#ifdef HAVE_GROUP_QUOTA
+ case SMB_GROUP_FS_QUOTA_TYPE:
+ quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+
+ if (qflags & QUOTAS_DENY_DISK) {
+ if (!(F.qs_flags & XFS_QUOTA_GDQ_ENFD))
+ q_on |= XFS_QUOTA_GDQ_ENFD;
+ if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT))
+ q_on |= XFS_QUOTA_GDQ_ACCT;
+
+ if (q_on != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+ } else {
+ ret = 0;
+ }
+
+ } else if (qflags & QUOTAS_ENABLED) {
+ if (F.qs_flags & XFS_QUOTA_GDQ_ENFD)
+ q_off |= XFS_QUOTA_GDQ_ENFD;
+
+ if (q_off != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+ } else {
+ ret = 0;
+ }
+
+ if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT))
+ q_on |= XFS_QUOTA_GDQ_ACCT;
+
+ if (q_on != 0) {
+ ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+ } else {
+ ret = 0;
+ }
+ } else {
+#if 0
+ /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+ * only swittching off XFS_QUOTA_UDQ_ACCT work
+ */
+ if (F.qs_flags & XFS_QUOTA_GDQ_ENFD)
+ q_off |= XFS_QUOTA_GDQ_ENFD;
+ if (F.qs_flags & XFS_QUOTA_GDQ_ACCT)
+ q_off |= XFS_QUOTA_GDQ_ACCT;
+
+ if (q_off !=0) {
+ ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+ } else {
+ ret = 0;
+ }
+#else
+ ret = -1;
+#endif
+ }
+
+ break;
+#endif /* HAVE_GROUP_QUOTA */
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+
+ return ret;
+}
+
+#else /* HAVE_XFS_QUOTAS */
+ void dummy_sysquotas_xfs(void){}
+#endif /* HAVE_XFS_QUOTAS */
diff --git a/source3/lib/talloctort.c b/source3/lib/talloctort.c
index ad5de38581..0cdf693bb9 100644
--- a/source3/lib/talloctort.c
+++ b/source3/lib/talloctort.c
@@ -51,9 +51,9 @@ int main(void)
}
for (i = 0; i < NCTX; i++) {
- printf("talloc@%p %-40s %dkB\n", ctx[i],
+ printf("talloc@%p %-40s %ldkB\n", ctx[i],
talloc_pool_name(ctx[i]),
- talloc_pool_size(ctx[i]) >> 10);
+ (unsigned long)talloc_pool_size(ctx[i]) >> 10);
}
printf("%s", talloc_describe_all(ctx[0]));
diff --git a/source3/lib/time.c b/source3/lib/time.c
index 635ede9be2..faca2cba87 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -465,10 +465,9 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
nt->low=~nt->low;
}
-
/****************************************************************************
-take an NTTIME structure, containing high / low time. convert to unix time.
-lkclXXXX this may need 2 SIVALs not a memcpy. we'll see...
+take a Unix time and convert to an NTTIME structure and place in buffer
+pointed to by p.
****************************************************************************/
void put_long_date(char *p,time_t t)
{
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index f552b38e67..d93f39696f 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -697,7 +697,7 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
if (!dest) {
DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
- return NULL;
+ return(NULL);
}
if (!src) {
@@ -1196,7 +1196,7 @@ char *strchr_m(const char *src, char c)
for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
if (*s == c)
- return s;
+ return (char *)s;
}
if (!*s)
@@ -1244,7 +1244,7 @@ char *strrchr_m(const char *s, char c)
break;
}
/* No - we have a match ! */
- return cp;
+ return (char *)cp;
}
} while (cp-- != s);
if (!got_mb)
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 5122803597..1ab71c6ee5 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -124,13 +124,13 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
{
DATA_BLOB blob;
struct berval cred, *scred;
- unsigned char sk[16];
+ DATA_BLOB session_key;
int rc;
- blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, sk);
+ rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key);
- if (!blob.data) {
- return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+ if (rc) {
+ return ADS_ERROR_KRB5(rc);
}
/* now send the auth packet and we should be done */
@@ -140,6 +140,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
data_blob_free(&blob);
+ data_blob_free(&session_key);
return ADS_ERROR(rc);
}
@@ -166,6 +167,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
blob = data_blob(scred->bv_val, scred->bv_len);
+ ber_bvfree(scred);
+
#if 0
file_save("sasl_spnego.dat", blob.data, blob.length);
#endif
@@ -196,9 +199,13 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
status = ads_sasl_spnego_krb5_bind(ads, principal);
if (ADS_ERR_OK(status))
return status;
- if (ads_kinit_password(ads) == 0) {
+
+ status = ADS_ERROR_KRB5(ads_kinit_password(ads));
+
+ if (ADS_ERR_OK(status)) {
status = ads_sasl_spnego_krb5_bind(ads, principal);
}
+
/* only fallback to NTLMSSP if allowed */
if (ADS_ERR_OK(status) ||
!(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 28de7fc9f3..707a33881d 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -53,6 +53,13 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
if (passlen > sizeof(pword)-1)
return False;
+ /* LANMAN servers predate NT status codes and Unicode and ignore those
+ smb flags so we must disable the corresponding default capabilities
+ that would otherwise cause the Unicode and NT Status flags to be
+ set (and even returned by the server) */
+
+ cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
+
/* if in share level security then don't send a password now */
if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
passlen = 0;
@@ -493,19 +500,22 @@ static void use_in_memory_ccache(void) {
Do a spnego/kerberos encrypted session setup.
****************************************************************************/
-static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
+static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
{
DATA_BLOB blob2, negTokenTarg;
DATA_BLOB session_key_krb5;
DATA_BLOB null_blob = data_blob(NULL, 0);
-
+ int rc;
+
DEBUG(2,("Doing kerberos session setup\n"));
/* generate the encapsulated kerberos5 ticket */
- negTokenTarg = spnego_gen_negTokenTarg(principal, 0, &session_key_krb5);
+ rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
- if (!negTokenTarg.data)
- return NT_STATUS_UNSUCCESSFUL;
+ if (rc) {
+ DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
+ return ADS_ERROR_KRB5(rc);
+ }
#if 0
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
@@ -524,10 +534,10 @@ static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *pr
if (cli_is_error(cli)) {
if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
- return NT_STATUS_UNSUCCESSFUL;
+ return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
}
- return NT_STATUS_OK;
+ return ADS_ERROR_NT(cli_nt_error(cli));
}
#endif /* HAVE_KRB5 */
@@ -537,7 +547,7 @@ static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *pr
****************************************************************************/
static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
- const char *pass, const char *workgroup)
+ const char *pass, const char *domain)
{
struct ntlmssp_state *ntlmssp_state;
NTSTATUS nt_status;
@@ -556,7 +566,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
return nt_status;
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
return nt_status;
}
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
@@ -654,8 +664,8 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
Do a spnego encrypted session setup.
****************************************************************************/
-NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
- const char *pass, const char *workgroup)
+ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
+ const char *pass, const char *domain)
{
char *principal;
char *OIDs[ASN1_MAX_OIDS];
@@ -682,7 +692,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
reply */
if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
data_blob_free(&blob);
- return NT_STATUS_INVALID_PARAMETER;
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
data_blob_free(&blob);
@@ -712,11 +722,11 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
if (ret){
DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
- return NT_STATUS_LOGON_FAILURE;
+ return ADS_ERROR_KRB5(ret);
}
}
- return cli_session_setup_kerberos(cli, principal, workgroup);
+ return cli_session_setup_kerberos(cli, principal, domain);
}
#endif
@@ -724,7 +734,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
ntlmssp:
- return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
+ return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
}
/****************************************************************************
@@ -805,9 +815,9 @@ BOOL cli_session_setup(struct cli_state *cli,
/* if the server supports extended security then use SPNEGO */
if (cli->capabilities & CAP_EXTENDED_SECURITY) {
- NTSTATUS nt_status;
- if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
- DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
+ ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3, ("SPENGO login failed: %s\n", ads_errstr(status)));
return False;
}
return True;
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 5568b5e033..15b244a83d 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -307,14 +307,14 @@ cleanup_princ:
/*
get a kerberos5 ticket for the given service
*/
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
+int cli_krb5_get_ticket(const char *principal, time_t time_offset,
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
{
krb5_error_code retval;
krb5_data packet;
krb5_ccache ccdef;
krb5_context context;
krb5_auth_context auth_context = NULL;
- DATA_BLOB ret;
krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC
ENCTYPE_ARCFOUR_HMAC,
@@ -356,17 +356,18 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BL
get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
- ret = data_blob(packet.data, packet.length);
+ *ticket = data_blob(packet.data, packet.length);
+
/* Hmm, heimdal dooesn't have this - what's the correct call? */
-/* krb5_free_data_contents(context, &packet); */
- krb5_free_context(context);
- return ret;
+#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
+ krb5_free_data_contents(context, &packet);
+#endif
failed:
if ( context )
krb5_free_context(context);
- return data_blob(NULL, 0);
+ return retval;
}
BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote)
@@ -410,10 +411,11 @@ failed:
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
- {
+int cli_krb5_get_ticket(const char *principal, time_t time_offset,
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
+{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
- return data_blob(NULL, 0);
- }
+ return 1;
+}
#endif
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 92543736ff..e6cadc466c 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -323,27 +323,30 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
kerberos session setup
*/
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, DATA_BLOB *session_key_krb5)
+int spnego_gen_negTokenTarg(const char *principal, int time_offset,
+ DATA_BLOB *targ,
+ DATA_BLOB *session_key_krb5)
{
- DATA_BLOB tkt, tkt_wrapped, targ;
+ int retval;
+ DATA_BLOB tkt, tkt_wrapped;
const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
/* get a kerberos ticket for the service and extract the session key */
- tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5);
+ retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5);
- if (tkt.data == NULL)
- return tkt;
+ if (retval)
+ return retval;
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
/* and wrap that in a shiny SPNEGO wrapper */
- targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
+ *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
data_blob_free(&tkt_wrapped);
data_blob_free(&tkt);
- return targ;
+ return retval;
}
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index c7cc4848b7..83902971b0 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -884,6 +884,40 @@ static BOOL resolve_hosts(const char *name, int name_type,
*/
struct hostent *hp;
+ if ( name_type != 0x20 && name_type != 0x0) {
+ DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
+ return False;
+ }
+
+ *return_iplist = NULL;
+ *return_count = 0;
+
+ DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
+
+ if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
+ struct in_addr return_ip;
+ putip((char *)&return_ip,(char *)hp->h_addr);
+ *return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service));
+ if(*return_iplist == NULL) {
+ DEBUG(3,("resolve_hosts: malloc fail !\n"));
+ return False;
+ }
+ (*return_iplist)->ip = return_ip;
+ (*return_iplist)->port = PORT_NONE;
+ *return_count = 1;
+ return True;
+ }
+ return False;
+}
+
+/********************************************************
+ Resolve via "ADS" method.
+*********************************************************/
+
+static BOOL resolve_ads(const char *name, int name_type,
+ struct ip_service **return_iplist, int *return_count)
+{
+
#ifdef HAVE_ADS
if ( name_type == 0x1c ) {
int count, i = 0;
@@ -935,28 +969,11 @@ static BOOL resolve_hosts(const char *name, int name_type,
*return_count = i;
return True;
- }
+ } else
#endif /* HAVE_ADS */
-
- *return_iplist = NULL;
- *return_count = 0;
-
- DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
-
- if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
- struct in_addr return_ip;
- putip((char *)&return_ip,(char *)hp->h_addr);
- *return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service));
- if(*return_iplist == NULL) {
- DEBUG(3,("resolve_hosts: malloc fail !\n"));
- return False;
- }
- (*return_iplist)->ip = return_ip;
- (*return_iplist)->port = PORT_NONE;
- *return_count = 1;
- return True;
+ {
+ return False;
}
- return False;
}
/*******************************************************************
@@ -1034,14 +1051,17 @@ static BOOL internal_resolve_name(const char *name, int name_type,
while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
if((strequal(tok, "host") || strequal(tok, "hosts"))) {
- /* deal with 0x20 & 0x1c names here. The latter will result
- in a SRV record lookup for _ldap._tcp.<domain> if we are using
- 'security = ads' */
- if ( name_type==0x20 || name_type == 0x1c ) {
- if (resolve_hosts(name, name_type, return_iplist, return_count)) {
- result = True;
- goto done;
- }
+ if (resolve_hosts(name, name_type, return_iplist, return_count)) {
+ result = True;
+ goto done;
+ }
+ } else if(strequal( tok, "ads")) {
+ /* deal with 0x1c names here. This will result in a
+ SRV record lookup for _ldap._tcp.<domain> if we
+ are using 'security = ads' */
+ if (resolve_ads(name, name_type, return_iplist, return_count)) {
+ result = True;
+ goto done;
}
} else if(strequal( tok, "lmhosts")) {
if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
@@ -1207,14 +1227,14 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
/*********************************************************************
small wrapper function to get the DC list and sort it if neccessary
*********************************************************************/
-BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL dns_only )
+BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
{
BOOL ordered;
DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
- (dns_only ? "hosts" : lp_name_resolve_order())));
+ (ads_only ? "ads" : lp_name_resolve_order())));
- if ( !get_dc_list(domain, ip_list, count, dns_only, &ordered) )
+ if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) )
return False;
/* only sort if we don't already have an ordered list */
@@ -1230,11 +1250,11 @@ BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *c
*********************************************************/
BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
- int *count, BOOL dns_only, int *ordered)
+ int *count, BOOL ads_only, int *ordered)
{
/* defined the name resolve order to internal_name_resolve()
only used for looking up 0x1c names */
- const char *resolve_oder = (dns_only ? "hosts" : lp_name_resolve_order());
+ const char *resolve_oder = (ads_only ? "ads" : lp_name_resolve_order());
*ordered = False;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index d645a2fffb..c3abd63818 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -361,7 +361,7 @@ void unlock_share_entry(connection_struct *conn,
}
/*******************************************************************
- Lock a hash bucket entry. Use an fsp for convenience.
+ Lock a hash bucket entry. use a fsp for convenience
******************************************************************/
BOOL lock_share_entry_fsp(files_struct *fsp)
@@ -370,7 +370,7 @@ BOOL lock_share_entry_fsp(files_struct *fsp)
}
/*******************************************************************
- Unlock a hash bucket entry. Use an fsp for convenience.
+ Unlock a hash bucket entry.
******************************************************************/
void unlock_share_entry_fsp(files_struct *fsp)
diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c
index fc66e0d6b4..728796ea21 100644
--- a/source3/nmbd/nmbd_processlogon.c
+++ b/source3/nmbd/nmbd_processlogon.c
@@ -255,7 +255,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
q = ALIGN4(q, buf);
}
- DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
+ DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) ));
if (len - PTR_DIFF(q, buf) > 8) {
/* with NT5 clients we can sometimes
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 7d25524f8e..c7dc89d43f 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -298,18 +298,20 @@ static BOOL wbinfo_domain_info(const char *domain_name)
/* Display response */
- d_printf("Name : %s\n", response.data.domain_info.name);
- d_printf("Alt_Name: %s\n", response.data.domain_info.alt_name);
+ d_printf("Name : %s\n", response.data.domain_info.name);
+ d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name);
- d_printf("SID : %s\n", response.data.domain_info.sid);
+ d_printf("SID : %s\n", response.data.domain_info.sid);
- d_printf("Native : %s\n",
+ d_printf("Active Directory : %s\n",
+ response.data.domain_info.active_directory ? "Yes" : "No");
+ d_printf("Native : %s\n",
response.data.domain_info.native_mode ? "Yes" : "No");
- d_printf("Primary : %s\n",
+ d_printf("Primary : %s\n",
response.data.domain_info.primary ? "Yes" : "No");
- d_printf("Sequence: %d\n", response.data.domain_info.sequence_number);
+ d_printf("Sequence : %d\n", response.data.domain_info.sequence_number);
return True;
}
@@ -909,14 +911,14 @@ static void wbinfo_get_auth_user(void)
char *user, *domain, *password;
/* Lift data from secrets file */
+
+ secrets_fetch_ipc_userpass(&user, &domain, &password);
- secrets_init();
-
- user = secrets_fetch(SECRETS_AUTH_USER, NULL);
- domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
- password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+ if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){
- if (!user && !domain && !password) {
+ SAFE_FREE(user);
+ SAFE_FREE(domain);
+ SAFE_FREE(password);
d_printf("No authorised user configured\n");
return;
}
diff --git a/source3/nsswitch/winbind_nss_freebsd.c b/source3/nsswitch/winbind_nss_freebsd.c
new file mode 100644
index 0000000000..b73a4ce44f
--- /dev/null
+++ b/source3/nsswitch/winbind_nss_freebsd.c
@@ -0,0 +1,81 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ AIX loadable authentication module, providing identification
+ routines against Samba winbind/Windows NT Domain
+
+ Copyright (C) Aaron Collins 2003
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "winbind_client.h"
+
+/* Make sure that the module gets registered needed by freebsd 5.1 */
+
+extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t,
+ int *);
+extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *,
+ char *, size_t, int *);
+extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *,
+ size_t, int *);
+extern enum nss_status _nss_winbind_setgrent(void);
+extern enum nss_status _nss_winbind_endgrent(void);
+
+extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t,
+ int *);
+extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *,
+ char *, size_t, int *);
+extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *,
+ size_t, int *);
+extern enum nss_status _nss_winbind_setpwent(void);
+extern enum nss_status _nss_winbind_endpwent(void);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setgrent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endgrent);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
+
+static ns_mtab methods[] = {
+{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r },
+{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r },
+{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r },
+{ NSDB_GROUP, "endgrent", __nss_compat_setgrent, _nss_winbind_setgrent },
+{ NSDB_GROUP, "setgrent", __nss_compat_endgrent, _nss_winbind_endgrent },
+
+{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r },
+{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r },
+{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r },
+{ NSDB_PASSWD, "endpwent", __nss_compat_setpwent, _nss_winbind_setpwent },
+{ NSDB_PASSWD, "setpwent", __nss_compat_endpwent, _nss_winbind_endpwent },
+
+};
+
+ns_mtab *
+nss_module_register(const char *source, unsigned int *mtabsize,
+ nss_module_unregister_fn *unreg)
+{
+ *mtabsize = sizeof(methods)/sizeof(methods[0]);
+ *unreg = NULL;
+ return (methods);
+}
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 4c03522461..3124ef6378 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -935,6 +935,8 @@ int main(int argc, char **argv)
netsamlogon_cache_init(); /* Non-critical */
+ init_domain_list();
+
/* Loop waiting for requests */
process_loop();
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 5dbe422bc1..7c8e6256e1 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -95,7 +95,8 @@ struct winbindd_domain {
fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */
BOOL native_mode; /* is this a win2k domain in native mode ? */
- BOOL primary; /* is this our primary domain ? */
+ BOOL active_directory; /* is this a win2k active directory ? */
+ BOOL primary; /* is this our primary domain ? */
/* Lookup methods for this domain (LDAP or RPC) */
struct winbindd_methods *methods;
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index ec93d494d0..e6b857f406 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -112,7 +112,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
goto done;
}
- rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
+ rc = ads_search_retry(ads, &res, "(objectClass=user)", attrs);
if (!ADS_ERR_OK(rc) || !res) {
DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
goto done;
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index a3c1706b75..8dec89a6aa 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -107,12 +107,14 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
case SEC_ADS: {
extern struct winbindd_methods ads_methods;
/* always obey the lp_security parameter for our domain */
- if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) {
+ if (domain->primary) {
domain->backend = &ads_methods;
break;
}
- if ( domain->native_mode ) {
+ /* if it have either of the indications of ADS,
+ use ads_methods */
+ if ( domain->active_directory || domain->native_mode ) {
domain->backend = &ads_methods;
break;
}
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 2b561be31d..44fc06fe54 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -174,16 +174,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
if ((lp_security() == SEC_ADS)
&& (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
+ ADS_STATUS ads_status;
new_conn->cli->use_kerberos = True;
DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n",
new_conn->controller, global_myname(), machine_krb5_principal));
- result = NT_STATUS_OK;
-
- if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
- machine_password,
- lp_workgroup()))) {
- DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+ ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal,
+ machine_password,
+ lp_workgroup());
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status)));
+ result = ads_ntstatus(ads_status);
+ } else {
+ result = NT_STATUS_OK;
}
}
new_conn->cli->use_kerberos = False;
@@ -405,46 +408,116 @@ static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const
}
/**********************************************************************************
+ We can 'sense' certain things about the DC by it's replies to certain questions.
+
+ This tells us if this particular remote server is Active Directory, and if it is
+ native mode.
**********************************************************************************/
-BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain )
+void set_dc_type_and_flags( struct winbindd_domain *domain )
{
NTSTATUS result;
struct winbindd_cm_conn conn;
DS_DOMINFO_CTR ctr;
- BOOL ret = False;
+ TALLOC_CTX *mem_ctx = NULL;
ZERO_STRUCT( conn );
ZERO_STRUCT( ctr );
+ domain->native_mode = False;
+ domain->active_directory = False;
if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
- DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
+ DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n",
domain->name, nt_errstr(result)));
- return False;
+ return;
}
if ( conn.cli ) {
if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli,
conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
- ret = False;
goto done;
}
}
if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING)
&& !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
- ret = True;
+ domain->native_mode = True;
-done:
+ /* Cheat - shut down the DS pipe, and open LSA */
+
+ cli_nt_session_close(conn.cli);
+
+ if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) {
+ char *domain_name = NULL;
+ char *dns_name = NULL;
+ DOM_SID *dom_sid = NULL;
+
+ mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name);
+ if (!mem_ctx) {
+ DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+ return;
+ }
+
+ result = cli_lsa_open_policy2(conn.cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &conn.pol);
+
+ if (NT_STATUS_IS_OK(result)) {
+ /* This particular query is exactly what Win2k clients use
+ to determine that the DC is active directory */
+ result = cli_lsa_query_info_policy2(conn.cli, mem_ctx,
+ &conn.pol,
+ 12, &domain_name,
+ &dns_name, NULL,
+ NULL, &dom_sid);
+ }
+
+ if (NT_STATUS_IS_OK(result)) {
+ if (domain_name)
+ fstrcpy(domain->name, domain_name);
+
+ if (dns_name)
+ fstrcpy(domain->alt_name, dns_name);
+ if (dom_sid)
+ sid_copy(&domain->sid, dom_sid);
+
+ domain->active_directory = True;
+ } else {
+
+ result = cli_lsa_open_policy(conn.cli, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &conn.pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = cli_lsa_query_info_policy(conn.cli, mem_ctx,
+ &conn.pol, 5, &domain_name,
+ &dom_sid);
+
+ if (NT_STATUS_IS_OK(result)) {
+ if (domain_name)
+ fstrcpy(domain->name, domain_name);
+
+ if (dom_sid)
+ sid_copy(&domain->sid, dom_sid);
+ }
+ }
+ }
+
+done:
+
/* close the connection; no other cals use this pipe and it is called only
on reestablishing the domain list --jerry */
-
+
if ( conn.cli )
cli_shutdown( conn.cli );
- return ret;
+ talloc_destroy(mem_ctx);
+
+ return;
}
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index 180a3db8e2..b31dc92b38 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -106,7 +106,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
*num_gr_mem = 0;
if ( !((group_name_type==SID_NAME_DOM_GRP) ||
- ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+ ((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
{
DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n",
sid_to_string(sid_string, group_sid), domain->name,
@@ -152,15 +152,10 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
occur in Universal groups on a Windows 2000 native mode
server. */
- if (name_types[i] != SID_NAME_USER) {
- DEBUG(3, ("name %s isn't a domain user\n", the_name));
- continue;
- }
+ /* make sure to allow machine accounts */
- /* Don't bother with machine accounts */
-
- if (the_name[strlen(the_name) - 1] == '$') {
- DEBUG(10, ("%s is machine account\n", the_name));
+ if (name_types[i] != SID_NAME_USER && name_types[i] != SID_NAME_COMPUTER) {
+ DEBUG(3, ("name %s isn't a domain user\n", the_name));
continue;
}
@@ -265,22 +260,20 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
return WINBINDD_OK;
}
- /* should we deal with users for our domain? */
-
- if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
- DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n",
- name_domain, name_group));
- return WINBINDD_ERROR;
- }
-
-
/* Get info for the domain */
if ((domain = find_domain_from_name(name_domain)) == NULL) {
- DEBUG(0, ("could not get domain sid for domain %s\n",
+ DEBUG(3, ("could not get domain sid for domain %s\n",
name_domain));
return WINBINDD_ERROR;
}
+ /* should we deal with users for our domain? */
+
+ if ( lp_winbind_trusted_domains_only() && domain->primary) {
+ DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n",
+ name_domain, name_group));
+ return WINBINDD_ERROR;
+ }
/* Get rid and name type from name */
@@ -292,7 +285,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
}
if ( !((name_type==SID_NAME_DOM_GRP) ||
- ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+ ((name_type==SID_NAME_ALIAS) && domain->primary)) )
{
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
name_group, name_type));
@@ -383,7 +376,7 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
}
if ( !((name_type==SID_NAME_DOM_GRP) ||
- ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+ ((name_type==SID_NAME_ALIAS) && domain->primary) ))
{
DEBUG(1, ("name '%s' is not a local or domain group: %d\n",
group_name, name_type));
@@ -441,7 +434,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
are a member of a Samba domain */
if ( (IS_DC || lp_winbind_trusted_domains_only())
- && strequal(domain->name, lp_workgroup()) )
+ && domain->primary )
{
continue;
}
@@ -547,7 +540,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
and are not using LDAP to get the groups */
if ( lp_security() != SEC_ADS && domain->native_mode
- && strequal(lp_workgroup(), domain->name) )
+ && domain->primary )
{
DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
@@ -887,7 +880,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
extra_data[extra_data_len++] = ',';
}
- free(groups.sam_entries);
+ SAFE_FREE(groups.sam_entries);
}
/* Assign extra_data fields in response structure */
@@ -938,21 +931,22 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
/* Parse domain and username */
parse_domain_user(state->request.data.username,
- name_domain, name_user);
-
- /* bail if there is no domain */
+ name_domain, name_user);
- if ( !*name_domain )
- goto done;
-
/* Get info for the domain */
if ((domain = find_domain_from_name(name_domain)) == NULL) {
- DEBUG(0, ("could not find domain entry for domain %s\n",
+ DEBUG(7, ("could not find domain entry for domain %s\n",
name_domain));
goto done;
}
+ if ( domain->primary && lp_winbind_trusted_domains_only()) {
+ DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getgroups() for %s\\%s.\n",
+ name_domain, name_user));
+ return WINBINDD_ERROR;
+ }
+
/* Get rid and name type from name. The following costs 1 packet */
if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid,
@@ -961,7 +955,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
goto done;
}
- if (name_type != SID_NAME_USER) {
+ if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) {
DEBUG(1, ("name '%s' is not a user name: %d\n",
name_user, name_type));
goto done;
@@ -1000,7 +994,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
in a win2k native mode domain. */
if ( !((sid_type==SID_NAME_DOM_GRP) ||
- ((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+ ((sid_type==SID_NAME_ALIAS) && domain->primary)) )
{
DEBUG(10, ("winbindd_getgroups: sid type %d "
"for %s is not a domain group\n",
@@ -1127,7 +1121,7 @@ enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state)
sid_string_static(&user_sid)));
goto done;
}
-
+
status = domain->methods->lookup_usergroups(domain, mem_ctx,
&user_sid, &num_groups,
&user_grpsids);
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
index 08b5be827d..18478992f3 100644
--- a/source3/nsswitch/winbindd_misc.c
+++ b/source3/nsswitch/winbindd_misc.c
@@ -36,7 +36,6 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
int num_retries = 0;
struct cli_state *cli;
uint32 sec_channel_type;
- const char *contact_domain_name = NULL;
struct winbindd_domain *contact_domain;
DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
@@ -51,18 +50,10 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
}
- /* use the realm name if appropriate and possible */
-
- if ( lp_security() == SEC_ADS )
- contact_domain_name = lp_realm();
-
- if ( !contact_domain_name || !*contact_domain_name )
- contact_domain_name = lp_workgroup();
-
- contact_domain = find_domain_from_name(contact_domain_name);
+ contact_domain = find_our_domain();
if (!contact_domain) {
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- DEBUG(1, ("%s is not a trusted domain\n", contact_domain_name));
+ DEBUG(1, ("Cannot find our own domain!\n"));
goto done;
}
@@ -132,7 +123,7 @@ enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state
/* Skip own domain */
- if (strequal(domain->name, lp_workgroup())) continue;
+ if (domain->primary) continue;
/* Add domain to list */
@@ -232,6 +223,7 @@ enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state)
sid_string_static(&domain->sid));
state->response.data.domain_info.native_mode = domain->native_mode;
+ state->response.data.domain_info.active_directory = domain->active_directory;
state->response.data.domain_info.primary = domain->primary;
state->response.data.domain_info.sequence_number =
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index 0dd00e9b39..0d110b8afa 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -36,7 +36,7 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 8
+#define WINBIND_INTERFACE_VERSION 9
/* Socket commands */
@@ -272,6 +272,7 @@ struct winbindd_response {
fstring alt_name;
fstring sid;
BOOL native_mode;
+ BOOL active_directory;
BOOL primary;
uint32 sequence_number;
} domain_info;
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index f619aa3564..21e0c3092e 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -950,7 +950,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
TALLOC_CTX *mem_ctx;
CLI_POLICY_HND *hnd;
- fstring level5_dom;
+ char *level5_dom;
+ DOM_SID *alloc_sid;
int retry;
DEBUG(3,("rpc: domain_sid\n"));
@@ -965,9 +966,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
goto done;
result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
- &hnd->pol, 0x05, level5_dom, sid);
+ &hnd->pol, 0x05, &level5_dom, &alloc_sid);
} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
+ if (NT_STATUS_IS_OK(result)) {
+ if (alloc_sid) {
+ sid_copy(sid, alloc_sid);
+ } else {
+ result = NT_STATUS_NO_MEMORY;
+ }
+ }
+
done:
talloc_destroy(mem_ctx);
return result;
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index 7c4c8d804a..9fbf47046d 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -152,7 +152,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
DOM_SID sid2;
uint32 rid;
- domain = find_domain_from_name( lp_workgroup() );
+ domain = find_our_domain();
if ( !domain ) {
DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
return WINBINDD_ERROR;
@@ -244,7 +244,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
uint32 rid;
unid_t id;
- domain = find_domain_from_name( lp_workgroup() );
+ domain = find_our_domain();
if ( !domain ) {
DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
return WINBINDD_ERROR;
@@ -341,7 +341,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
if ( !(pw = getpwuid(state->request.data.uid)) )
return WINBINDD_ERROR;
- if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+ if ( !(domain = find_our_domain()) ) {
DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
return WINBINDD_ERROR;
}
@@ -411,7 +411,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
if ( !(grp = getgrgid(state->request.data.gid)) )
return WINBINDD_ERROR;
- if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+ if ( !(domain = find_our_domain()) ) {
DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
return WINBINDD_ERROR;
}
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 903a2a8bfa..d08377c888 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -37,7 +37,8 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
char *full_name, struct winbindd_pw *pw)
{
fstring output_username;
- pstring homedir;
+ char *homedir;
+ char *shell;
fstring sid_string;
if (!pw || !dom_name || !user_name)
@@ -72,24 +73,32 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
shell. */
/* The substitution of %U and %D in the 'template homedir' is done
- by lp_string() calling standard_sub_basic(). */
+ by alloc_sub_specified() below. */
- fstrcpy(current_user_info.smb_name, user_name);
- sub_set_smb_name(user_name);
fstrcpy(current_user_info.domain, dom_name);
- pstrcpy(homedir, lp_template_homedir());
+ homedir = alloc_sub_specified(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid);
+
+ if (!homedir)
+ return False;
safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1);
- safe_strcpy(pw->pw_shell, lp_template_shell(),
+ SAFE_FREE(homedir);
+
+ shell = alloc_sub_specified(lp_template_shell(), user_name, dom_name, pw->pw_uid, pw->pw_gid);
+
+ if (!shell)
+ return False;
+
+ safe_strcpy(pw->pw_shell, shell,
sizeof(pw->pw_shell) - 1);
/* Password - set to "x" as we can't generate anything useful here.
Authentication can be done using the pam_winbind module. */
safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
-
+
return True;
}
@@ -115,7 +124,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* Parse domain and username */
parse_domain_user(state->request.data.username,
- name_domain, name_user);
+ name_domain, name_user);
/* if this is our local domain (or no domain), the do a local tdb search */
@@ -131,17 +140,17 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
/* should we deal with users for our domain? */
- if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
- DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n",
- name_domain, name_user));
- return WINBINDD_ERROR;
- }
-
if ((domain = find_domain_from_name(name_domain)) == NULL) {
DEBUG(5, ("no such domain: %s\n", name_domain));
return WINBINDD_ERROR;
}
+ if ( domain->primary && lp_winbind_trusted_domains_only()) {
+ DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n",
+ name_domain, name_user));
+ return WINBINDD_ERROR;
+ }
+
/* Get rid and name type from name */
if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) {
@@ -149,15 +158,13 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
- if (name_type != SID_NAME_USER) {
+ if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) {
DEBUG(1, ("name '%s' is not a user name: %d\n", name_user,
name_type));
return WINBINDD_ERROR;
}
- /* Get some user info. Split the user rid from the sid obtained
- from the winbind_lookup_by_name() call and use it in a
- winbind_lookup_userinfo() */
+ /* Get some user info. */
if (!(mem_ctx = talloc_init("winbindd_getpwnam([%s]\\[%s])",
name_domain, name_user))) {
@@ -530,15 +537,6 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
name_list = ent->sam_entries;
- /* Skip machine accounts */
-
- if (name_list[ent->sam_entry_index].
- name[strlen(name_list[ent->sam_entry_index].name) - 1]
- == '$') {
- ent->sam_entry_index++;
- continue;
- }
-
/* Lookup user info */
result = winbindd_fill_pwent(
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 4cc43e85d6..076ab1a2fc 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -49,6 +49,14 @@ static const fstring name_deadbeef = "<deadbeef>";
static struct winbindd_domain *_domain_list;
+/**
+ When was the last scan of trusted domains done?
+
+ 0 == not ever
+*/
+
+static time_t last_trustdom_scan;
+
struct winbindd_domain *domain_list(void)
{
/* Initialise list */
@@ -83,6 +91,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
{
struct winbindd_domain *domain;
const char *alternative_name = NULL;
+ static const DOM_SID null_sid;
/* ignore alt_name if we are not in an AD domain */
@@ -103,6 +112,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
return domain;
}
}
+ if (sid) {
+ if (sid_equal(sid, &null_sid) ) {
+
+ } else if (sid_equal(sid, &domain->sid)) {
+ return domain;
+ }
+ }
}
/* Create new domain entry */
@@ -133,12 +149,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
sid_copy(&domain->sid, sid);
}
- /* see if this is a native mode win2k domain */
+ /* set flags about native_mode, active_directory */
- domain->native_mode = cm_check_for_native_mode_win2k( domain );
+ set_dc_type_and_flags( domain );
- DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name,
- domain->native_mode ? "native" : "mixed (or NT4)" ));
+ DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
+ domain->active_directory ? "ADS" : "NT4",
+ domain->native_mode ? "native mode" :
+ ((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
/* Link to domain list */
DLIST_ADD(_domain_list, domain);
@@ -156,13 +174,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
void rescan_trusted_domains( void )
{
- static time_t last_scan;
time_t now = time(NULL);
struct winbindd_domain *mydomain = NULL;
/* see if the time has come... */
- if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) )
+ if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
return;
if ( (mydomain = find_our_domain()) == NULL ) {
@@ -174,7 +191,7 @@ void rescan_trusted_domains( void )
add_trusted_domains( mydomain );
- last_scan = now;
+ last_trustdom_scan = now;
return;
}
@@ -200,7 +217,7 @@ void add_trusted_domains( struct winbindd_domain *domain )
return;
}
- DEBUG(1, ("scanning trusted domain list\n"));
+ DEBUG(5, ("scanning trusted domain list\n"));
if (!(mem_ctx = talloc_init("init_domain_list")))
return;
@@ -221,7 +238,7 @@ void add_trusted_domains( struct winbindd_domain *domain )
for(i = 0; i < num_domains; i++) {
DEBUG(10,("Found domain %s\n", names[i]));
add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
- domain->methods, &dom_sids[i]);
+ domain->methods, &dom_sids[i]);
/* if the SID was empty, we better set it now */
@@ -263,7 +280,7 @@ BOOL init_domain_list(void)
/* Free existing list */
free_domain_list();
- /* Add ourselves as the first entry. It *must* be the first entry */
+ /* Add ourselves as the first entry. */
domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL);
@@ -286,7 +303,9 @@ BOOL init_domain_list(void)
/* do an initial scan for trusted domains */
add_trusted_domains(domain);
-
+
+ /* avoid rescanning this right away */
+ last_trustdom_scan = time(NULL);
return True;
}
@@ -364,10 +383,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
{
NTSTATUS result;
TALLOC_CTX *mem_ctx;
- /* Don't bother with machine accounts */
-
- if (name[strlen(name) - 1] == '$')
- return False;
mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name);
if (!mem_ctx)
diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c
index 779d1b2c6c..100a103924 100644
--- a/source3/nsswitch/wins.c
+++ b/source3/nsswitch/wins.c
@@ -194,7 +194,7 @@ int lookup(nsd_file_t *rq)
* response needs to be a string of the following format
* ip_address[ ip_address]*\tname[ alias]*
*/
- if (strcasecmp(map,"hosts.byaddr") == 0) {
+ if (StrCaseCmp(map,"hosts.byaddr") == 0) {
if ( status = lookup_byaddr_backend(key, &count)) {
size = strlen(key) + 1;
if (size > len) {
@@ -222,7 +222,7 @@ int lookup(nsd_file_t *rq)
response[strlen(response)-1] = '\n';
free(status);
}
- } else if (strcasecmp(map,"hosts.byname") == 0) {
+ } else if (StrCaseCmp(map,"hosts.byname") == 0) {
if (ip_list = lookup_byname_backend(key, &count)) {
for (i = count; i ; i--) {
addr = inet_ntoa(ip_list[i-1]);
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 67012ee087..a1fb90157c 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -217,6 +217,7 @@ typedef struct
int change_notify_timeout;
int map_to_guest;
int min_passwd_length;
+ BOOL use_cracklib;
int oplock_break_wait_time;
int winbind_cache_time;
int iLockSpinCount;
@@ -749,6 +750,12 @@ static const struct enum_list enum_map_to_guest[] = {
* Any parameter that does NOT have FLAG_ADVANCED will not disply at all
* Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
* respective views.
+ *
+ * NOTE2: Handling of duplicated (synonym) paramters:
+ * Only the first occurance of a parameter should be enabled by FLAG_BASIC
+ * and/or FLAG_ADVANCED. All duplicates following the first mention should be
+ * set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
+ * name first, and all synonyms must follow it with the FLAG_HIDE attribute.
*/
static struct parm_struct parm_table[] = {
@@ -784,6 +791,7 @@ static struct parm_struct parm_table[] = {
{"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED},
{"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED},
{"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED},
+ {"use cracklib", P_BOOL, P_GLOBAL, &Globals.use_cracklib, NULL, NULL, FLAG_ADVANCED},
{"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED},
{"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED},
{"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED},
@@ -1153,9 +1161,9 @@ static struct parm_struct parm_table[] = {
{"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED},
{"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED},
{"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
- {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
+ {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE},
{"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED},
- {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED},
+ {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE},
{"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED},
{"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED},
{"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED},
@@ -1437,6 +1445,7 @@ static void init_globals(void)
Globals.map_to_guest = 0; /* By Default, "Never" */
Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */
+ Globals.use_cracklib = False;
Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
Globals.enhanced_browsing = True;
Globals.iLockSpinCount = 3; /* Try 3 times. */
@@ -1681,8 +1690,8 @@ FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
-FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
-FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
+FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
+FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
FN_GLOBAL_BOOL(lp_winbind_enable_local_accounts, &Globals.bWinbindEnableLocalAccounts)
@@ -1791,6 +1800,7 @@ FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout
FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
+FN_GLOBAL_BOOL(lp_use_cracklib, &Globals.use_cracklib)
FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index a5a2c29a8b..f9557cac42 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -3,6 +3,7 @@
Copyright (C) Andrew Tridgell 1992-2001
Copyright (C) Andrew Bartlett 2002
Copyright (C) Rafal Szczesniak 2002
+ Copyright (C) Tim Potter 2001
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
@@ -790,3 +791,40 @@ BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result)
return True;
}
+
+/******************************************************************************
+ When kerberos is not available, choose between anonymous or
+ authenticated connections.
+
+ We need to use an authenticated connection if DCs have the
+ RestrictAnonymous registry entry set > 0, or the "Additional
+ restrictions for anonymous connections" set in the win2k Local
+ Security Policy.
+
+ Caller to free() result in domain, username, password
+*******************************************************************************/
+void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
+{
+ *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
+ *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+ *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+
+ if (*username && **username) {
+
+ if (!*domain || !**domain)
+ *domain = smb_xstrdup(lp_workgroup());
+
+ if (!*password || !**password)
+ *password = smb_xstrdup("");
+
+ DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
+ *domain, *username));
+
+ } else {
+ DEBUG(3, ("IPC$ connections done anonymously\n"));
+ *username = smb_xstrdup("");
+ *domain = smb_xstrdup("");
+ *password = smb_xstrdup("");
+ }
+}
+
diff --git a/source3/printing/notify.c b/source3/printing/notify.c
index f2dd7d4f22..7750239630 100644
--- a/source3/printing/notify.c
+++ b/source3/printing/notify.c
@@ -20,6 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "includes.h"
#include "printing.h"
static TALLOC_CTX *send_ctx;
diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c
index 77719ffc52..f0096a17c2 100644
--- a/source3/printing/print_cups.c
+++ b/source3/printing/print_cups.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "includes.h"
#include "printing.h"
#ifdef HAVE_CUPS
diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c
index 1c847448da..9e0ea85bb9 100644
--- a/source3/printing/print_generic.c
+++ b/source3/printing/print_generic.c
@@ -18,6 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "includes.h"
#include "printing.h"
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index 791c41fe69..bdcd950450 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -20,6 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "includes.h"
#include "printing.h"
/* Current printer interface */
diff --git a/source3/printing/printing_db.c b/source3/printing/printing_db.c
index 1c7ac71353..0e0fb1b51d 100644
--- a/source3/printing/printing_db.c
+++ b/source3/printing/printing_db.c
@@ -20,6 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "includes.h"
#include "printing.h"
static struct tdb_print_db *print_db_head;
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index 0ec9beb1a4..40b83c5c0c 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -443,7 +443,7 @@ NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint16 info_class,
- fstring domain_name, DOM_SID *domain_sid)
+ char **domain_name, DOM_SID **domain_sid)
{
prs_struct qbuf, rbuf;
LSA_Q_QUERY_INFO q;
@@ -481,39 +481,40 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Return output parameters */
- ZERO_STRUCTP(domain_sid);
- domain_name[0] = '\0';
-
switch (info_class) {
case 3:
- if (r.dom.id3.buffer_dom_name != 0) {
- unistr2_to_ascii(domain_name,
- &r.dom.id3.
- uni_domain_name,
- sizeof (fstring) - 1);
+ if (domain_name && (r.dom.id3.buffer_dom_name != 0)) {
+ *domain_name = unistr2_tdup(mem_ctx,
+ &r.dom.id3.
+ uni_domain_name);
}
- if (r.dom.id3.buffer_dom_sid != 0) {
- *domain_sid = r.dom.id3.dom_sid.sid;
+ if (domain_sid && (r.dom.id3.buffer_dom_sid != 0)) {
+ *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+ if (*domain_sid) {
+ sid_copy(*domain_sid, &r.dom.id3.dom_sid.sid);
+ }
}
break;
case 5:
- if (r.dom.id5.buffer_dom_name != 0) {
- unistr2_to_ascii(domain_name, &r.dom.id5.
- uni_domain_name,
- sizeof (fstring) - 1);
+ if (domain_name && (r.dom.id5.buffer_dom_name != 0)) {
+ *domain_name = unistr2_tdup(mem_ctx,
+ &r.dom.id5.
+ uni_domain_name);
}
- if (r.dom.id5.buffer_dom_sid != 0) {
- *domain_sid = r.dom.id5.dom_sid.sid;
+ if (domain_sid && (r.dom.id5.buffer_dom_sid != 0)) {
+ *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+ if (*domain_sid) {
+ sid_copy(*domain_sid, &r.dom.id5.dom_sid.sid);
+ }
}
-
break;
-
+
default:
DEBUG(3, ("unknown info class %d\n", info_class));
break;
@@ -536,10 +537,9 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint16 info_class,
- fstring domain_name, fstring dns_name,
- fstring forest_name,
- struct uuid *domain_guid,
- DOM_SID *domain_sid)
+ char **domain_name, char **dns_name,
+ char **forest_name, struct uuid **domain_guid,
+ DOM_SID **domain_sid)
{
prs_struct qbuf, rbuf;
LSA_Q_QUERY_INFO2 q;
@@ -580,30 +580,37 @@ NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Return output parameters */
- ZERO_STRUCTP(domain_sid);
ZERO_STRUCTP(domain_guid);
- domain_name[0] = '\0';
- if (r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
- unistr2_to_ascii(domain_name,
- &r.info.dns_dom_info.uni_nb_dom_name,
- sizeof(fstring) - 1);
+ if (domain_name && r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
+ *domain_name = unistr2_tdup(mem_ctx,
+ &r.info.dns_dom_info
+ .uni_nb_dom_name);
}
- if (r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
- unistr2_to_ascii(dns_name,
- &r.info.dns_dom_info.uni_dns_dom_name,
- sizeof(fstring) - 1);
+ if (dns_name && r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
+ *dns_name = unistr2_tdup(mem_ctx,
+ &r.info.dns_dom_info
+ .uni_dns_dom_name);
}
- if (r.info.dns_dom_info.hdr_forest_name.buffer) {
- unistr2_to_ascii(forest_name,
- &r.info.dns_dom_info.uni_forest_name,
- sizeof(fstring) - 1);
+ if (forest_name && r.info.dns_dom_info.hdr_forest_name.buffer) {
+ *forest_name = unistr2_tdup(mem_ctx,
+ &r.info.dns_dom_info
+ .uni_forest_name);
}
- memcpy(domain_guid, &r.info.dns_dom_info.dom_guid,sizeof(struct uuid));
-
- if (r.info.dns_dom_info.ptr_dom_sid != 0) {
- *domain_sid = r.info.dns_dom_info.dom_sid.sid;
+ if (domain_guid) {
+ *domain_guid = talloc(mem_ctx, sizeof(**domain_guid));
+ memcpy(*domain_guid,
+ &r.info.dns_dom_info.dom_guid,
+ sizeof(struct uuid));
+ }
+
+ if (domain_sid && r.info.dns_dom_info.ptr_dom_sid != 0) {
+ *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+ if (*domain_sid) {
+ sid_copy(*domain_sid,
+ &r.info.dns_dom_info.dom_sid.sid);
+ }
}
done:
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index b9974cba8a..7edd34c8dd 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -2834,11 +2834,17 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
} else {
/* update the UNIX password */
- if (lp_unix_password_sync() )
- if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
+ if (lp_unix_password_sync() ) {
+ struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd));
+ if (!passwd) {
+ DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
+ }
+
+ if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
pdb_free_sam(&pwd);
return False;
}
+ }
}
ZERO_STRUCT(plaintext_buf);
@@ -2899,7 +2905,12 @@ static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
} else {
/* update the UNIX password */
if (lp_unix_password_sync()) {
- if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
+ struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd));
+ if (!passwd) {
+ DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
+ }
+
+ if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
pdb_free_sam(&pwd);
return False;
}
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
index 217e6b1d68..d9afde465d 100644
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -68,9 +68,13 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
{
POLICY_HND pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- DOM_SID dom_sid;
- struct uuid dom_guid;
- fstring sid_str, domain_name="", dns_name="", forest_name="";
+ DOM_SID *dom_sid;
+ struct uuid *dom_guid;
+ fstring sid_str;
+ char *domain_name = NULL;
+ char *dns_name = NULL;
+ char *forest_name = NULL;
+
uint32 info_class = 3;
if (argc > 2) {
@@ -91,8 +95,8 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
if (!NT_STATUS_IS_OK(result))
goto done;
result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol,
- info_class, domain_name,
- dns_name, forest_name,
+ info_class, &domain_name,
+ &dns_name, &forest_name,
&dom_guid, &dom_sid);
break;
default:
@@ -103,28 +107,28 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
if (!NT_STATUS_IS_OK(result))
goto done;
result = cli_lsa_query_info_policy(cli, mem_ctx, &pol,
- info_class, domain_name,
+ info_class, &domain_name,
&dom_sid);
}
if (!NT_STATUS_IS_OK(result))
goto done;
+
+ sid_to_string(sid_str, dom_sid);
- sid_to_string(sid_str, &dom_sid);
-
- if (domain_name[0])
+ if (domain_name)
printf("domain %s has sid %s\n", domain_name, sid_str);
else
printf("could not query info for level %d\n", info_class);
- if (dns_name[0])
+ if (dns_name)
printf("domain dns name is %s\n", dns_name);
- if (forest_name[0])
+ if (forest_name)
printf("forest name is %s\n", forest_name);
if (info_class == 12) {
- printf("domain GUID is %s\n",
- smb_uuid_string_static(dom_guid));
+ printf("domain GUID is ");
+ smb_uuid_string_static(*dom_guid);
}
done:
return result;
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index 798949fae9..f5a440c024 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -1336,7 +1336,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
strupper_m(servername);
- /* Fill in the DRIVER_INFO_3 struct */
+ /* Fill in the DRIVER_INFO_2 struct */
ZERO_STRUCT(info2);
#if 0 /* JERRY */
init_unistr( &info2.servername, servername);
diff --git a/source3/script/installswat.sh b/source3/script/installswat.sh
index 027ca35110..c0285bda55 100755
--- a/source3/script/installswat.sh
+++ b/source3/script/installswat.sh
@@ -71,7 +71,7 @@ for ln in $LANGS; do
done
-# Install html documentation
+# Install html documentation (if html documentation tree is here)
if [ -d $SRCDIR../docs/htmldocs/ ]; then
diff --git a/source3/script/mkbuildoptions.awk b/source3/script/mkbuildoptions.awk
index cdc5bd9881..9c22662310 100644
--- a/source3/script/mkbuildoptions.awk
+++ b/source3/script/mkbuildoptions.awk
@@ -242,14 +242,14 @@ END {
# add code to display the various type sizes
print " /* Output the sizes of the various types */";
print " output(screen, \"\\nType sizes:\\n\");";
- print " output(screen, \" sizeof(char): %u\\n\",sizeof(char));";
- print " output(screen, \" sizeof(int): %u\\n\",sizeof(int));";
- print " output(screen, \" sizeof(long): %u\\n\",sizeof(long));";
- print " output(screen, \" sizeof(uint8): %u\\n\",sizeof(uint8));";
- print " output(screen, \" sizeof(uint16): %u\\n\",sizeof(uint16));";
- print " output(screen, \" sizeof(uint32): %u\\n\",sizeof(uint32));";
- print " output(screen, \" sizeof(short): %u\\n\",sizeof(short));";
- print " output(screen, \" sizeof(void*): %u\\n\",sizeof(void*));";
+ print " output(screen, \" sizeof(char): %lu\\n\",(unsigned long)sizeof(char));";
+ print " output(screen, \" sizeof(int): %lu\\n\",(unsigned long)sizeof(int));";
+ print " output(screen, \" sizeof(long): %lu\\n\",(unsigned long)sizeof(long));";
+ print " output(screen, \" sizeof(uint8): %lu\\n\",(unsigned long)sizeof(uint8));";
+ print " output(screen, \" sizeof(uint16): %lu\\n\",(unsigned long)sizeof(uint16));";
+ print " output(screen, \" sizeof(uint32): %lu\\n\",(unsigned long)sizeof(uint32));";
+ print " output(screen, \" sizeof(short): %lu\\n\",(unsigned long)sizeof(short));";
+ print " output(screen, \" sizeof(void*): %lu\\n\",(unsigned long)sizeof(void*));";
##################################################
# add code to give information about modules
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index e6117245e7..692e82680d 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -49,6 +49,16 @@
#include "includes.h"
+#ifdef HAVE_WORKING_CRACKLIB
+#include <crack.h>
+
+#ifndef HAVE_CRACKLIB_DICTPATH
+#ifndef CRACKLIB_DICTPATH
+#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH
+#endif
+#endif
+#endif
+
extern struct passdb_ops pdb_ops;
static NTSTATUS check_oem_password(const char *user,
@@ -441,25 +451,14 @@ while we were waiting\n", WTERMSIG(wstat)));
return (chstat);
}
-BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root)
+BOOL chgpasswd(const char *name, const struct passwd *pass,
+ const char *oldpass, const char *newpass, BOOL as_root)
{
pstring passwordprogram;
pstring chatsequence;
size_t i;
size_t len;
- struct passwd *pass;
-
- if (!name) {
- DEBUG(1, ("chgpasswd: NULL username specfied !\n"));
- }
-
- pass = Get_Pwnam(name);
- if (!pass) {
- DEBUG(1, ("chgpasswd: Username does not exist in system !\n"));
- return False;
- }
-
if (!oldpass) {
oldpass = "";
}
@@ -471,13 +470,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
#endif
/* Take the passed information and test it for minimum criteria */
- /* Minimum password length */
- if (strlen(newpass) < lp_min_passwd_length()) {
- /* too short, must be at least MINPASSWDLENGTH */
- DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n",
- name, lp_min_passwd_length()));
- return (False); /* inform the user */
- }
/* Password is same as old password */
if (strcmp(oldpass, newpass) == 0) {
@@ -570,7 +562,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram ));
#else /* ALLOW_CHANGE_PASSWORD */
-BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root)
+BOOL chgpasswd(const char *name, const struct passwd *pass,
+ const char *oldpass, const char *newpass, BOOL as_root)
{
DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name));
return (False);
@@ -909,6 +902,8 @@ static NTSTATUS check_oem_password(const char *user,
NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
{
+ struct passwd *pass;
+
BOOL ret;
uint32 min_len;
@@ -936,7 +931,47 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
/* return NT_STATUS_PWD_TOO_SHORT; */
}
- /* TODO: Add cracklib support here */
+ pass = Get_Pwnam(pdb_get_username(hnd));
+ if (!pass) {
+ DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n"));
+ }
+
+#ifdef HAVE_WORKING_CRACKLIB
+ if (pass) {
+ /* if we can, become the user to overcome internal cracklib sillyness */
+ if (!push_sec_ctx())
+ return NT_STATUS_UNSUCCESSFUL;
+
+ set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
+ set_re_uid();
+ }
+
+ if (lp_use_cracklib()) {
+ const char *crack_check_reason;
+ DEBUG(4, ("change_oem_password: Checking password for user [%s]"
+ " against cracklib. \n", pdb_get_username(hnd)));
+ DEBUGADD(4, ("If this is your last message, then something is "
+ "wrong with cracklib, it might be missing it's "
+ "dictionaries at %s\n",
+ CRACKLIB_DICTPATH));
+ dbgflush();
+
+ crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH);
+ if (crack_check_reason) {
+ DEBUG(1, ("Password Change: user [%s], "
+ "New password failed cracklib test - %s\n",
+ pdb_get_username(hnd), crack_check_reason));
+
+ /* get back to where we should be */
+ if (pass)
+ pop_sec_ctx();
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ }
+
+ if (pass)
+ pop_sec_ctx();
+#endif
/*
* If unix password sync was requested, attempt to change
@@ -951,7 +986,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
*/
if(lp_unix_password_sync() &&
- !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) {
+ !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) {
return NT_STATUS_ACCESS_DENIED;
}
diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
index 46f688a219..19f225e973 100644
--- a/source3/smbd/quotas.c
+++ b/source3/smbd/quotas.c
@@ -50,33 +50,16 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B
#ifdef LINUX
#include <sys/types.h>
-#include <asm/types.h>
+#include <mntent.h>
/*
* This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
+ * So we include all the files has *should* be in the system into a large,
+ * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
*/
-#include <linux/quota.h>
-#ifdef HAVE_LINUX_XQM_H
-#include <linux/xqm.h>
-#else
-#ifdef HAVE_XFS_XQM_H
-#include <xfs/xqm.h>
-#define HAVE_LINUX_XQM_H
-#endif
-#endif
-
-#include <mntent.h>
-#include <linux/unistd.h>
-
-
-#define LINUX_QUOTAS_2
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
typedef struct _LINUX_SMB_DISK_QUOTA {
SMB_BIG_UINT bsize;
@@ -92,22 +75,20 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
Abstract out the XFS Quota Manager quota get call.
****************************************************************************/
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret = -1;
-#ifdef HAVE_LINUX_XQM_H
struct fs_disk_quota D;
+ int ret;
ZERO_STRUCT(D);
- ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+ ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D);
- /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */
- if (ret) {
- ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
- if (ret)
- return ret;
- }
+ if (ret)
+ ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret)
+ return ret;
dp->bsize = (SMB_BIG_UINT)512;
dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
@@ -116,7 +97,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
dp->curinodes = (SMB_BIG_UINT)D.d_icount;
dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-#endif
+
return ret;
}
@@ -124,48 +105,90 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
Abstract out the old and new Linux quota get calls.
****************************************************************************/
-static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
{
- int ret = 0;
-#ifdef LINUX_QUOTAS_1
- struct dqblk D;
+ struct v1_kern_dqblk D;
+ int ret;
+
ZERO_STRUCT(D);
- dp->bsize = (SMB_BIG_UINT)1024;
-#else /* LINUX_QUOTAS_2 */
- struct mem_dqblk D;
+
+ ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ return ret;
+
+ dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+ return ret;
+}
+
+static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+ struct v2_kern_dqblk D;
+ int ret;
+
ZERO_STRUCT(D);
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
+
+ ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+ if (ret && errno != EDQUOT)
+ return ret;
+
dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-#endif
+ dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+ dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+ dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+ dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+ dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+ dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
+
+ return ret;
+}
+
+/****************************************************************************
+ Brand-new generic quota interface.
+****************************************************************************/
+
+static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+ struct if_dqblk D;
+ int ret;
+
+ ZERO_STRUCT(D);
ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
- /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */
- if (ret) {
- ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
- if (ret)
- return ret;
- }
+ if (ret && errno != EDQUOT)
+ ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+ if (ret && errno != EDQUOT)
+ return ret;
+
+ dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-
-#ifdef LINUX_QUOTAS_1
- dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-#else /* LINUX_QUOTAS_2 */
- dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
-#endif
+ dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
return ret;
}
/****************************************************************************
-try to get the disk space from disk quotas (LINUX version)
+ Try to get the disk space from disk quotas (LINUX version).
****************************************************************************/
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
@@ -178,9 +201,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
SMB_DEV_T devno;
int found;
uid_t euser_id;
+ gid_t egrp_id;
euser_id = geteuid();
-
+ egrp_id = getegid();
+
/* find the block device file */
if ( sys_stat(path, &S) == -1 )
@@ -208,10 +233,18 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
save_re_uid();
set_effective_uid(0);
- if (strcmp(mnt->mnt_type, "xfs") == 0)
- r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
- else
- r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D);
+
+ if (strcmp(mnt->mnt_type, "xfs")==0) {
+ r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ } else {
+ r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ if (r == -1 && errno != EDQUOT) {
+ r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ if (r == -1 && errno != EDQUOT)
+ r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+ }
+ }
+
restore_re_uid();
/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -920,8 +953,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
#else
if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0))
-#endif /* ifdef HPUX */
return (False);
+#endif /* ifdef HPUX */
#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index c98b0936ed..ff70750385 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -853,6 +853,8 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
tdb_off rec_ptr, last_ptr, newrec_ptr;
struct list_struct newrec;
+ memset(&newrec, '\0', sizeof(newrec));
+
if (tdb_lock(tdb, -1, F_WRLCK) == -1)
return 0;
diff --git a/source3/tests/crack.c b/source3/tests/crack.c
new file mode 100644
index 0000000000..1342887852
--- /dev/null
+++ b/source3/tests/crack.c
@@ -0,0 +1,5 @@
+
+int main(int argc, char **argv) {
+ FascistCheck("Foo", CRACKLIB_DICTPATH);
+ return 0;
+}
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index b28365274c..9f0f64edec 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -48,27 +48,14 @@ typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_C
* @return The Domain SID of the remote machine.
**/
-static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
+static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx)
{
DOM_SID *domain_sid;
POLICY_HND pol;
NTSTATUS result = NT_STATUS_OK;
uint32 info_class = 5;
- fstring domain_name;
- TALLOC_CTX *mem_ctx;
+ char *domain_name;
- if (!(domain_sid = malloc(sizeof(DOM_SID)))){
- DEBUG(0,("net_get_remote_domain_sid: malloc returned NULL!\n"));
- goto error;
- }
-
- if (!(mem_ctx=talloc_init("net_get_remote_domain_sid")))
- {
- DEBUG(0,("net_get_remote_domain_sid: talloc_init returned NULL!\n"));
- goto error;
- }
-
-
if (!cli_nt_session_open (cli, PI_LSARPC)) {
fprintf(stderr, "could not initialise lsa pipe\n");
goto error;
@@ -82,7 +69,7 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
}
result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
- domain_name, domain_sid);
+ &domain_name, &domain_sid);
if (!NT_STATUS_IS_OK(result)) {
error:
fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
@@ -96,7 +83,6 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
cli_lsa_close(cli, mem_ctx, &pol);
cli_nt_session_close(cli);
- talloc_destroy(mem_ctx);
return domain_sid;
}
@@ -132,7 +118,7 @@ static int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int co
return -1;
}
- domain_sid = net_get_remote_domain_sid(cli);
+ domain_sid = net_get_remote_domain_sid(cli, mem_ctx);
/* Create mem_ctx */
@@ -1928,10 +1914,11 @@ static int rpc_trustdom_establish(int argc, const char **argv)
POLICY_HND connect_hnd;
TALLOC_CTX *mem_ctx;
NTSTATUS nt_status;
- DOM_SID domain_sid;
+ DOM_SID *domain_sid;
WKS_INFO_100 wks_info;
char* domain_name;
+ char* domain_name_pol;
char* acct_name;
fstring pdc_name;
@@ -2052,7 +2039,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
/* Querying info level 5 */
nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
- 5 /* info level */, domain_name,
+ 5 /* info level */, &domain_name_pol,
&domain_sid);
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2072,7 +2059,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
wks_info.uni_lan_grp.uni_str_len, opt_password,
- domain_sid)) {
+ *domain_sid)) {
DEBUG(0, ("Storing password for trusted domain failed.\n"));
return -1;
}
@@ -2163,7 +2150,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
struct cli_state *cli, *remote_cli;
NTSTATUS nt_status;
const char *domain_name = NULL;
- DOM_SID queried_dom_sid;
+ DOM_SID *queried_dom_sid;
fstring ascii_sid, padding;
int ascii_dom_name_len;
POLICY_HND connect_hnd;
@@ -2173,7 +2160,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
int i, pad_len, col_len = 20;
DOM_SID *domain_sids;
char **trusted_dom_names;
- fstring pdc_name, dummy;
+ fstring pdc_name;
+ char *dummy;
/* trusting domains listing variables */
POLICY_HND domain_hnd;
@@ -2222,7 +2210,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
/* query info level 5 to obtain sid of a domain being queried */
nt_status = cli_lsa_query_info_policy(
cli, mem_ctx, &connect_hnd, 5 /* info level */,
- dummy, &queried_dom_sid);
+ &dummy, &queried_dom_sid);
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2304,8 +2292,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
/* SamrOpenDomain - we have to open domain policy handle in order to be
able to enumerate accounts*/
nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
- SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
- &queried_dom_sid, &domain_hnd);
+ SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+ queried_dom_sid, &domain_hnd);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Couldn't open domain object. Error was %s\n",
nt_errstr(nt_status)));
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 96e52964b4..74918045ee 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -1072,6 +1072,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
DATA_BLOB session_key_krb5;
SPNEGO_DATA reply;
char *reply_base64;
+ int retval;
const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
ssize_t len;
@@ -1093,9 +1094,9 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
spnego.negTokenInit.mechListMIC.length);
principal[spnego.negTokenInit.mechListMIC.length] = '\0';
- tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
- if (tkt.data == NULL) {
+ if (retval) {
pstring user;
@@ -1110,13 +1111,17 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
- if (kerberos_kinit_password(user, opt_password, 0) != 0) {
- DEBUG(10, ("Requesting TGT failed\n"));
+ if ((retval = kerberos_kinit_password(user, opt_password, 0))) {
+ DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
x_fprintf(x_stdout, "NA\n");
return True;
}
- tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
+
+ if (retval) {
+ DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
+ }
}
data_blob_free(&session_key_krb5);
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index eae1f97b58..8a27684a4d 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -717,7 +717,7 @@ int main(int argc, const char **argv)
argc -= 2;
break;
case 's': /* --configfile */
- pstrcpy(dyn_CONFIGFILE, optarg);
+ pstrcpy(dyn_CONFIGFILE, poptGetOptArg(pc));
argc -= 2;
break;
default:
diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c
new file mode 100644
index 0000000000..92a3831752
--- /dev/null
+++ b/source3/utils/smbget.c
@@ -0,0 +1,574 @@
+/*
+ smbget: a wget-like utility with support for recursive downloading and
+ smb:// urls
+ Copyright (C) 2003-2004 Jelmer Vernooij <jelmer@samba.org>
+
+ 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. */
+
+#include "includes.h"
+#include "libsmbclient.h"
+
+#if _FILE_OFFSET_BITS==64
+#define OFF_T_FORMAT "%lld"
+#else
+#define OFF_T_FORMAT "%ld"
+#endif
+
+int columns = 0;
+
+time_t total_start_time = 0;
+off_t total_bytes = 0;
+
+#define SMB_MAXPATHLEN MAXPATHLEN
+
+/* Number of bytes to read when checking whether local and remote file are really the same file */
+#define RESUME_CHECK_SIZE 512
+#define RESUME_DOWNLOAD_OFFSET 1024
+#define RESUME_CHECK_OFFSET RESUME_DOWNLOAD_OFFSET+RESUME_CHECK_SIZE
+/* Number of bytes to read at once */
+#define SMB_DEFAULT_BLOCKSIZE 64000
+
+const char *username = NULL, *password = NULL, *workgroup = NULL;
+int nonprompt = 0, quiet = 0, dots = 0, keep_permissions = 0, verbose = 0;
+int blocksize = SMB_DEFAULT_BLOCKSIZE;
+
+int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile);
+
+int get_num_cols(void)
+{
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+ if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {
+ perror("ioctl");
+ return 0;
+ }
+ return ws.ws_col;
+#else
+#warning No support for TIOCGWINSZ
+ char *cols = getenv("COLUMNS");
+ if(!cols) return 0;
+ return atoi(cols);
+#endif
+}
+
+void change_columns(int sig)
+{
+ columns = get_num_cols();
+}
+
+void human_readable(off_t s, char *buffer, int l)
+{
+ if(s > 1024 * 1024 * 1024) snprintf(buffer, l, "%.2fGb", 1.0 * s / (1024 * 1024 * 1024));
+ else if(s > 1024 * 1024) snprintf(buffer, l, "%.2fMb", 1.0 * s / (1024 * 1024));
+ else if(s > 1024) snprintf(buffer, l, "%.2fkb", 1.0 * s / 1024);
+ else snprintf(buffer, l, OFF_T_FORMAT"b", s);
+}
+
+void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
+{
+ static char hasasked = 0;
+ char *wgtmp, *usertmp;
+ char tmp[128];
+
+ if(hasasked) return;
+ hasasked = 1;
+
+ if(!nonprompt && !username) {
+ printf("Username for %s at %s [guest] ", shr, srv);
+ fgets(tmp, sizeof(tmp), stdin);
+ if(tmp[strlen(tmp)-1] == '\n')tmp[strlen(tmp)-1] = '\0';
+ strncpy(un, tmp, unlen-1);
+ } else if(username) strncpy(un, username, unlen-1);
+
+ if(!nonprompt && !password) {
+ char *prompt, *pass;
+ asprintf(&prompt, "Password for %s at %s: ", shr, srv);
+ pass = getpass(prompt);
+ free(prompt);
+ strncpy(pw, pass, pwlen-1);
+ } else if(password) strncpy(pw, password, pwlen-1);
+
+ if(workgroup)strncpy(wg, workgroup, wglen-1);
+
+ wgtmp = strndup(wg, wglen);
+ usertmp = strndup(un, unlen);
+ if(!quiet)printf("Using workgroup %s, %s%s\n", wgtmp, *usertmp?"user ":"guest user", usertmp);
+ free(wgtmp); free(usertmp);
+}
+
+int smb_download_dir(const char *base, const char *name, int resume)
+{
+ char path[SMB_MAXPATHLEN];
+ int dirhandle;
+ struct smbc_dirent *dirent;
+ const char *relname = name;
+ char *tmpname;
+ struct stat remotestat;
+ snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (base[0] && name[0] && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name);
+
+ /* List files in directory and call smb_download_file on them */
+ dirhandle = smbc_opendir(path);
+ if(dirhandle < 1) {
+ if(errno == ENOTDIR) return smb_download_file(base, name, 1, resume, NULL);
+ fprintf(stderr, "Can't open directory %s: %s\n", path, strerror(errno));
+ return 0;
+ }
+
+ while(*relname == '/')relname++;
+ mkdir(relname, 0755);
+
+ tmpname = strdup(name);
+
+ while((dirent = smbc_readdir(dirhandle))) {
+ char *newname;
+ if(!strcmp(dirent->name, ".") || !strcmp(dirent->name, ".."))continue;
+ asprintf(&newname, "%s/%s", tmpname, dirent->name);
+ switch(dirent->smbc_type) {
+ case SMBC_DIR:
+ smb_download_dir(base, newname, resume);
+ break;
+
+ case SMBC_WORKGROUP:
+ smb_download_dir("smb://", dirent->name, resume);
+ break;
+
+ case SMBC_SERVER:
+ smb_download_dir("smb://", dirent->name, resume);
+ break;
+
+ case SMBC_FILE:
+ smb_download_file(base, newname, 1, resume, NULL);
+ break;
+
+ case SMBC_FILE_SHARE:
+ smb_download_dir(base, newname, resume);
+ break;
+
+ case SMBC_PRINTER_SHARE:
+ if(!quiet)printf("Ignoring printer share %s\n", dirent->name);
+ break;
+
+ case SMBC_COMMS_SHARE:
+ if(!quiet)printf("Ignoring comms share %s\n", dirent->name);
+ break;
+
+ case SMBC_IPC_SHARE:
+ if(!quiet)printf("Ignoring ipc$ share %s\n", dirent->name);
+ break;
+
+ default:
+ fprintf(stderr, "Ignoring file '%s' of type '%d'\n", newname, dirent->smbc_type);
+ break;
+ }
+ free(newname);
+ }
+ free(tmpname);
+
+ if(keep_permissions) {
+ if(smbc_fstat(dirhandle, &remotestat) < 0) {
+ fprintf(stderr, "Unable to get stats on %s on remote server\n", path);
+ smbc_closedir(dirhandle);
+ return 0;
+ }
+
+ if(chmod(relname, remotestat.st_mode) < 0) {
+ fprintf(stderr, "Unable to change mode of local dir %s to %o\n", relname, remotestat.st_mode);
+ smbc_closedir(dirhandle);
+ return 0;
+ }
+ }
+
+ smbc_closedir(dirhandle);
+ return 1;
+}
+
+char *print_time(long t)
+{
+ static char buffer[100];
+ int secs, mins, hours;
+ if(t < -1) {
+ strncpy(buffer, "Unknown", sizeof(buffer));
+ return buffer;
+ }
+
+ secs = (int)t % 60;
+ mins = (int)t / 60 % 60;
+ hours = (int)t / (60 * 60);
+ snprintf(buffer, sizeof(buffer)-1, "%02d:%02d:%02d", hours, mins, secs);
+ return buffer;
+}
+
+void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total)
+{
+ double avg = 0.0;
+ long eta = -1;
+ double prcnt = 0.0;
+ char hpos[20], htotal[20], havg[20];
+ char *status, *filename;
+ int len;
+ if(now - start)avg = 1.0 * (pos - start_pos) / (now - start);
+ eta = (total - pos - start_pos) / avg;
+ if(total)prcnt = 100.0 * pos / total;
+
+ human_readable(pos, hpos, sizeof(hpos));
+ human_readable(total, htotal, sizeof(htotal));
+ human_readable(avg, havg, sizeof(havg));
+
+ len = asprintf(&status, "%s of %s (%.2f%%) at %s/s ETA: %s", hpos, htotal, prcnt, havg, print_time(eta));
+
+ if(columns) {
+ int required = strlen(name), available = columns - len - strlen("[] ");
+ if(required > available) asprintf(&filename, "...%s", name + required - available + 3);
+ else filename = strndup(name, available);
+ } else filename = strdup(name);
+
+ fprintf(stderr, "\r[%s] %s", filename, status);
+
+ free(filename); free(status);
+}
+
+int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile) {
+ int remotehandle, localhandle;
+ time_t start_time = time(NULL);
+ const char *newpath;
+ char path[SMB_MAXPATHLEN];
+ char checkbuf[2][RESUME_CHECK_SIZE];
+ char *readbuf = NULL;
+ off_t offset_download = 0, offset_check = 0, curpos = 0, start_offset = 0;
+ struct stat localstat, remotestat;
+
+ snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (*base && *name && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name);
+
+ remotehandle = smbc_open(path, O_RDONLY, 0755);
+
+ if(remotehandle < 0) {
+ switch(errno) {
+ case EISDIR:
+ if(!recursive) {
+ fprintf(stderr, "%s is a directory. Specify -R to download recursively\n", path);
+ return 0;
+ }
+ smb_download_dir(base, name, resume);
+ return 0;
+
+ case ENOENT:
+ fprintf(stderr, "%s can't be found on the remote server\n", path);
+ return 0;
+
+ case ENOMEM:
+ fprintf(stderr, "Not enough memory\n");
+ exit(1);
+ return 0;
+
+ case ENODEV:
+ fprintf(stderr, "The share name used in %s does not exist\n", path);
+ return 0;
+
+ case EACCES:
+ fprintf(stderr, "You don't have enough permissions to access %s\n", path);
+ return 0;
+
+ default:
+ perror("smbc_open");
+ return 0;
+ }
+ }
+
+ if(smbc_fstat(remotehandle, &remotestat) < 0) {
+ fprintf(stderr, "Can't stat %s: %s\n", path, strerror(errno));
+ return 0;
+ }
+
+ if(outfile) newpath = outfile;
+ else if(!name[0]) {
+ newpath = strrchr(base, '/');
+ if(newpath)newpath++; else newpath = base;
+ } else newpath = name;
+
+ if(newpath[0] == '/')newpath++;
+
+ /* Open local file and, if necessary, resume */
+ localhandle = open(newpath, O_CREAT | O_NONBLOCK | O_RDWR | (!resume?O_EXCL:0), 0755);
+ if(localhandle < 0) {
+ fprintf(stderr, "Can't open %s: %s\n", newpath, strerror(errno));
+ smbc_close(remotehandle);
+ return 0;
+ }
+
+ fstat(localhandle, &localstat);
+
+ start_offset = localstat.st_size;
+
+ if(localstat.st_size && localstat.st_size == remotestat.st_size) {
+ if(verbose)fprintf(stderr, "%s is already downloaded completely.\n", path);
+ else if(!quiet)fprintf(stderr, "%s\n", path);
+ smbc_close(remotehandle);
+ close(localhandle);
+ return 1;
+ }
+
+ if(localstat.st_size > RESUME_CHECK_OFFSET && remotestat.st_size > RESUME_CHECK_OFFSET) {
+ offset_download = localstat.st_size - RESUME_DOWNLOAD_OFFSET;
+ offset_check = localstat.st_size - RESUME_CHECK_OFFSET;
+ if(verbose)printf("Trying to start resume of %s at "OFF_T_FORMAT"\n"
+ "At the moment "OFF_T_FORMAT" of "OFF_T_FORMAT" bytes have been retrieved\n", newpath, offset_check,
+ localstat.st_size, remotestat.st_size);
+ }
+
+ if(offset_check) {
+ off_t off1, off2;
+ /* First, check all bytes from offset_check to offset_download */
+ off1 = lseek(localhandle, offset_check, SEEK_SET);
+ if(off1 < 0) {
+ fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in local file %s\n", offset_check, newpath);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+
+ off2 = smbc_lseek(remotehandle, offset_check, SEEK_SET);
+ if(off2 < 0) {
+ fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in remote file %s\n", offset_check, newpath);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+
+ if(off1 != off2) {
+ fprintf(stderr, "Offset in local and remote files is different (local: "OFF_T_FORMAT", remote: "OFF_T_FORMAT")\n", off1, off2);
+ return 0;
+ }
+
+ if(smbc_read(remotehandle, checkbuf[0], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) {
+ fprintf(stderr, "Can't read %d bytes from remote file %s\n", RESUME_CHECK_SIZE, path);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+
+ if(read(localhandle, checkbuf[1], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) {
+ fprintf(stderr, "Can't read %d bytes from local file %s\n", RESUME_CHECK_SIZE, name);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+
+ if(memcmp(checkbuf[0], checkbuf[1], RESUME_CHECK_SIZE) == 0) {
+ if(verbose)printf("Current local and remote file appear to be the same. Starting download from offset "OFF_T_FORMAT"\n", offset_download);
+ } else {
+ fprintf(stderr, "Local and remote file appear to be different, not doing resume for %s\n", path);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+ }
+
+ readbuf = malloc(blocksize);
+
+ /* Now, download all bytes from offset_download to the end */
+ for(curpos = offset_download; curpos < remotestat.st_size; curpos+=blocksize) {
+ ssize_t bytesread = smbc_read(remotehandle, readbuf, blocksize);
+ if(bytesread < 0) {
+ fprintf(stderr, "Can't read %d bytes at offset "OFF_T_FORMAT", file %s\n", blocksize, curpos, path);
+ smbc_close(remotehandle); close(localhandle);
+ free(readbuf);
+ return 0;
+ }
+
+ total_bytes += bytesread;
+
+ if(write(localhandle, readbuf, bytesread) < 0) {
+ fprintf(stderr, "Can't write %d bytes to local file %s at offset "OFF_T_FORMAT"\n", bytesread, path, curpos);
+ free(readbuf);
+ smbc_close(remotehandle); close(localhandle);
+ return 0;
+ }
+
+ if(dots)fputc('.', stderr);
+ else if(!quiet) {
+ print_progress(newpath, start_time, time(NULL), start_offset, curpos, remotestat.st_size);
+ }
+ }
+
+ free(readbuf);
+
+ if(dots){
+ fputc('\n', stderr);
+ printf("%s downloaded\n", path);
+ } else if(!quiet) {
+ int i;
+ fprintf(stderr, "\r%s", path);
+ if(columns) {
+ for(i = strlen(path); i < columns; i++) {
+ fputc(' ', stderr);
+ }
+ }
+ fputc('\n', stderr);
+ }
+
+ if(keep_permissions) {
+ if(fchmod(localhandle, remotestat.st_mode) < 0) {
+ fprintf(stderr, "Unable to change mode of local file %s to %o\n", path, remotestat.st_mode);
+ smbc_close(remotehandle);
+ close(localhandle);
+ return 0;
+ }
+ }
+ smbc_close(remotehandle);
+ close(localhandle);
+ return 1;
+}
+
+void clean_exit(void)
+{
+ char bs[100];
+ human_readable(total_bytes, bs, sizeof(bs));
+ if(!quiet)fprintf(stderr, "Downloaded %s in %lu seconds\n", bs, time(NULL) - total_start_time);
+ exit(0);
+}
+
+void signal_quit(int v)
+{
+ clean_exit();
+}
+
+int readrcfile(const char *name, const struct poptOption long_options[])
+{
+ FILE *fd = fopen(name, "r");
+ int lineno = 0, i;
+ char var[101], val[101];
+ char found;
+ int *intdata; char **stringdata;
+ if(!fd) {
+ fprintf(stderr, "Can't open RC file %s\n", name);
+ return 1;
+ }
+
+ while(!feof(fd)) {
+ lineno++;
+ if(fscanf(fd, "%100s %100s\n", var, val) < 2) {
+ fprintf(stderr, "Can't parse line %d of %s, ignoring.\n", lineno, name);
+ continue;
+ }
+
+ found = 0;
+
+ for(i = 0; long_options[i].shortName; i++) {
+ if(!long_options[i].longName)continue;
+ if(strcmp(long_options[i].longName, var)) continue;
+ if(!long_options[i].arg)continue;
+
+ switch(long_options[i].argInfo) {
+ case POPT_ARG_NONE:
+ intdata = (int *)long_options[i].arg;
+ if(!strcmp(val, "on")) *intdata = 1;
+ else if(!strcmp(val, "off")) *intdata = 0;
+ else fprintf(stderr, "Illegal value %s for %s at line %d in %s\n", val, var, lineno, name);
+ break;
+ case POPT_ARG_INT:
+ intdata = (int *)long_options[i].arg;
+ *intdata = atoi(val);
+ break;
+ case POPT_ARG_STRING:
+ stringdata = (char **)long_options[i].arg;
+ *stringdata = strdup(val);
+ break;
+ default:
+ fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name);
+ break;
+ }
+
+ found = 1;
+ }
+ if(!found) {
+ fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name);
+ }
+ }
+
+ fclose(fd);
+ return 0;
+}
+
+int main(int argc, const char **argv)
+{
+ int resume = 0, recursive = 0;
+ int c = 0;
+ int debuglevel = 0;
+ const char *file = NULL;
+ char *rcfile = NULL;
+ char *outputfile = NULL;
+ struct poptOption long_options[] = {
+ {"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },
+ {"resume", 'r', POPT_ARG_NONE, &resume, 0, "Automatically resume aborted files" },
+ {"recursive", 'R', POPT_ARG_NONE, &recursive, 0, "Recursively download files" },
+ {"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },
+ {"password", 'p', POPT_ARG_STRING, &password, 'p', "Password to use" },
+ {"workgroup", 'w', POPT_ARG_STRING, &workgroup, 'w', "Workgroup to use (optional)" },
+ {"nonprompt", 'n', POPT_ARG_NONE, &nonprompt, 'n', "Don't ask anything (non-interactive)" },
+ {"debuglevel", 'd', POPT_ARG_INT, &debuglevel, 'd', "Debuglevel to use" },
+ {"outputfile", 'o', POPT_ARG_STRING, &outputfile, 'o', "Write downloaded data to specified file" },
+ {"dots", 'D', POPT_ARG_NONE, &dots, 'D', "Show dots as progress indication" },
+ {"quiet", 'q', POPT_ARG_NONE, &quiet, 'q', "Be quiet" },
+ {"verbose", 'v', POPT_ARG_NONE, &verbose, 'v', "Be verbose" },
+ {"keep-permissions", 'P', POPT_ARG_NONE, &keep_permissions, 'P', "Keep permissions" },
+ {"blocksize", 'b', POPT_ARG_INT, &blocksize, 'b', "Change number of bytes in a block"},
+ {"rcfile", 'f', POPT_ARG_STRING, NULL, 0, "Use specified rc file"},
+ POPT_AUTOHELP
+ POPT_TABLEEND
+ };
+ poptContext pc;
+
+ /* only read rcfile if it exists */
+ asprintf(&rcfile, "%s/.smbgetrc", getenv("HOME"));
+ if(access(rcfile, F_OK) == 0) readrcfile(rcfile, long_options);
+ free(rcfile);
+
+#ifdef SIGWINCH
+ signal(SIGWINCH, change_columns);
+#endif
+ signal(SIGINT, signal_quit);
+ signal(SIGTERM, signal_quit);
+
+ pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+
+ while((c = poptGetNextOpt(pc)) >= 0) {
+ switch(c) {
+ case 'f':
+ readrcfile(poptGetOptArg(pc), long_options);
+ break;
+ case 'a':
+ username = ""; password = "";
+ break;
+ }
+ }
+
+ if(outputfile && recursive) {
+ fprintf(stderr, "The -o and -R options can not be used together.\n");
+ return 1;
+ }
+
+ if(smbc_init(get_auth_data, debuglevel) < 0) {
+ fprintf(stderr, "Unable to initialize libsmbclient\n");
+ return 1;
+ }
+
+ columns = get_num_cols();
+
+ total_start_time = time(NULL);
+
+ while((file = poptGetArg(pc))) {
+ if(!recursive) return smb_download_file(file, "", recursive, resume, outputfile);
+ else return smb_download_dir(file, "", resume);
+ }
+
+ clean_exit();
+
+ return 0;
+}