summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2007-03-20 16:56:16 +0000
committerGerald Carter <jerry@samba.org>2007-03-20 16:56:16 +0000
commit651d5a89c59c107c05e789358624058e16af1b66 (patch)
treedfd29754255ea87b30eb16a06c505e42f98b9be3 /source
parent0f475ed1a387e37d477fd434c06ad5783c58adea (diff)
downloadsamba-651d5a89c59c107c05e789358624058e16af1b66.tar.gz
samba-651d5a89c59c107c05e789358624058e16af1b66.tar.xz
samba-651d5a89c59c107c05e789358624058e16af1b66.zip
r21889: * Pull from SAMBA-3_0_25 svn r21888
* Set version to 3.0.25pre2
Diffstat (limited to 'source')
-rw-r--r--source/Makefile.in16
-rw-r--r--source/VERSION2
-rw-r--r--source/auth/auth_domain.c2
-rw-r--r--source/auth/auth_winbind.c3
-rw-r--r--source/client/client.c272
-rw-r--r--source/client/clitar.c4
-rwxr-xr-xsource/client/mount.cifs.c4
-rw-r--r--source/client/smbctool.c14
-rw-r--r--source/configure.in39
-rw-r--r--source/include/client.h30
-rw-r--r--source/include/doserr.h1
-rw-r--r--source/include/includes.h4
-rw-r--r--source/include/msdfs.h27
-rw-r--r--source/include/nt_printing.h9
-rw-r--r--source/include/rpc_secdes.h16
-rw-r--r--source/include/rpc_srvsvc.h246
-rw-r--r--source/include/smb.h5
-rw-r--r--source/include/smbprofile.h6
-rw-r--r--source/include/trans2.h95
-rw-r--r--source/include/vfs.h14
-rw-r--r--source/include/vfs_macros.h9
-rw-r--r--source/lib/debug.c10
-rw-r--r--source/lib/interface.c12
-rw-r--r--source/lib/ldap_escape.c44
-rw-r--r--source/lib/messages.c3
-rw-r--r--source/lib/smbldap_util.c47
-rw-r--r--source/lib/system.c29
-rw-r--r--source/lib/time.c156
-rw-r--r--source/lib/util.c34
-rw-r--r--source/libaddns/dnsgss.c10
-rw-r--r--source/libads/cldap.c9
-rw-r--r--source/libads/kerberos_keytab.c30
-rw-r--r--source/libads/kerberos_verify.c103
-rw-r--r--source/libads/krb5_errs.c2
-rw-r--r--source/libads/ldap.c11
-rw-r--r--source/libads/ldap_user.c12
-rw-r--r--source/libads/sasl.c32
-rw-r--r--source/libads/smb_krb5_locator.c386
-rw-r--r--source/librpc/ndr/libndr.h2
-rw-r--r--source/librpc/ndr/ndr.c12
-rw-r--r--source/libsmb/cliconnect.c5
-rw-r--r--source/libsmb/clidfs.c328
-rw-r--r--source/libsmb/clifile.c197
-rw-r--r--source/libsmb/clikrb5.c39
-rw-r--r--source/libsmb/clilist.c10
-rw-r--r--source/libsmb/cliquota.c2
-rw-r--r--source/libsmb/clirap.c200
-rw-r--r--source/libsmb/doserr.c4
-rw-r--r--source/libsmb/errormap.c4
-rw-r--r--source/libsmb/libsmbclient.c15
-rw-r--r--source/locking/brlock.c3
-rw-r--r--source/locking/locking.c51
-rw-r--r--source/modules/nfs4_acls.c50
-rw-r--r--source/modules/vfs_cap.c6
-rw-r--r--source/modules/vfs_catia.c8
-rw-r--r--source/modules/vfs_default.c46
-rw-r--r--source/modules/vfs_full_audit.c60
-rw-r--r--source/modules/vfs_netatalk.c8
-rw-r--r--source/modules/vfs_recycle.c39
-rw-r--r--source/nsswitch/idmap.c39
-rw-r--r--source/nsswitch/idmap_ldap.c3
-rw-r--r--source/nsswitch/pam_winbind.c3
-rw-r--r--source/nsswitch/wb_common.c47
-rw-r--r--source/nsswitch/winbind_client.h7
-rw-r--r--source/nsswitch/winbind_nss_irix.c2
-rw-r--r--source/nsswitch/winbindd.c17
-rw-r--r--source/nsswitch/winbindd.h2
-rw-r--r--source/nsswitch/winbindd_ads.c18
-rw-r--r--source/nsswitch/winbindd_cred_cache.c1
-rw-r--r--source/nsswitch/winbindd_dual.c4
-rw-r--r--source/nsswitch/winbindd_group.c10
-rw-r--r--source/nsswitch/winbindd_pam.c34
-rw-r--r--source/nsswitch/winbindd_rpc.c6
-rw-r--r--source/nsswitch/winbindd_user.c8
-rw-r--r--source/param/loadparm.c18
-rw-r--r--source/passdb/lookup_sid.c14
-rw-r--r--source/passdb/pdb_ldap.c71
-rw-r--r--source/printing/nt_printing.c80
-rw-r--r--source/printing/print_cups.c139
-rw-r--r--source/profile/profile.c2
-rw-r--r--source/rpc_client/cli_srvsvc.c29
-rw-r--r--source/rpc_parse/parse_srv.c524
-rw-r--r--source/rpc_server/srv_dfs_nt.c12
-rw-r--r--source/rpc_server/srv_pipe_hnd.c7
-rw-r--r--source/rpc_server/srv_samr_nt.c2
-rw-r--r--source/rpc_server/srv_srvsvc.c33
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c420
-rw-r--r--source/rpcclient/cmd_samr.c1
-rw-r--r--source/smbd/close.c4
-rw-r--r--source/smbd/dir.c6
-rw-r--r--source/smbd/dosmode.c36
-rw-r--r--source/smbd/fileio.c4
-rw-r--r--source/smbd/files.c6
-rw-r--r--source/smbd/msdfs.c841
-rw-r--r--source/smbd/negprot.c4
-rw-r--r--source/smbd/notify_inotify.c4
-rw-r--r--source/smbd/nttrans.c138
-rw-r--r--source/smbd/open.c3
-rw-r--r--source/smbd/pipes.c2
-rw-r--r--source/smbd/process.c23
-rw-r--r--source/smbd/reply.c678
-rw-r--r--source/smbd/sesssetup.c236
-rw-r--r--source/smbd/trans2.c711
-rw-r--r--source/tdb/common/open.c10
-rw-r--r--source/tdb/common/tdb.c181
-rw-r--r--source/tdb/common/tdb_private.h1
-rw-r--r--source/tdb/include/tdb.h1
-rw-r--r--source/torture/cmd_vfs.c8
-rw-r--r--source/torture/nsstest.c6
-rw-r--r--source/torture/torture.c5
-rw-r--r--source/utils/net_ads.c125
-rw-r--r--source/utils/net_ads_gpo.c1
-rw-r--r--source/utils/net_rpc.c30
-rw-r--r--source/utils/net_sam.c14
-rw-r--r--source/utils/net_status.c4
-rw-r--r--source/utils/ntlm_auth.c3
-rw-r--r--source/utils/pdbedit.c1
-rw-r--r--source/utils/smbcontrol.c28
-rw-r--r--source/utils/status.c4
-rw-r--r--source/utils/status_profile.c4
-rw-r--r--source/web/statuspage.c2
121 files changed, 5296 insertions, 2218 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index 3f3aa5ea57a..f27fed1f391 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -159,7 +159,8 @@ TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ \
bin/pdbtest@EXEEXT@ bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@
-BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@
+BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@ \
+ @SMBMOUNT_PROGS@
EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ \
bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@ \
@@ -788,6 +789,10 @@ WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @WINBIND_NSS_EXTRA_OBJS@
+SMB_KRB5_LOCATOR_OBJ1 = libads/smb_krb5_locator.o
+SMB_KRB5_LOCATOR_OBJ = $(SMB_KRB5_LOCATOR_OBJ1) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
+ $(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(DOSERR_OBJ)
+
POPT_OBJ=popt/findme.o popt/popt.o popt/poptconfig.o \
popt/popthelp.o popt/poptparse.o
@@ -1275,6 +1280,12 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
$(LDAP_LIBS) $(KRB5LIBS) $(LIBS) \
@SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
+@SMB_KRB5_LOCATOR@: $(SMB_KRB5_LOCATOR_OBJ)
+ @echo "Linking $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(SMB_KRB5_LOCATOR_OBJ) \
+ $(LDAP_LIBS) $(LIBS) -lcom_err \
+ @SONAMEFLAG@`basename $@`
+
bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy
@echo "Linking shared library $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) -lpam @INIPARSERLIBS@ $(GPLIBS) \
@@ -1655,7 +1666,8 @@ revert:
@$(SHELL) $(srcdir)/script/revert.sh $(BINDIR) $(BIN_PROGS) $(SCRIPTS)
installman: installdirs
- @$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
+ @SMBMOUNT_PROGS="@SMBMOUNT_PROGS@" $(SHELL) \
+ $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
.PHONY: showlayout
diff --git a/source/VERSION b/source/VERSION
index fc1f872b07a..4d4416c8ee3 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -47,7 +47,7 @@ SAMBA_VERSION_REVISION=
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=2
########################################################
# For 'rc' releases the version will be #
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index 6468c18cb0e..a32677d0370 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -237,7 +237,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
user_info->logon_parameters,/* flags such as 'allow workstation logon' */
dc_name, /* server name */
user_info->smb_name, /* user name logging on. */
- user_info->domain, /* domain name */
+ user_info->client_domain, /* domain name */
user_info->wksta_name, /* workstation name */
chal, /* 8 byte challenge. */
user_info->lm_resp, /* lanman 24 byte response */
diff --git a/source/auth/auth_winbind.c b/source/auth/auth_winbind.c
index fa56757950d..f06f83f4065 100644
--- a/source/auth/auth_winbind.c
+++ b/source/auth/auth_winbind.c
@@ -108,7 +108,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
/* we are contacting the privileged pipe */
become_root();
- result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+ result = winbindd_priv_request_response(WINBINDD_PAM_AUTH_CRAP,
+ &request, &response);
unbecome_root();
if ( result == NSS_STATUS_UNAVAIL ) {
diff --git a/source/client/client.c b/source/client/client.c
index 8ed3f1dc21e..e95b9ed9ce3 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -271,19 +271,17 @@ static int do_cd(char *newdir)
pstrcpy(saved_dir, cur_dir);
- if (*p == CLI_DIRSEP_CHAR)
+ if (*p == CLI_DIRSEP_CHAR) {
pstrcpy(cur_dir,p);
- else
+ } else {
pstrcat(cur_dir,p);
-
- if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
- pstrcat(cur_dir, CLI_DIRSEP_STR);
+ if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
+ pstrcat(cur_dir, CLI_DIRSEP_STR);
+ }
}
- dos_clean_name(cur_dir);
+ clean_name(cur_dir);
pstrcpy( dname, cur_dir );
- pstrcat(cur_dir,CLI_DIRSEP_STR);
- dos_clean_name(cur_dir);
if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
d_printf("cd %s: %s\n", dname, cli_errstr(cli));
@@ -291,9 +289,9 @@ static int do_cd(char *newdir)
goto out;
}
-
- if ( strequal(targetpath,CLI_DIRSEP_STR ) )
- return 0;
+ if (strequal(targetpath,CLI_DIRSEP_STR )) {
+ return 0;
+ }
/* Use a trans2_qpathinfo to test directories for modern servers.
Except Win9x doesn't support the qpathinfo_basic() call..... */
@@ -312,7 +310,7 @@ static int do_cd(char *newdir)
}
} else {
pstrcat( targetpath, CLI_DIRSEP_STR );
- dos_clean_name( targetpath );
+ clean_name( targetpath );
if ( !cli_chkpath(targetcli, targetpath) ) {
d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
@@ -387,7 +385,7 @@ static void display_finfo(file_info *finfo)
finfo->name,
attrib_string(finfo->mode),
(double)finfo->size,
- time_to_asc(&t));
+ time_to_asc(t));
dir_total += finfo->size;
} else {
pstring afname;
@@ -398,25 +396,25 @@ static void display_finfo(file_info *finfo)
return;
/* create absolute filename for cli_nt_create() FIXME */
pstrcpy( afname, cwd);
- pstrcat( afname, "\\");
+ pstrcat( afname, CLI_DIRSEP_STR);
pstrcat( afname, finfo->name);
/* print file meta date header */
d_printf( "FILENAME:%s\n", afname);
d_printf( "MODE:%s\n", attrib_string(finfo->mode));
d_printf( "SIZE:%.0f\n", (double)finfo->size);
- d_printf( "MTIME:%s", time_to_asc(&t));
- fnum = cli_nt_create(cli, afname, CREATE_ACCESS_READ);
+ d_printf( "MTIME:%s", time_to_asc(t));
+ fnum = cli_nt_create(finfo->cli, afname, CREATE_ACCESS_READ);
if (fnum == -1) {
DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
afname,
- cli_errstr( cli)));
+ cli_errstr( finfo->cli)));
} else {
SEC_DESC *sd = NULL;
- sd = cli_query_secdesc(cli, fnum, ctx);
+ sd = cli_query_secdesc(finfo->cli, fnum, ctx);
if (!sd) {
DEBUG( 0, ("display_finfo() failed to "
"get security descriptor: %s",
- cli_errstr( cli)));
+ cli_errstr( finfo->cli)));
} else {
display_sec_desc(sd);
}
@@ -591,7 +589,8 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
return;
p[1] = 0;
pstrcat(mask2, f->name);
- pstrcat(mask2,"\\*");
+ pstrcat(mask2,CLI_DIRSEP_STR);
+ pstrcat(mask2,"*");
add_to_do_list_queue(mask2);
}
return;
@@ -714,6 +713,11 @@ static int cmd_dir(void)
pstrcat(mask,"*");
}
+ if (showacls) {
+ /* cwd is only used if showacls is on */
+ pstrcpy(cwd, cur_dir);
+ }
+
do_list(mask, attribute, display_finfo, recurse, True);
rc = do_dskattr();
@@ -790,17 +794,6 @@ static int do_get(char *rname, char *lname, BOOL reget)
GetTimeOfDay(&tp_start);
- if ( targetcli->dfsroot ) {
- pstring path;
-
- /* we need to refer to the full \server\share\path format
- for dfs shares */
-
- pstrcpy( path, targetname );
- cli_dfs_make_full_path( targetname, targetcli->desthost,
- targetcli->share, path);
- }
-
fnum = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE);
if (fnum == -1) {
@@ -924,7 +917,7 @@ static int cmd_get(void)
return 1;
}
pstrcpy(lname,p);
- dos_clean_name(rname);
+ clean_name(rname);
next_token_nr(NULL,lname,NULL,sizeof(lname));
@@ -1025,7 +1018,7 @@ static int cmd_more(void)
unlink(lname);
return 1;
}
- dos_clean_name(rname);
+ clean_name(rname);
rc = do_get(rname, lname, False);
@@ -1155,14 +1148,20 @@ static int cmd_mkdir(void)
if (recurse) {
pstring ddir;
pstring ddir2;
+ struct cli_state *targetcli;
+ pstring targetname;
*ddir2 = 0;
- pstrcpy(ddir,mask);
+ if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+ return 1;
+ }
+
+ pstrcpy(ddir,targetname);
trim_char(ddir,'.','\0');
p = strtok(ddir,"/\\");
while (p) {
pstrcat(ddir2,p);
- if (!cli_chkpath(cli, ddir2)) {
+ if (!cli_chkpath(targetcli, ddir2)) {
do_mkdir(ddir2);
}
pstrcat(ddir2,CLI_DIRSEP_STR);
@@ -1358,7 +1357,7 @@ static int cmd_put(void)
else
pstrcat(rname,lname);
- dos_clean_name(rname);
+ clean_name(rname);
{
SMB_STRUCT_STAT st;
@@ -1672,13 +1671,13 @@ static void do_del(file_info *finfo)
{
pstring mask;
- pstr_sprintf( mask, "%s\\%s", finfo->dir, finfo->name );
+ pstr_sprintf( mask, "%s%c%s", finfo->dir, CLI_DIRSEP_CHAR, finfo->name );
if (finfo->mode & aDIR)
return;
- if (!cli_unlink(cli, mask)) {
- d_printf("%s deleting remote file %s\n",cli_errstr(cli),mask);
+ if (!cli_unlink(finfo->cli, mask)) {
+ d_printf("%s deleting remote file %s\n",cli_errstr(finfo->cli),mask);
}
}
@@ -1717,6 +1716,8 @@ static int cmd_wdel(void)
pstring mask;
pstring buf;
uint16 attribute;
+ struct cli_state *targetcli;
+ pstring targetname;
if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
d_printf("wdel 0x<attrib> <wcard>\n");
@@ -1733,13 +1734,17 @@ static int cmd_wdel(void)
pstrcpy(mask,cur_dir);
pstrcat(mask,buf);
- if (!cli_unlink_full(cli, mask, attribute)) {
- d_printf("%s deleting remote files %s\n",cli_errstr(cli),mask);
+ if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+ d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_unlink_full(targetcli, targetname, attribute)) {
+ d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
}
return 0;
}
-
/****************************************************************************
****************************************************************************/
@@ -1779,6 +1784,146 @@ static int cmd_open(void)
return 0;
}
+/****************************************************************************
+****************************************************************************/
+
+static int cmd_posix_open(void)
+{
+ pstring mask;
+ pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
+ mode_t mode;
+ int fnum;
+
+ pstrcpy(mask,cur_dir);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_open <filename> 0<mode>\n");
+ return 1;
+ }
+ pstrcat(mask,buf);
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_open <filename> 0<mode>\n");
+ return 1;
+ }
+ mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+ if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+ d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode);
+ if (fnum == -1) {
+ fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode);
+ if (fnum != -1) {
+ d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+ } else {
+ d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+ }
+ } else {
+ d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+ }
+
+ return 0;
+}
+
+static int cmd_posix_mkdir(void)
+{
+ pstring mask;
+ pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
+ mode_t mode;
+ int fnum;
+
+ pstrcpy(mask,cur_dir);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_mkdir <filename> 0<mode>\n");
+ return 1;
+ }
+ pstrcat(mask,buf);
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_mkdir <filename> 0<mode>\n");
+ return 1;
+ }
+ mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+ if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+ d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ fnum = cli_posix_mkdir(targetcli, targetname, mode);
+ if (fnum == -1) {
+ d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+ } else {
+ d_printf("posix_mkdir created directory %s\n", targetname);
+ }
+
+ return 0;
+}
+
+static int cmd_posix_unlink(void)
+{
+ pstring mask;
+ pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
+
+ pstrcpy(mask,cur_dir);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_unlink <filename>\n");
+ return 1;
+ }
+ pstrcat(mask,buf);
+
+ if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+ d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_posix_unlink(targetcli, targetname)) {
+ d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
+ } else {
+ d_printf("posix_unlink deleted file %s\n", targetname);
+ }
+
+ return 0;
+}
+
+static int cmd_posix_rmdir(void)
+{
+ pstring mask;
+ pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
+
+ pstrcpy(mask,cur_dir);
+
+ if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+ d_printf("posix_rmdir <filename>\n");
+ return 1;
+ }
+ pstrcat(mask,buf);
+
+ if (!cli_resolve_path( "", cli, mask, &targetcli, targetname)) {
+ d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_posix_rmdir(targetcli, targetname)) {
+ d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
+ } else {
+ d_printf("posix_rmdir deleted directory %s\n", targetname);
+ }
+
+ return 0;
+}
+
static int cmd_close(void)
{
fstring buf;
@@ -1829,6 +1974,9 @@ static int cmd_posix(void)
if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
pstrcat(caps, "pathnames ");
}
+ if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
+ pstrcat(caps, "posix_path_operations ");
+ }
if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
caps[strlen(caps)-1] = '\0';
@@ -2013,6 +2161,8 @@ static int cmd_symlink(void)
{
pstring oldname,newname;
pstring buf,buf2;
+ struct cli_state *targetcli;
+ pstring targetname;
if (!SERVER_HAS_UNIX_CIFS(cli)) {
d_printf("Server doesn't support UNIX CIFS calls.\n");
@@ -2030,9 +2180,14 @@ static int cmd_symlink(void)
pstrcpy(oldname,buf);
pstrcat(newname,buf2);
- if (!cli_unix_symlink(cli, oldname, newname)) {
+ if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
+ d_printf("link %s: %s\n", oldname, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_unix_symlink(targetcli, targetname, newname)) {
d_printf("%s symlinking files (%s -> %s)\n",
- cli_errstr(cli), newname, oldname);
+ cli_errstr(targetcli), newname, targetname);
return 1;
}
@@ -2230,7 +2385,6 @@ static int cmd_getfacl(void)
return 1;
}
-
if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
d_printf("%s getfacl doing a stat on file %s\n",
cli_errstr(targetcli), src);
@@ -2415,7 +2569,7 @@ static int cmd_stat(void)
lt = localtime(&sbuf.st_atime);
if (lt) {
- strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+ strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
} else {
fstrcpy(mode_str, "unknown");
}
@@ -2423,7 +2577,7 @@ static int cmd_stat(void)
lt = localtime(&sbuf.st_mtime);
if (lt) {
- strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+ strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
} else {
fstrcpy(mode_str, "unknown");
}
@@ -2431,7 +2585,7 @@ static int cmd_stat(void)
lt = localtime(&sbuf.st_ctime);
if (lt) {
- strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+ strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
} else {
fstrcpy(mode_str, "unknown");
}
@@ -2472,7 +2626,6 @@ static int cmd_chown(void)
return 1;
}
-
if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
d_printf("Server doesn't support UNIX CIFS calls.\n");
return 1;
@@ -2495,6 +2648,8 @@ static int cmd_rename(void)
{
pstring src,dest;
pstring buf,buf2;
+ struct cli_state *targetcli;
+ pstring targetname;
pstrcpy(src,cur_dir);
pstrcpy(dest,cur_dir);
@@ -2508,8 +2663,13 @@ static int cmd_rename(void)
pstrcat(src,buf);
pstrcat(dest,buf2);
- if (!cli_rename(cli, src, dest)) {
- d_printf("%s renaming files\n",cli_errstr(cli));
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+ d_printf("chown %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_rename(targetcli, targetname, dest)) {
+ d_printf("%s renaming files\n",cli_errstr(targetcli));
return 1;
}
@@ -2602,7 +2762,7 @@ static int cmd_newer(void)
if (ok && (sys_stat(buf,&sbuf) == 0)) {
newer_than = sbuf.st_mtime;
DEBUG(1,("Getting files newer than %s",
- time_to_asc(&newer_than)));
+ time_to_asc(newer_than)));
} else {
newer_than = 0;
}
@@ -2738,7 +2898,7 @@ static int cmd_reget(void)
return 1;
}
pstrcpy(local_name, p);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
next_token_nr(NULL, local_name, NULL, sizeof(local_name));
@@ -2776,7 +2936,7 @@ static int cmd_reput(void)
else
pstrcat(remote_name, local_name);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
return do_put(remote_name, local_name, True);
}
@@ -3067,6 +3227,10 @@ static struct
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
{"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+ {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+ {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+ {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+ {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
{"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
{"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},
{"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
diff --git a/source/client/clitar.c b/source/client/clitar.c
index f228db11998..7bbb9fc58bf 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -652,7 +652,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE);
- dos_clean_name(rname);
+ clean_name(rname);
if (fnum == -1) {
DEBUG(0,("%s opening remote file %s (%s)\n",
@@ -1650,7 +1650,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
if (sys_stat(argv[Optind], &stbuf) == 0) {
newer_than = stbuf.st_mtime;
DEBUG(1,("Getting files newer than %s",
- time_to_asc(&newer_than)));
+ time_to_asc(newer_than)));
newOptind++;
Optind++;
} else {
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index 076001ccc07..7e4c27c820b 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -59,6 +59,10 @@
#define MS_MOVE 8192
#endif
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
+
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
const char *thisprogram;
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index b7042f99cb2..2063418a916 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -368,7 +368,7 @@ static int do_cd(char *newdir)
all_string_sub(cur_dir, "/./", "/", 0);
/* Format the directory in a libmsmbclient friendly way */
- unix_clean_name(cur_dir);
+ clean_name(cur_dir);
all_string_sub(cur_dir, "/./", "/", 0);
pstrcpy(targetpath, "smb:");
pstrcat(targetpath, service);
@@ -445,7 +445,7 @@ static void display_finfo(file_info *finfo)
finfo->name,
attrib_string(finfo->mode),
(double)finfo->size,
- time_to_asc(&t));
+ time_to_asc(t));
dir_total += finfo->size;
}
}
@@ -458,7 +458,7 @@ static void display_stat(char *name, struct stat *st)
{
time_t t = st->st_mtime;
pstring time_str;
- pstrcpy(time_str, time_to_asc(&t));
+ pstrcpy(time_str, time_to_asc(t));
time_str[strlen(time_str)-1] = 0;
d_printf("> %-30s", name);
d_printf("%10.10s %8.0f %s\n", *mode_t_string(st->st_mode), (double)st->st_size, time_str);
@@ -1130,7 +1130,7 @@ static int cmd_more(void)
unlink(lname);
return 1;
}
- dos_clean_name(rname);
+ clean_name(rname);
rc = do_get(rname, lname, False);
@@ -2561,7 +2561,7 @@ static int cmd_newer(void)
if (ok && (sys_stat(buf,&sbuf) == 0)) {
newer_than = sbuf.st_mtime;
DEBUG(1,("Getting files newer than %s",
- time_to_asc(&newer_than)));
+ time_to_asc(newer_than)));
} else {
newer_than = 0;
}
@@ -2678,7 +2678,7 @@ static int cmd_reget(void)
return 1;
}
pstrcpy(local_name, p);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
next_token_nr(NULL, local_name, NULL, sizeof(local_name));
@@ -2716,7 +2716,7 @@ static int cmd_reput(void)
else
pstrcat(remote_name, local_name);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
return do_put(remote_name, local_name, True);
}
diff --git a/source/configure.in b/source/configure.in
index f54c9bd2982..13152f39b24 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -299,6 +299,7 @@ AC_SUBST(PAM_MODULES)
AC_SUBST(INSTALL_PAM_MODULES)
AC_SUBST(UNINSTALL_PAM_MODULES)
AC_SUBST(EXTRA_BIN_PROGS)
+AC_SUBST(SMBMOUNT_PROGS)
AC_SUBST(CIFSMOUNT_PROGS)
AC_SUBST(INSTALL_CIFSMOUNT)
AC_SUBST(UNINSTALL_CIFSMOUNT)
@@ -2966,6 +2967,23 @@ if test x"$samba_cv_HAVE_STAT_ST_BLKSIZE" = x"yes"; then
AC_DEFINE(HAVE_STAT_ST_BLKSIZE,1,[Whether the stat struct has a st_blksize property])
fi
+AC_CACHE_CHECK([for st_flags in struct stat],
+ samba_cv_HAVE_STAT_ST_FLAGS,
+ [
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>],
+ [struct stat st; st.st_flags = 0;],
+ samba_cv_HAVE_STAT_ST_FLAGS=yes,
+ samba_cv_HAVE_STAT_ST_FLAGS=no,
+ samba_cv_HAVE_STAT_ST_FLAGS=cross)
+ ])
+
+if test x"$samba_cv_HAVE_STAT_ST_FLAGS" = x"yes"; then
+ AC_DEFINE(HAVE_STAT_ST_FLAGS, 1,
+ [Whether the stat struct has a st_flags member])
+fi
+
case "$host_os" in
*linux*)
AC_CACHE_CHECK([for broken RedHat 7.2 system header files],samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[
@@ -3413,6 +3431,7 @@ if test x"$with_ads_support" != x"no"; then
CPPFLAGS=$ac_save_CPPFLAGS
LDFLAGS=$ac_save_LDFLAGS
fi
+ AC_CHECK_HEADERS(krb5/locate_plugin.h)
fi
# Now we have determined whether we really want ADS support
@@ -3832,6 +3851,20 @@ if test x"$with_ads_support" != x"no"; then
[Whether the type krb5_addresses type exists])
fi
+ AC_CACHE_CHECK([whether krb5_mk_error takes 3 arguments MIT or 9 Heimdal],
+ samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE, [
+ AC_TRY_COMPILE([#include <krb5.h>],
+ [
+ krb5_mk_error(0,0,0);],
+ samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE=yes,
+ samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE=no)])
+
+ if test x"$samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE" = x"yes"; then
+ AC_DEFINE(HAVE_SHORT_KRB5_MK_ERROR_INTERFACE,1,
+ [whether krb5_mk_error takes 3 arguments MIT or 9 Heimdal])
+ fi
+
+
#
#
# Now the decisions whether we can support krb5
@@ -4017,7 +4050,7 @@ AC_ARG_WITH(smbmount,
*linux*)
AC_MSG_RESULT(yes)
AC_DEFINE(WITH_SMBMOUNT,1,[Whether to build smbmount])
- EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/smbmount bin/smbmnt bin/smbumount"
+ SMBMOUNT_PROGS="bin/smbmount bin/smbmnt bin/smbumount"
;;
*)
AC_MSG_ERROR(not on a linux system!)
@@ -5571,6 +5604,8 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
NSSSONAMEVERSIONSUFFIX=""
+SMB_KRB5_LOCATOR="bin/smb_krb5_locator.$SHLIBEXT"
+
case "$host_os" in
*linux*)
NSSSONAMEVERSIONSUFFIX=".2"
@@ -5640,6 +5675,8 @@ AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
AC_SUBST(NSSSONAMEVERSIONSUFFIX)
+AC_SUBST(SMB_KRB5_LOCATOR)
+
# Check the setting of --with-winbind
AC_ARG_WITH(winbind,
diff --git a/source/include/client.h b/source/include/client.h
index dc266995c62..aa8a6479470 100644
--- a/source/include/client.h
+++ b/source/include/client.h
@@ -34,21 +34,6 @@
* These definitions depend on smb.h
*/
-typedef struct file_info
-{
- SMB_BIG_UINT size;
- uint16 mode;
- uid_t uid;
- gid_t gid;
- /* these times are normally kept in GMT */
- struct timespec mtime_ts;
- struct timespec atime_ts;
- struct timespec ctime_ts;
- pstring name;
- pstring dir;
- char short_name[13*3]; /* the *3 is to cope with multi-byte */
-} file_info;
-
struct print_job_info
{
uint16 id;
@@ -173,6 +158,21 @@ struct cli_state {
BOOL case_sensitive; /* False by default. */
};
+typedef struct file_info {
+ struct cli_state *cli;
+ SMB_BIG_UINT size;
+ uint16 mode;
+ uid_t uid;
+ gid_t gid;
+ /* these times are normally kept in GMT */
+ struct timespec mtime_ts;
+ struct timespec atime_ts;
+ struct timespec ctime_ts;
+ pstring name;
+ pstring dir;
+ char short_name[13*3]; /* the *3 is to cope with multi-byte */
+} file_info;
+
#define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001
#define CLI_FULL_CONNECTION_USE_KERBEROS 0x0002
#define CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK 0x0004
diff --git a/source/include/doserr.h b/source/include/doserr.h
index 4e3a85ff73f..3c3978a5b9f 100644
--- a/source/include/doserr.h
+++ b/source/include/doserr.h
@@ -202,6 +202,7 @@
#define WERR_SERVICE_NEVER_STARTED W_ERROR(1077)
#define WERR_MACHINE_LOCKED W_ERROR(1271)
#define WERR_NO_LOGON_SERVERS W_ERROR(1311)
+#define WERR_LOGON_FAILURE W_ERROR(1326)
#define WERR_NO_SUCH_DOMAIN W_ERROR(1355)
#define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
#define WERR_TIME_SKEW W_ERROR(1398)
diff --git a/source/include/includes.h b/source/include/includes.h
index 34b9c36c8ac..bdd92f219ee 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -1181,6 +1181,10 @@ krb5_error_code handle_krberror_packet(krb5_context context,
krb5_data *packet);
void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt);
krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt);
+krb5_error_code smb_krb5_mk_error(krb5_context context,
+ krb5_error_code error_code,
+ const krb5_principal server,
+ krb5_data *reply);
#endif /* HAVE_KRB5 */
diff --git a/source/include/msdfs.h b/source/include/msdfs.h
index 4e3487de0f4..05cfe4e102f 100644
--- a/source/include/msdfs.h
+++ b/source/include/msdfs.h
@@ -51,7 +51,7 @@ struct referral {
};
struct junction_map {
- pstring service_name;
+ fstring service_name;
pstring volume_name;
pstring comment;
int referral_count;
@@ -59,31 +59,12 @@ struct junction_map {
};
struct dfs_path {
- pstring hostname;
- pstring servicename;
+ fstring hostname;
+ fstring servicename;
pstring reqpath;
+ BOOL posix_path;
};
-#define RESOLVE_DFSPATH(name, conn, inbuf, outbuf) \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \
- lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \
- dfs_redirect(name, conn, False)) \
- return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \
- ERRSRV, ERRbadpath);; }
-
-#define RESOLVE_DFSPATH_STATUS(name, conn, inbuf, outbuf) \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \
- lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \
- dfs_redirect(name, conn, False)) \
- return NT_STATUS_PATH_NOT_COVERED;; }
-
-#define RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf) \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \
- lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \
- dfs_redirect(name,conn, True)) \
- return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \
- ERRSRV, ERRbadpath);; }
-
#define init_dfsroot(conn, inbuf, outbuf) \
{ if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) { \
DEBUG(2,("Serving %s as a Dfs root\n", \
diff --git a/source/include/nt_printing.h b/source/include/nt_printing.h
index 5bd64ae7be3..c2dde7d4785 100644
--- a/source/include/nt_printing.h
+++ b/source/include/nt_printing.h
@@ -386,18 +386,13 @@ typedef struct {
#define NE_HEADER_MAJOR_VER_OFFSET 63
/* Portable Executable format */
-#define PE_HEADER_SIZE 248
+#define PE_HEADER_SIZE 24
#define PE_HEADER_SIGNATURE_OFFSET 0
#define PE_HEADER_SIGNATURE 0x00004550
#define PE_HEADER_MACHINE_OFFSET 4
#define PE_HEADER_MACHINE_I386 0x14c
#define PE_HEADER_NUMBER_OF_SECTIONS 6
-#define PE_HEADER_MAJOR_OS_VER_OFFSET 64
-#define PE_HEADER_MINOR_OS_VER_OFFSET 66
-#define PE_HEADER_MAJOR_IMG_VER_OFFSET 68
-#define PE_HEADER_MINOR_IMG_VER_OFFSET 70
-#define PE_HEADER_MAJOR_SS_VER_OFFSET 72
-#define PE_HEADER_MINOR_SS_VER_OFFSET 74
+#define PE_HEADER_OPTIONAL_HEADER_SIZE 20
#define PE_HEADER_SECT_HEADER_SIZE 40
#define PE_HEADER_SECT_NAME_OFFSET 0
#define PE_HEADER_SECT_SIZE_DATA_OFFSET 16
diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h
index 9e65052f849..6bfddcef01f 100644
--- a/source/include/rpc_secdes.h
+++ b/source/include/rpc_secdes.h
@@ -195,6 +195,7 @@ typedef struct standard_mapping {
/* Combinations of standard masks. */
#define STANDARD_RIGHTS_ALL_ACCESS STD_RIGHT_ALL_ACCESS /* 0x001f0000 */
+#define STANDARD_RIGHTS_MODIFY_ACCESS STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
#define STANDARD_RIGHTS_EXECUTE_ACCESS STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
#define STANDARD_RIGHTS_READ_ACCESS STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
#define STANDARD_RIGHTS_WRITE_ACCESS \
@@ -243,10 +244,23 @@ typedef struct standard_mapping {
#define GENERIC_RIGHTS_FILE_EXECUTE \
(STANDARD_RIGHTS_EXECUTE_ACCESS | \
+ STD_RIGHT_SYNCHRONIZE_ACCESS | \
SA_RIGHT_FILE_READ_ATTRIBUTES | \
SA_RIGHT_FILE_EXECUTE)
-
+#define GENERIC_RIGHTS_FILE_MODIFY \
+ (STANDARD_RIGHTS_MODIFY_ACCESS | \
+ STD_RIGHT_SYNCHRONIZE_ACCESS | \
+ STD_RIGHT_DELETE_ACCESS | \
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES | \
+ SA_RIGHT_FILE_READ_ATTRIBUTES | \
+ SA_RIGHT_FILE_EXECUTE | \
+ SA_RIGHT_FILE_WRITE_EA | \
+ SA_RIGHT_FILE_READ_EA | \
+ SA_RIGHT_FILE_APPEND_DATA | \
+ SA_RIGHT_FILE_WRITE_DATA | \
+ SA_RIGHT_FILE_READ_DATA)
+
/* SAM server specific access rights */
#define SA_RIGHT_SAM_CONNECT_SERVER 0x00000001
diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h
index 5d32d65c3df..62acce58050 100644
--- a/source/include/rpc_srvsvc.h
+++ b/source/include/rpc_srvsvc.h
@@ -5,6 +5,8 @@
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
Copyright (C) Nigel Williams 2001
+ Copyright (C) Gerald (Jerry) Carter 2006.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -72,128 +74,84 @@ typedef struct net_srv_disk_enum {
WERROR status; /* return status */
} SRV_Q_NET_DISK_ENUM, SRV_R_NET_DISK_ENUM;
-typedef struct net_name_validate {
- uint32 ptr_srv_name;
- UNISTR2 uni_srv_name;
- UNISTR2 uni_name; /*name to validate*/
+/***************************/
+
+typedef struct {
+ UNISTR2 *servername;
+ UNISTR2 sharename;
uint32 type;
uint32 flags;
WERROR status;
-} SRV_Q_NET_NAME_VALIDATE, SRV_R_NET_NAME_VALIDATE;
-
-/* SESS_INFO_0 (pointers to level 0 session info strings) */
-typedef struct ptr_sess_info0
-{
- uint32 ptr_name; /* pointer to name. */
-
-} SESS_INFO_0;
+} SRV_Q_NET_NAME_VALIDATE;
-/* SESS_INFO_0_STR (level 0 session info strings) */
-typedef struct str_sess_info0
-{
- UNISTR2 uni_name; /* unicode string of name */
+typedef struct {
+ WERROR status;
+} SRV_R_NET_NAME_VALIDATE;
-} SESS_INFO_0_STR;
+/***************************/
/* oops - this is going to take up a *massive* amount of stack. */
/* the UNISTR2s already have 1024 uint16 chars in them... */
-#define MAX_SESS_ENTRIES 32
-/* SRV_SESS_INFO_0 */
-typedef struct srv_sess_info_0_info
-{
- uint32 num_entries_read; /* EntriesRead */
- uint32 ptr_sess_info; /* Buffer */
- uint32 num_entries_read2; /* EntriesRead */
+#define MAX_SESS_ENTRIES 32
- SESS_INFO_0 info_0 [MAX_SESS_ENTRIES]; /* session entry pointers */
- SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */
+typedef struct {
+ UNISTR2 *sharename;
+} SESS_INFO_0;
+typedef struct {
+ uint32 num_entries_read;
+ uint32 ptr_sess_info;
+ uint32 num_entries_read2;
+ SESS_INFO_0 info_0[MAX_SESS_ENTRIES];
} SRV_SESS_INFO_0;
-/* SESS_INFO_1 (pointers to level 1 session info strings) */
-typedef struct ptr_sess_info1
-{
- uint32 ptr_name; /* pointer to name. */
- uint32 ptr_user; /* pointer to user name. */
-
+typedef struct {
+ UNISTR2 *sharename;
+ UNISTR2 *username;
uint32 num_opens;
uint32 open_time;
uint32 idle_time;
uint32 user_flags;
-
} SESS_INFO_1;
-/* SESS_INFO_1_STR (level 1 session info strings) */
-typedef struct str_sess_info1
-{
- UNISTR2 uni_name; /* unicode string of name */
- UNISTR2 uni_user; /* unicode string of user */
-
-} SESS_INFO_1_STR;
-
-/* SRV_SESS_INFO_1 */
-typedef struct srv_sess_info_1_info
-{
- uint32 num_entries_read; /* EntriesRead */
- uint32 ptr_sess_info; /* Buffer */
- uint32 num_entries_read2; /* EntriesRead */
-
- SESS_INFO_1 info_1 [MAX_SESS_ENTRIES]; /* session entry pointers */
- SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */
-
+typedef struct {
+ uint32 num_entries_read;
+ uint32 ptr_sess_info;
+ uint32 num_entries_read2;
+ SESS_INFO_1 info_1[MAX_SESS_ENTRIES];
} SRV_SESS_INFO_1;
-/* SRV_SESS_INFO_CTR */
-typedef struct srv_sess_info_ctr_info
-{
- uint32 switch_value; /* switch value */
- uint32 ptr_sess_ctr; /* pointer to sess info union */
- union
- {
- SRV_SESS_INFO_0 info0; /* session info level 0 */
- SRV_SESS_INFO_1 info1; /* session info level 1 */
-
- } sess;
+typedef struct {
+ uint32 switch_value;
+ uint32 ptr_sess_ctr;
+ union {
+ SRV_SESS_INFO_0 info0;
+ SRV_SESS_INFO_1 info1;
+ } sess;
} SRV_SESS_INFO_CTR;
-
-/* SRV_Q_NET_SESS_ENUM */
-typedef struct q_net_sess_enum_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* server name */
-
- uint32 ptr_qual_name; /* pointer (to qualifier name) */
- UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */
-
- uint32 ptr_user_name; /* pointer (to user name */
- UNISTR2 uni_user_name; /* user name */
-
- uint32 sess_level; /* session level */
-
+typedef struct {
+ UNISTR2 *servername;
+ UNISTR2 *qualifier;
+ UNISTR2 *username;
+ uint32 sess_level;
SRV_SESS_INFO_CTR *ctr;
-
- uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
+ uint32 preferred_len;
ENUM_HND enum_hnd;
-
} SRV_Q_NET_SESS_ENUM;
-/* SRV_R_NET_SESS_ENUM */
-typedef struct r_net_sess_enum_info
-{
- uint32 sess_level; /* share level */
-
+typedef struct {
+ uint32 sess_level;
SRV_SESS_INFO_CTR *ctr;
-
- uint32 total_entries; /* total number of entries */
+ uint32 total_entries;
ENUM_HND enum_hnd;
-
- WERROR status; /* return status */
-
+ WERROR status;
} SRV_R_NET_SESS_ENUM;
+/***************************/
+
/* SRV_Q_NET_SESS_DEL */
typedef struct q_net_sess_del
{
@@ -685,104 +643,47 @@ typedef struct r_net_share_del
} SRV_R_NET_SHARE_DEL;
-/* FILE_INFO_3 (level 3 file info strings) */
-typedef struct file_info3_info
-{
+/***************************/
+
+typedef struct {
uint32 id; /* file index */
uint32 perms; /* file permissions. don't know what format */
uint32 num_locks; /* file locks */
- uint32 ptr_path_name; /* file name */
- uint32 ptr_user_name; /* file owner */
-
+ UNISTR2 *path; /* file name */
+ UNISTR2 *user; /* file owner */
} FILE_INFO_3;
-/* FILE_INFO_3_STR (level 3 file info strings) */
-typedef struct str_file_info3_info
-{
- UNISTR2 uni_path_name; /* unicode string of file name */
- UNISTR2 uni_user_name; /* unicode string of file owner. */
-
-} FILE_INFO_3_STR;
-
-/* SRV_FILE_INFO_3 */
-typedef struct srv_file_info_3
-{
- uint32 num_entries_read; /* EntriesRead */
- uint32 ptr_file_info; /* Buffer */
-
- uint32 num_entries_read2; /* EntriesRead */
- FILE_INFO_3 info_3; /* file entry details */
- FILE_INFO_3_STR info_3_str; /* file entry strings */
-} SRV_FILE_INFO_3;
-
-/* SRV_FILE_INFO_CTR */
-typedef struct srv_file_info_3_info
-{
- uint32 switch_value; /* switch value */
+typedef struct {
+ uint32 level; /* switch value */
uint32 ptr_file_info; /* pointer to file info union */
uint32 num_entries;
uint32 ptr_entries;
uint32 num_entries2;
- union
- {
- SRV_FILE_INFO_3 *info3;
+ union {
+ FILE_INFO_3 *info3;
} file;
} SRV_FILE_INFO_CTR;
-
-/* SRV_Q_NET_FILE_ENUM */
-typedef struct q_net_file_enum_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* server name */
-
- uint32 ptr_qual_name; /* pointer (to qualifier name) */
- UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */
-
- uint32 ptr_user_name; /* pointer (to user name) */
- UNISTR2 uni_user_name; /* user name */
-
- uint32 file_level; /* file level */
-
+typedef struct {
+ UNISTR2 *servername;
+ UNISTR2 *qualifier;
+ UNISTR2 *username;
+ uint32 level;
SRV_FILE_INFO_CTR ctr;
-
- uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
+ uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
ENUM_HND enum_hnd;
-
} SRV_Q_NET_FILE_ENUM;
-
-/* SRV_R_NET_FILE_ENUM */
-typedef struct r_net_file_enum_info
-{
- uint32 file_level; /* file level */
-
+typedef struct {
+ uint32 level;
SRV_FILE_INFO_CTR ctr;
-
- uint32 total_entries; /* total number of files */
+ uint32 total_entries;
ENUM_HND enum_hnd;
-
- WERROR status; /* return status */
-
+ WERROR status;
} SRV_R_NET_FILE_ENUM;
-/* SRV_Q_NET_FILE_CLOSE */
-typedef struct q_net_file_close
-{
- uint32 ptr_srv_name; /* pointer to server name */
- UNISTR2 uni_srv_name; /* server name */
-
- uint32 file_id;
-} SRV_Q_NET_FILE_CLOSE;
-
-/* SRV_R_NET_FILE_CLOSE */
-typedef struct r_net_file_close
-{
- WERROR status; /* return status */
-} SRV_R_NET_FILE_CLOSE;
-
/* SRV_INFO_100 */
typedef struct srv_info_100_info
{
@@ -967,4 +868,17 @@ typedef struct r_net_file_set_secdesc
WERROR status;
} SRV_R_NET_FILE_SET_SECDESC;
+/***************************/
+
+typedef struct {
+ UNISTR2 *servername;
+ uint32 file_id;
+} SRV_Q_NET_FILE_CLOSE;
+
+typedef struct {
+ WERROR status;
+} SRV_R_NET_FILE_CLOSE;
+
+/***************************/
+
#endif /* _RPC_SRVSVC_H */
diff --git a/source/include/smb.h b/source/include/smb.h
index 3f0356f2248..a8fb39797b2 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -500,12 +500,13 @@ typedef struct files_struct {
uint32 access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */
uint32 share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
BOOL pending_modtime_owner;
- time_t pending_modtime;
- time_t last_write_time;
+ struct timespec pending_modtime;
+ struct timespec last_write_time;
int oplock_type;
int sent_oplock_break;
struct timed_event *oplock_timeout;
struct lock_struct last_lock_failure;
+ int current_lock_count; /* Count the number of outstanding locks and pending locks. */
struct share_mode_entry *pending_break_messages;
int num_pending_break_messages;
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index fa7c6e4a5ae..cc501739c16 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -152,9 +152,9 @@ enum profile_stats_values
#define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count)
#define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time)
- PR_VALUE_SYSCALL_UTIME,
-#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count)
-#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time)
+ PR_VALUE_SYSCALL_NTIMES,
+#define syscall_ntimes_count __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, count)
+#define syscall_ntimes_time __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, time)
PR_VALUE_SYSCALL_FTRUNCATE,
#define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count)
diff --git a/source/include/trans2.h b/source/include/trans2.h
index 5b9623e3d40..c7faf4f63f6 100644
--- a/source/include/trans2.h
+++ b/source/include/trans2.h
@@ -1,6 +1,8 @@
/*
Unix SMB/CIFS implementation.
SMB transaction2 handling
+
+ Copyright (C) James Peach 2007
Copyright (C) Jeremy Allison 1994-2002.
Extensively modified by Andrew Tridgell, 1995
@@ -352,6 +354,7 @@ Byte offset Type name description
#define SMB_QUERY_FILE_UNIX_BASIC 0x200 /* UNIX File Info*/
#define SMB_SET_FILE_UNIX_BASIC 0x200
+#define SMB_SET_FILE_UNIX_INFO2 0x20B /* UNIX File Info2 */
#define SMB_MODE_NO_CHANGE 0xFFFFFFFF /* file mode value which */
/* means "don't change it" */
@@ -435,6 +438,18 @@ Offset Size Name
#define UNIX_EXTRA_MASK 0007000
#define UNIX_ALL_MASK 0007777
+/* Flags for chflags (CIFS_UNIX_EXTATTR_CAP capability) and
+ * SMB_QUERY_FILE_UNIX_INFO2.
+ */
+#define EXT_SECURE_DELETE 0x00000001
+#define EXT_ENABLE_UNDELETE 0x00000002
+#define EXT_SYNCHRONOUS 0x00000004
+#define EXT_IMMUTABLE 0x00000008
+#define EXT_OPEN_APPEND_ONLY 0x00000010
+#define EXT_DO_NOT_BACKUP 0x00000020
+#define EXT_NO_UPDATE_ATIME 0x00000040
+#define EXT_HIDDEN 0x00000080
+
#define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_HLINK 0x203
@@ -455,8 +470,35 @@ Offset Size Name
#define SMB_QUERY_FILE_UNIX_INFO2 0x20B /* UNIX File Info2 */
#define SMB_SET_FILE_UNIX_INFO2 0x20B
+/*
+SMB_QUERY_FILE_UNIX_INFO2 is SMB_QUERY_FILE_UNIX_BASIC with create
+time and file flags appended. The corresponding info level for
+findfirst/findnext is SMB_FIND_FILE_UNIX_INFO2.
+ Size Offset Value
+ ---------------------
+ 0 LARGE_INTEGER EndOfFile File size
+ 8 LARGE_INTEGER Blocks Number of blocks used on disk
+ 16 LARGE_INTEGER ChangeTime Attribute change time
+ 24 LARGE_INTEGER LastAccessTime Last access time
+ 32 LARGE_INTEGER LastModificationTime Last modification time
+ 40 LARGE_INTEGER Uid Numeric user id for the owner
+ 48 LARGE_INTEGER Gid Numeric group id of owner
+ 56 ULONG Type Enumeration specifying the file type
+ 60 LARGE_INTEGER devmajor Major device number if type is device
+ 68 LARGE_INTEGER devminor Minor device number if type is device
+ 76 LARGE_INTEGER uniqueid This is a server-assigned unique id
+ 84 LARGE_INTEGER permissions Standard UNIX permissions
+ 92 LARGE_INTEGER nlinks Number of hard links
+ 100 LARGE_INTEGER CreationTime Create/birth time
+ 108 ULONG FileFlags File flags enumeration
+ 112 ULONG FileFlagsMask Mask of valid flags
+*/
+
/* Transact 2 Find First levels */
#define SMB_FIND_FILE_UNIX 0x202
+#define SMB_FIND_FILE_UNIX_INFO2 0x20B /* UNIX File Info2 */
+
+#define SMB_FILE_UNIX_INFO2_SIZE 116
/*
Info level for TRANS2_QFSINFO - returns version of CIFS UNIX extensions, plus
@@ -564,6 +606,37 @@ number of entries sent will be zero.
*/
+#define SMB_QUERY_POSIX_WHOAMI 0x202
+
+enum smb_whoami_flags {
+ SMB_WHOAMI_GUEST = 0x1 /* Logged in as (or squashed to) guest */
+};
+
+/* Mask of which WHOAMI bits are valid. This should make it easier for clients
+ * to cope with servers that have different sets of WHOAMI flags (as more get
+ * added).
+ */
+#define SMB_WHOAMI_MASK 0x00000001
+
+/*
+ SMBWhoami - Query the user mapping performed by the server for the
+ connected tree. This is a subcommand of the TRANS2_QFSINFO.
+
+ Returns:
+ 4 bytes unsigned - mapping flags (smb_whoami_flags)
+ 4 bytes unsigned - flags mask
+
+ 8 bytes unsigned - primary UID
+ 8 bytes unsigned - primary GID
+ 4 bytes unsigned - number of supplementary GIDs
+ 4 bytes unsigned - number of SIDs
+ 4 bytes unsigned - SID list byte count
+ 4 bytes - pad / reserved (must be zero)
+
+ 8 bytes unsigned[] - list of GIDs (may be empty)
+ DOM_SID[] - list of SIDs (may be empty)
+*/
+
/* The query/set info levels for POSIX ACLs. */
#define SMB_QUERY_POSIX_ACL 0x204
#define SMB_SET_POSIX_ACL 0x204
@@ -589,7 +662,7 @@ number of entries sent will be zero.
#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF
-/* Definition of parameter block of SMB_SET_POSIX_LOCK */
+/* Definition of data block of SMB_SET_POSIX_LOCK */
/*
[2 bytes] lock_type - 0 = Read, 1 = Write, 2 = Unlock
[2 bytes] lock_flags - 1 = Wait (only valid for setlock)
@@ -628,11 +701,11 @@ number of entries sent will be zero.
#define SMB_O_NOFOLLOW 0x400
#define SMB_O_DIRECT 0x800
-/* Definition of request parameter block for SMB_POSIX_PATH_OPEN */
+/* Definition of request data block for SMB_POSIX_PATH_OPEN */
/*
[4 bytes] flags (as smb_ntcreate_Flags).
- [4 bytes] open_mode
- [4 bytes] mode_t - same encoding as "Standard UNIX permissions" above.
+ [4 bytes] open_mode - SMB_O_xxx flags above.
+ [8 bytes] mode_t (permissions) - same encoding as "Standard UNIX permissions" above in SMB_SET_FILE_UNIX_BASIC.
[2 bytes] ret_info_level - optimization. Info level to be returned.
*/
@@ -641,8 +714,20 @@ number of entries sent will be zero.
#define SMB_NO_INFO_LEVEL_RETURNED 0xFFFF
/*
- [2 bytes] reply info level - as requested or 0xFFFF if not available.
+ [2 bytes] - flags field. Identical to flags reply for oplock response field in SMBNTCreateX)
+ [2 bytes] - FID returned.
+ [4 bytes] - CreateAction (same as in NTCreateX response).
+ [2 bytes] - reply info level - as requested or 0xFFFF if not available.
+ [2 bytes] - padding (must be zero)
[n bytes] - info level reply - if available.
*/
+/* Definition of request data block for SMB_POSIX_UNLINK */
+/*
+ [2 bytes] flags (defined below).
+*/
+
+#define SMB_POSIX_UNLINK_FILE_TARGET 0
+#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
+
#endif
diff --git a/source/include/vfs.h b/source/include/vfs.h
index 2d04a374c4c..29e96f6b506 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -67,7 +67,10 @@
Also include kernel_flock call - jmcd */
/* Changed to version 19, kernel change notify has been merged
Also included linux setlease call - jmcd */
-#define SMB_VFS_INTERFACE_VERSION 19
+/* Changed to version 20, use ntimes call instead of utime (greater
+ * timestamp resolition. JRA. */
+/* Changed to version21 to add chflags operation -- jpeach */
+#define SMB_VFS_INTERFACE_VERSION 21
/* to bug old modules which are trying to compile with the old functions */
@@ -144,7 +147,7 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_FCHOWN,
SMB_VFS_OP_CHDIR,
SMB_VFS_OP_GETWD,
- SMB_VFS_OP_UTIME,
+ SMB_VFS_OP_NTIMES,
SMB_VFS_OP_FTRUNCATE,
SMB_VFS_OP_LOCK,
SMB_VFS_OP_KERNEL_FLOCK,
@@ -156,6 +159,7 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_MKNOD,
SMB_VFS_OP_REALPATH,
SMB_VFS_OP_NOTIFY_WATCH,
+ SMB_VFS_OP_CHFLAGS,
/* NT ACL operations. */
@@ -269,7 +273,7 @@ struct vfs_ops {
int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
int (*chdir)(struct vfs_handle_struct *handle, const char *path);
char *(*getwd)(struct vfs_handle_struct *handle, char *buf);
- int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times);
+ int (*ntimes)(struct vfs_handle_struct *handle, const char *path, const struct timespec ts[2]);
int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode);
@@ -287,6 +291,7 @@ struct vfs_ops {
void *private_data,
struct notify_event *ev),
void *private_data, void *handle_p);
+ int (*chflags)(struct vfs_handle_struct *handle, const char *path, uint flags);
/* NT ACL operations. */
@@ -392,7 +397,7 @@ struct vfs_ops {
struct vfs_handle_struct *fchown;
struct vfs_handle_struct *chdir;
struct vfs_handle_struct *getwd;
- struct vfs_handle_struct *utime;
+ struct vfs_handle_struct *ntimes;
struct vfs_handle_struct *ftruncate;
struct vfs_handle_struct *lock;
struct vfs_handle_struct *kernel_flock;
@@ -404,6 +409,7 @@ struct vfs_ops {
struct vfs_handle_struct *mknod;
struct vfs_handle_struct *realpath;
struct vfs_handle_struct *notify_watch;
+ struct vfs_handle_struct *chflags;
/* NT ACL operations. */
diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h
index f50da3a02b5..2ff313b42ce 100644
--- a/source/include/vfs_macros.h
+++ b/source/include/vfs_macros.h
@@ -67,7 +67,7 @@
#define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid)))
#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path)))
#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf)))
-#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times)))
+#define SMB_VFS_NTIMES(conn, path, ts) ((conn)->vfs.ops.ntimes((conn)->vfs.handles.ntimes, (path), (ts)))
#define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
#define SMB_VFS_KERNEL_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs.ops.kernel_flock((fsp)->conn->vfs.handles.kernel_flock, (fsp), (fd), (share_mode)))
@@ -79,6 +79,7 @@
#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (path), (mode), (dev)))
#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path)))
#define SMB_VFS_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs.ops.notify_watch((conn)->vfs.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
+#define SMB_VFS_CHFLAGS(conn, path, flags) ((conn)->vfs.ops.chflags((conn)->vfs.handles.chflags, (path), (flags)))
/* NT ACL operations. */
#define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
@@ -182,7 +183,7 @@
#define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid)))
#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path)))
#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf)))
-#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times)))
+#define SMB_VFS_OPAQUE_NTIMES(conn, path, ts) ((conn)->vfs_opaque.ops.ntimes((conn)->vfs_opaque.handles.ntimes, (path), (ts)))
#define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
#define SMB_VFS_OPAQUE_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.kernel_flock, (fsp), (fd), (share_mode)))
@@ -194,6 +195,7 @@
#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (path), (mode), (dev)))
#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path)))
#define SMB_VFS_OPAQUE_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_opaque.ops.notify_watch((conn)->vfs_opaque.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
+#define SMB_VFS_OPAQUE_CHFLAGS(conn, path, flags) ((conn)->vfs_opaque.ops.chflags((conn)->vfs_opaque.handles.chflags, (path), (flags)))
/* NT ACL operations. */
#define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
@@ -298,7 +300,7 @@
#define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid)))
#define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path)))
#define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf)))
-#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times)))
+#define SMB_VFS_NEXT_NTIMES(handle, path, ts) ((handle)->vfs_next.ops.ntimes((handle)->vfs_next.handles.ntimes, (path), (ts)))
#define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
#define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode)((handle)->vfs_next.ops.kernel_flock((handle)->vfs_next.handles.kernel_flock, (fsp), (fd), (share_mode)))
@@ -310,6 +312,7 @@
#define SMB_VFS_NEXT_MKNOD(handle, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (path), (mode), (dev)))
#define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path)))
#define SMB_VFS_NEXT_NOTIFY_WATCH(conn, ctx, e, callback, private_data, handle_p) ((conn)->vfs_next.ops.notify_watch((conn)->vfs_next.handles.notify_watch, (ctx), (e), (callback), (private_data), (handle_p)))
+#define SMB_VFS_NEXT_CHFLAGS(handle, path, flags) ((handle)->vfs_next.ops.chflags((handle)->vfs_next.handles.chflags, (path), (flags)))
/* NT ACL operations. */
#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
diff --git a/source/lib/debug.c b/source/lib/debug.c
index 5f141661106..62fda5741c9 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -962,7 +962,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
/* Print the header if timestamps are turned on. If parameters are
* not yet loaded, then default to timestamps on.
*/
- if( lp_timestamp_logs() || !(lp_loaded()) ) {
+ if( lp_timestamp_logs() || lp_debug_prefix_timestamp() || !(lp_loaded()) ) {
char header_str[200];
header_str[0] = '\0';
@@ -980,9 +980,15 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
}
/* Print it all out at once to prevent split syslog output. */
- (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
+ if( lp_debug_prefix_timestamp() ) {
+ (void)Debug1( "[%s, %d%s] ",
+ current_timestring(lp_debug_hires_timestamp()), level,
+ header_str);
+ } else {
+ (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
current_timestring(lp_debug_hires_timestamp()), level,
header_str, file, func, line );
+ }
}
errno = old_errno;
diff --git a/source/lib/interface.c b/source/lib/interface.c
index 9d0b966390f..e2c9294b281 100644
--- a/source/lib/interface.c
+++ b/source/lib/interface.c
@@ -231,6 +231,18 @@ void load_interfaces(void)
}
+void gfree_interfaces(void)
+{
+ while (local_interfaces) {
+ struct interface *iface = local_interfaces;
+ DLIST_REMOVE(local_interfaces, local_interfaces);
+ ZERO_STRUCTPN(iface);
+ SAFE_FREE(iface);
+ }
+
+ SAFE_FREE(probed_ifaces);
+}
+
/****************************************************************************
return True if the list of probed interfaces has changed
****************************************************************************/
diff --git a/source/lib/ldap_escape.c b/source/lib/ldap_escape.c
index 26230884341..8907399be4a 100644
--- a/source/lib/ldap_escape.c
+++ b/source/lib/ldap_escape.c
@@ -89,3 +89,47 @@ char *escape_ldap_string_alloc(const char *s)
*p = '\0';
return output;
}
+
+char *escape_rdn_val_string_alloc(const char *s)
+{
+ char *output, *p;
+
+ /* The maximum size of the escaped string can be twice the actual size */
+ output = (char *)SMB_MALLOC(2*strlen(s) + 1);
+
+ if (output == NULL) {
+ return NULL;
+ }
+
+ p = output;
+
+ while (*s)
+ {
+ switch (*s)
+ {
+ case ',':
+ case '=':
+ case '+':
+ case '<':
+ case '>':
+ case '#':
+ case ';':
+ case '\\':
+ case '\"':
+ *p++ = '\\';
+ *p++ = *s;
+ break;
+ default:
+ *p = *s;
+ p++;
+ }
+
+ s++;
+ }
+
+ *p = '\0';
+
+ /* resize the string to the actual final size */
+ output = (char *)SMB_REALLOC(output, strlen(output) + 1);
+ return output;
+}
diff --git a/source/lib/messages.c b/source/lib/messages.c
index e0bf86a46ce..e2c8a6b52fa 100644
--- a/source/lib/messages.c
+++ b/source/lib/messages.c
@@ -133,6 +133,9 @@ BOOL message_init(void)
return False;
}
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
+
CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
message_register(MSG_PING, ping_message, NULL);
diff --git a/source/lib/smbldap_util.c b/source/lib/smbldap_util.c
index aff4eff6f6d..11b27bf98fb 100644
--- a/source/lib/smbldap_util.c
+++ b/source/lib/smbldap_util.c
@@ -39,12 +39,21 @@ static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state
const char *policy_attr = NULL;
pstring dn;
LDAPMod **mods = NULL;
+ char *escape_domain_name;
DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n"));
-
+
+ escape_domain_name = escape_rdn_val_string_alloc(domain_name);
+ if (!escape_domain_name) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
pstr_sprintf(dn, "%s=%s,%s",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name, lp_ldap_suffix());
+ escape_domain_name, lp_ldap_suffix());
+
+ SAFE_FREE(escape_domain_name);
for (i=1; decode_account_policy_name(i) != NULL; i++) {
@@ -104,10 +113,20 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
LDAPMessage *result = NULL;
int num_result;
const char **attr_list;
+ char *escape_domain_name;
+
+ /* escape for filter */
+ escape_domain_name = escape_ldap_string_alloc(domain_name);
+ if (!escape_domain_name) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name, LDAP_OBJ_DOMINFO);
+ escape_domain_name, LDAP_OBJ_DOMINFO);
+
+ SAFE_FREE(escape_domain_name);
attr_list = get_attr_list( NULL, dominfo_attr_list );
rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
@@ -129,9 +148,18 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
/* Check if we need to add an entry */
DEBUG(3,("add_new_domain_info: Adding new domain\n"));
+ /* this time escape for DN */
+ escape_domain_name = escape_rdn_val_string_alloc(domain_name);
+ if (!escape_domain_name) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
pstr_sprintf(dn, "%s=%s,%s",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name, lp_ldap_suffix());
+ escape_domain_name, lp_ldap_suffix());
+
+ SAFE_FREE(escape_domain_name);
/* Free original search */
ldap_msgfree(result);
@@ -210,11 +238,20 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
int rc;
const char **attr_list;
int count;
+ char *escape_domain_name;
+
+ escape_domain_name = escape_ldap_string_alloc(domain_name);
+ if (!escape_domain_name) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
LDAP_OBJ_DOMINFO,
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name);
+ escape_domain_name);
+
+ SAFE_FREE(escape_domain_name);
DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
diff --git a/source/lib/system.c b/source/lib/system.c
index 20b31113ecd..eaebc7190f0 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -47,20 +47,35 @@
A wrapper for memalign
********************************************************************/
-void* sys_memalign( size_t align, size_t size )
+void *sys_memalign( size_t align, size_t size )
{
-#if defined(HAVE_MEMALIGN)
- return memalign( align, size );
-#elif defined(HAVE_POSIX_MEMALIGN)
- char *p = NULL;
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *p = NULL;
int ret = posix_memalign( &p, align, size );
if ( ret == 0 )
return p;
return NULL;
+#elif defined(HAVE_MEMALIGN)
+ return memalign( align, size );
#else
- DEBUG(0,("memalign functionalaity not available on this platform!\n"));
- return NULL;
+ /* On *BSD systems memaligns doesn't exist, but memory will
+ * be aligned on allocations of > pagesize. */
+#if defined(SYSCONF_SC_PAGESIZE)
+ size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+ size_t pagesize = (size_t)getpagesize();
+#else
+ size_t pagesize = (size_t)-1;
+#endif
+ if (pagesize == (size_t)-1) {
+ DEBUG(0,("memalign functionalaity not available on this platform!\n"));
+ return NULL;
+ }
+ if (size < pagesize) {
+ size = pagesize;
+ }
+ return SMB_MALLOC(size);
#endif
}
diff --git a/source/lib/time.c b/source/lib/time.c
index 403fb0594d4..e98f8232abc 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 1992-2004
Copyright (C) Stefan (metze) Metzmacher 2002
+ Copyright (C) Jeremy Allison 2007
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
@@ -36,17 +37,21 @@
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
-/**
+#define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
+
+/***************************************************************************
External access to time_t_min and time_t_max.
-**/
+****************************************************************************/
+
time_t get_time_t_max(void)
{
return TIME_T_MAX;
}
-/**
-a gettimeofday wrapper
-**/
+/***************************************************************************
+ A gettimeofday wrapper.
+****************************************************************************/
+
void GetTimeOfDay(struct timeval *tval)
{
#ifdef HAVE_GETTIMEOFDAY_TZ
@@ -56,14 +61,6 @@ void GetTimeOfDay(struct timeval *tval)
#endif
}
-struct timespec convert_time_t_to_timespec(time_t t)
-{
- struct timespec ts;
- ts.tv_sec = t;
- ts.tv_nsec = 0;
- return ts;
-}
-
#if (SIZEOF_LONG == 8)
#define TIME_FIXUP_CONSTANT_INT 11644473600L
#elif (SIZEOF_LONG_LONG == 8)
@@ -111,10 +108,10 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
*nt = t2;
}
+/****************************************************************************
+ Check if it's a null unix time.
+****************************************************************************/
-/**
-check if it's a null unix time
-**/
BOOL null_time(time_t t)
{
return t == 0 ||
@@ -122,15 +119,26 @@ BOOL null_time(time_t t)
t == (time_t)-1;
}
+/****************************************************************************
+ Check if it's a null NTTIME.
+****************************************************************************/
-/**
-check if it's a null NTTIME
-**/
BOOL null_nttime(NTTIME t)
{
return t == 0 || t == (NTTIME)-1;
}
+/****************************************************************************
+ Check if it's a null timespec.
+****************************************************************************/
+
+BOOL null_timespec(struct timespec ts)
+{
+ return ts.tv_sec == 0 ||
+ ts.tv_sec == (time_t)0xFFFFFFFF ||
+ ts.tv_sec == (time_t)-1;
+}
+
/*******************************************************************
create a 16 bit dos packed date
********************************************************************/
@@ -547,8 +555,9 @@ NTTIME timeval_to_nttime(const struct timeval *tv)
}
/*******************************************************************
-yield the difference between *A and *B, in seconds, ignoring leap seconds
+ Yield the difference between *A and *B, in seconds, ignoring leap seconds.
********************************************************************/
+
static int tm_diff(struct tm *a, struct tm *b)
{
int ay = a->tm_year + (1900 - 1);
@@ -566,9 +575,10 @@ static int tm_diff(struct tm *a, struct tm *b)
int extra_time_offset=0;
-/**
- return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
- */
+/*******************************************************************
+ Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
+********************************************************************/
+
int get_time_zone(time_t t)
{
struct tm *tm = gmtime(&t);
@@ -778,7 +788,7 @@ void put_long_date(char *p, time_t t)
structure.
****************************************************************************/
-time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+time_t get_create_time(const SMB_STRUCT_STAT *st,BOOL fake_dirs)
{
time_t ret, ret1;
@@ -800,7 +810,7 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
return ret;
}
-struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,BOOL fake_dirs)
{
struct timespec ts;
ts.tv_sec = get_create_time(st, fake_dirs);
@@ -812,7 +822,7 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
Get/Set all the possible time fields from a stat struct as a timespec.
****************************************************************************/
-struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_atimespec(const SMB_STRUCT_STAT *pst)
{
#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret;
@@ -852,7 +862,7 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
#endif
}
-struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst)
{
#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret;
@@ -892,7 +902,7 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
#endif
}
-struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst)
{
#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret;
@@ -1020,6 +1030,81 @@ time_t convert_timespec_to_time_t(struct timespec ts)
return ts.tv_sec;
}
+struct timespec convert_time_t_to_timespec(time_t t)
+{
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ return ts;
+}
+
+/****************************************************************************
+ Convert a normalized timeval to a timespec.
+****************************************************************************/
+
+struct timespec convert_timeval_to_timespec(const struct timeval tv)
+{
+ struct timespec ts;
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ return ts;
+}
+
+/****************************************************************************
+ Convert a normalized timespec to a timeval.
+****************************************************************************/
+
+struct timeval convert_timespec_to_timeval(const struct timespec ts)
+{
+ struct timeval tv;
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+ return tv;
+}
+
+/****************************************************************************
+ Return a timespec for the current time
+****************************************************************************/
+
+struct timespec timespec_current(void)
+{
+ struct timeval tv;
+ struct timespec ts;
+ GetTimeOfDay(&tv);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_sec * 1000;
+ return ts;
+}
+
+/****************************************************************************
+ Return the lesser of two timespecs.
+****************************************************************************/
+
+struct timespec timespec_min(const struct timespec *ts1,
+ const struct timespec *ts2)
+{
+ if (ts1->tv_sec < ts2->tv_sec) return *ts1;
+ if (ts1->tv_sec > ts2->tv_sec) return *ts2;
+ if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
+ return *ts2;
+}
+
+/****************************************************************************
+ compare two timespec structures.
+ Return -1 if ts1 < ts2
+ Return 0 if ts1 == ts2
+ Return 1 if ts1 > ts2
+****************************************************************************/
+
+int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
+{
+ if (ts1->tv_sec > ts2->tv_sec) return 1;
+ if (ts1->tv_sec < ts2->tv_sec) return -1;
+ if (ts1->tv_nsec > ts2->tv_nsec) return 1;
+ if (ts1->tv_nsec < ts2->tv_nsec) return -1;
+ return 0;
+}
+
/****************************************************************************
Interprets an nt time into a unix struct timespec.
Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
@@ -1180,6 +1265,10 @@ time_t nt_time_to_unix_abs(const NTTIME *nt)
return (time_t)-1;
}
+ if (*nt == NTTIME_INFINITY) {
+ return (time_t)-1;
+ }
+
/* reverse the time */
/* it's a negative value, turn it to positive */
d=~*nt;
@@ -1248,7 +1337,7 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
if (t == (time_t)-1) {
/* that's what NT uses for infinite */
- *nt = 0x8000000000000000LL;
+ *nt = NTTIME_INFINITY;
return;
}
@@ -1278,10 +1367,10 @@ BOOL null_mtime(time_t mtime)
and asctime fail.
****************************************************************************/
-const char *time_to_asc(const time_t *t)
+const char *time_to_asc(const time_t t)
{
const char *asct;
- struct tm *lt = localtime(t);
+ struct tm *lt = localtime(&t);
if (!lt) {
return "unknown time";
@@ -1306,7 +1395,7 @@ const char *display_time(NTTIME nttime)
if (nttime==0)
return "Now";
- if (nttime==0x8000000000000000LL)
+ if (nttime==NTTIME_INFINITY)
return "Never";
high = 65536;
@@ -1335,10 +1424,9 @@ BOOL nt_time_is_set(const NTTIME *nt)
return False;
}
- if (*nt == 0x8000000000000000LL) {
+ if (*nt == NTTIME_INFINITY) {
return False;
}
return True;
}
-
diff --git a/source/lib/util.c b/source/lib/util.c
index 67c9c8d37a7..45d3916ebe6 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -200,6 +200,7 @@ void gfree_all( void )
gfree_debugsyms();
gfree_charcnv();
gfree_messages();
+ gfree_interfaces();
/* release the talloc null_context memory last */
talloc_disable_null_tracking();
@@ -579,6 +580,13 @@ void dos_clean_name(char *s)
/* remove any double slashes */
all_string_sub(s, "\\\\", "\\", 0);
+ /* Remove leading .\\ characters */
+ if(strncmp(s, ".\\", 2) == 0) {
+ trim_string(s, ".\\", NULL);
+ if(*s == 0)
+ pstrcpy(s,".\\");
+ }
+
while ((p = strstr_m(s,"\\..\\")) != NULL) {
pstring s1;
@@ -593,7 +601,6 @@ void dos_clean_name(char *s)
}
trim_string(s,NULL,"\\..");
-
all_string_sub(s, "\\.\\", "\\", 0);
}
@@ -631,6 +638,13 @@ void unix_clean_name(char *s)
}
trim_string(s,NULL,"/..");
+ all_string_sub(s, "/./", "/", 0);
+}
+
+void clean_name(char *s)
+{
+ dos_clean_name(s);
+ unix_clean_name(s);
}
/*******************************************************************
@@ -913,17 +927,6 @@ void *malloc_(size_t size)
}
/****************************************************************************
- Internal malloc wrapper. Externally visible.
-****************************************************************************/
-
-void *memalign_(size_t align, size_t size)
-{
-#undef memalign
- return memalign(align, size);
-#define memalign(align, s) __ERROR_DONT_USE_MEMALIGN_DIRECTLY
-}
-
-/****************************************************************************
Internal calloc wrapper. Not externally visible.
****************************************************************************/
@@ -974,11 +977,7 @@ void *memalign_array(size_t el_size, size_t align, unsigned int count)
return NULL;
}
-#if defined(PARANOID_MALLOC_CHECKER)
- return memalign_(align, el_size*count);
-#else
return sys_memalign(align, el_size*count);
-#endif
}
/****************************************************************************
@@ -2093,6 +2092,9 @@ BOOL is_myname_or_ipaddr(const char *s)
/* check for loopback */
+ if (strequal(servername, "127.0.0.1"))
+ return True;
+
if (strequal(servername, "localhost"))
return True;
diff --git a/source/libaddns/dnsgss.c b/source/libaddns/dnsgss.c
index 798fd4404ee..8324e6761f3 100644
--- a/source/libaddns/dnsgss.c
+++ b/source/libaddns/dnsgss.c
@@ -252,6 +252,11 @@ DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
krb5_init_context( &krb_ctx );
krb5_parse_name( krb_ctx, targetname, &host_principal );
+ /* don't free the principal until after you call
+ gss_release_name() or else you'll get a segv
+ as the krb5_copy_principal() does a structure
+ copy and not a deep copy. --jerry*/
+
input_name.value = &host_principal;
input_name.length = sizeof( host_principal );
@@ -267,8 +272,11 @@ DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname,
targ_name, gss_ctx, srv_type );
-
+
gss_release_name( &minor, &targ_name );
+
+ /* now we can free the principal */
+
krb5_free_principal( krb_ctx, host_principal );
krb5_free_context( krb_ctx );
diff --git a/source/libads/cldap.c b/source/libads/cldap.c
index 72018c620d8..3cb98c59c58 100644
--- a/source/libads/cldap.c
+++ b/source/libads/cldap.c
@@ -187,8 +187,10 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
{
int ret;
ASN1_DATA data;
- DATA_BLOB blob;
- DATA_BLOB os1, os2, os3;
+ DATA_BLOB blob = data_blob(NULL, 0);
+ DATA_BLOB os1 = data_blob(NULL, 0);
+ DATA_BLOB os2 = data_blob(NULL, 0);
+ DATA_BLOB os3 = data_blob(NULL, 0);
int i1;
/* half the time of a regular ldap timeout, not less than 3 seconds. */
unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
@@ -238,6 +240,9 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
if (data.has_error) {
data_blob_free(&blob);
+ data_blob_free(&os1);
+ data_blob_free(&os2);
+ data_blob_free(&os3);
asn1_free(&data);
DEBUG(1,("Failed to parse cldap reply\n"));
return -1;
diff --git a/source/libads/kerberos_keytab.c b/source/libads/kerberos_keytab.c
index ba1a9165674..0ad225fbebb 100644
--- a/source/libads/kerberos_keytab.c
+++ b/source/libads/kerberos_keytab.c
@@ -55,20 +55,20 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
ret = smb_krb5_parse_name(context, princ_s, &princ);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
goto out;
}
/* Seek and delete old keytab entries */
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if (ret != KRB5_KT_END && ret != ENOENT ) {
- DEBUG(3,("ads_keytab_add_entry: Will try to delete old keytab entries\n"));
+ DEBUG(3,("smb_krb5_kt_add_entry: Will try to delete old keytab entries\n"));
while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
BOOL compare_name_ok = False;
ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: smb_krb5_unparse_name failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
goto out;
}
@@ -89,7 +89,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
#endif
if (!compare_name_ok) {
- DEBUG(10,("ads_keytab_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
+ DEBUG(10,("smb_krb5_kt_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
ktprinc, kt_entry.vno));
}
@@ -97,39 +97,39 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
if (compare_name_ok) {
if (kt_entry.vno == kvno - 1) {
- DEBUG(5,("ads_keytab_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
+ DEBUG(5,("smb_krb5_kt_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
kvno - 1, princ_s));
} else {
- DEBUG(5,("ads_keytab_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
+ DEBUG(5,("smb_krb5_kt_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
princ_s, kt_entry.vno));
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
ZERO_STRUCT(cursor);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
error_message(ret)));
goto out;
}
ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
error_message(ret)));
goto out;
}
- DEBUG(5,("ads_keytab_add_entry: removed old entry for principal: %s (kvno %d).\n",
+ DEBUG(5,("smb_krb5_kt_add_entry: removed old entry for principal: %s (kvno %d).\n",
princ_s, kt_entry.vno));
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_kt_start_seq failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_start_seq failed (%s)\n",
error_message(ret)));
goto out;
}
ret = smb_krb5_kt_free_entry(context, &kt_entry);
ZERO_STRUCT(kt_entry);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+ DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
error_message(ret)));
goto out;
}
@@ -141,7 +141,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
ret = smb_krb5_kt_free_entry(context, &kt_entry);
ZERO_STRUCT(kt_entry);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
goto out;
}
}
@@ -149,7 +149,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
ZERO_STRUCT(cursor);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
goto out;
}
}
@@ -180,13 +180,13 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
kt_entry.principal = princ;
kt_entry.vno = kvno;
- DEBUG(3,("ads_keytab_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
+ DEBUG(3,("smb_krb5_kt_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
princ_s, enctypes[i], kt_entry.vno));
ret = krb5_kt_add_entry(context, keytab, &kt_entry);
krb5_free_keyblock_contents(context, keyp);
ZERO_STRUCT(kt_entry);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
+ DEBUG(1,("smb_krb5_kt_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
goto out;
}
}
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index 2c114b1240e..0ec03ef4bf2 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -7,6 +7,7 @@
Copyright (C) Guenther Deschner 2003, 2005
Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+ Copyright (C) Jeremy Allison 2007
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
@@ -37,9 +38,12 @@ const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
ads_keytab_add_entry function for details.
***********************************************************************************/
-static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context,
- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
- krb5_keyblock **keyblock)
+static BOOL ads_keytab_verify_ticket(krb5_context context,
+ krb5_auth_context auth_context,
+ const DATA_BLOB *ticket,
+ krb5_ticket **pp_tkt,
+ krb5_keyblock **keyblock,
+ krb5_error_code *perr)
{
krb5_error_code ret = 0;
BOOL auth_ok = False;
@@ -51,6 +55,11 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
fstring my_name, my_fqdn;
int i;
int number_matched_principals = 0;
+ krb5_data packet;
+
+ *pp_tkt = NULL;
+ *keyblock = NULL;
+ *perr = 0;
/* Generate the list of principal names which we expect
* clients might want to use for authenticating to the file
@@ -103,11 +112,11 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
}
number_matched_principals++;
- p_packet->length = ticket->length;
- p_packet->data = (char *)ticket->data;
+ packet.length = ticket->length;
+ packet.data = (char *)ticket->data;
*pp_tkt = NULL;
- ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
+ ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, &packet,
kt_entry.principal, keytab,
NULL, pp_tkt, keyblock);
@@ -125,7 +134,8 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
* entries - Guenther */
if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
- ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+ ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
+ ret == KRB5KRB_AP_ERR_SKEW) {
break;
}
} else {
@@ -184,6 +194,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
if (keytab) {
krb5_kt_close(context, keytab);
}
+ *perr = ret;
return auth_ok;
}
@@ -191,32 +202,40 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
Try to verify a ticket using the secrets.tdb.
***********************************************************************************/
-static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context,
- krb5_principal host_princ,
- const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
- krb5_keyblock **keyblock)
+static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_principal host_princ,
+ const DATA_BLOB *ticket,
+ krb5_ticket **pp_tkt,
+ krb5_keyblock **keyblock,
+ krb5_error_code *perr)
{
krb5_error_code ret = 0;
BOOL auth_ok = False;
char *password_s = NULL;
krb5_data password;
krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, 0, 0 };
+ krb5_data packet;
int i;
+ *pp_tkt = NULL;
+ *keyblock = NULL;
+ *perr = 0;
+
#if defined(ENCTYPE_ARCFOUR_HMAC)
enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
#endif
- ZERO_STRUCTP(keyblock);
-
if (!secrets_init()) {
DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
+ *perr = KRB5_CONFIG_CANTOPEN;
return False;
}
password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
if (!password_s) {
DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
+ *perr = KRB5_LIBOS_CANTREADPWD;
return False;
}
@@ -225,14 +244,15 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
- p_packet->length = ticket->length;
- p_packet->data = (char *)ticket->data;
+ packet.length = ticket->length;
+ packet.data = (char *)ticket->data;
/* We need to setup a auth context with each possible encoding type in turn. */
for (i=0;enctypes[i];i++) {
krb5_keyblock *key = NULL;
if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
+ ret = ENOMEM;
goto out;
}
@@ -243,7 +263,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
krb5_auth_con_setuseruserkey(context, auth_context, key);
- if (!(ret = krb5_rd_req(context, &auth_context, p_packet,
+ if (!(ret = krb5_rd_req(context, &auth_context, &packet,
NULL,
NULL, NULL, pp_tkt))) {
DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
@@ -260,7 +280,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
/* successfully decrypted but ticket is just not valid at the moment */
if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
- ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+ ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
+ ret == KRB5KRB_AP_ERR_SKEW) {
break;
}
@@ -270,7 +291,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
out:
SAFE_FREE(password_s);
-
+ *perr = ret;
return auth_ok;
}
@@ -280,9 +301,11 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
***********************************************************************************/
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
- const char *realm, time_t time_offset,
- const DATA_BLOB *ticket,
- char **principal, PAC_DATA **pac_data,
+ const char *realm,
+ time_t time_offset,
+ const DATA_BLOB *ticket,
+ char **principal,
+ PAC_DATA **pac_data,
DATA_BLOB *ap_rep,
DATA_BLOB *session_key)
{
@@ -296,20 +319,22 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
krb5_rcache rcache = NULL;
krb5_keyblock *keyblock = NULL;
time_t authtime;
- int ret;
-
+ krb5_error_code ret = 0;
+
krb5_principal host_princ = NULL;
krb5_const_principal client_principal = NULL;
char *host_princ_s = NULL;
- BOOL got_replay_mutex = False;
-
BOOL auth_ok = False;
+ BOOL got_replay_mutex = False;
BOOL got_auth_data = False;
ZERO_STRUCT(packet);
ZERO_STRUCT(auth_data);
- ZERO_STRUCTP(ap_rep);
- ZERO_STRUCTP(session_key);
+
+ *principal = NULL;
+ *pac_data = NULL;
+ *ap_rep = data_blob(NULL,0);
+ *session_key = data_blob(NULL,0);
initialize_krb5_error_table();
ret = krb5_init_context(&context);
@@ -339,6 +364,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
}
asprintf(&host_princ_s, "%s$", global_myname());
+ if (!host_princ_s) {
+ goto out;
+ }
+
strlower_m(host_princ_s);
ret = smb_krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) {
@@ -353,6 +382,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
if (!grab_server_mutex("replay cache mutex")) {
DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
+ ret = KRB5_CC_IO;
goto out;
}
@@ -375,11 +405,11 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
}
if (lp_use_kerberos_keytab()) {
- auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, &keyblock);
+ auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &tkt, &keyblock, &ret);
}
if (!auth_ok) {
auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
- ticket, &packet, &tkt, &keyblock);
+ ticket, &tkt, &keyblock, &ret);
}
release_server_mutex();
@@ -395,6 +425,15 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
if (!auth_ok) {
DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n",
error_message(ret)));
+ /* Try map the error return in case it's something like
+ * a clock skew error.
+ */
+ sret = krb5_to_nt_status(ret);
+ if (NT_STATUS_IS_OK(sret) || NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) {
+ sret = NT_STATUS_LOGON_FAILURE;
+ }
+ DEBUG(10,("ads_verify_ticket: returning error %s\n",
+ nt_errstr(sret) ));
goto out;
}
@@ -409,8 +448,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
}
*ap_rep = data_blob(packet.data, packet.length);
- SAFE_FREE(packet.data);
- packet.length = 0;
+ if (packet.data) {
+ kerberos_free_data_contents(context, &packet);
+ ZERO_STRUCT(packet);
+ }
get_krb5_smb_session_key(context, auth_context, session_key, True);
dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
diff --git a/source/libads/krb5_errs.c b/source/libads/krb5_errs.c
index 89cfc2d1439..c153bee96e6 100644
--- a/source/libads/krb5_errs.c
+++ b/source/libads/krb5_errs.c
@@ -59,6 +59,8 @@ static const struct {
{KRB5_CC_NOTFOUND, NT_STATUS_NO_SUCH_FILE},
{KRB5_FCC_NOFILE, NT_STATUS_NO_SUCH_FILE},
{KRB5KDC_ERR_NONE, NT_STATUS_OK},
+ {KRB5_RC_MALLOC, NT_STATUS_NO_MEMORY},
+ {ENOMEM, NT_STATUS_NO_MEMORY},
{0, NT_STATUS_OK}
};
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index dfc68fdc2b1..1d08a01a263 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -1635,6 +1635,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
char *samAccountName, *controlstr;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
+ char *machine_escaped = NULL;
char *new_dn;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
@@ -1647,8 +1648,13 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
return ADS_ERROR(LDAP_NO_MEMORY);
ret = ADS_ERROR(LDAP_NO_MEMORY);
-
- new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_name, org_unit);
+
+ machine_escaped = escape_rdn_val_string_alloc(machine_name);
+ if (!machine_escaped) {
+ goto done;
+ }
+
+ new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_escaped, org_unit);
samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
if ( !new_dn || !samAccountName ) {
@@ -1675,6 +1681,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
ret = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(machine_escaped);
ads_msgfree(ads, res);
talloc_destroy(ctx);
diff --git a/source/libads/ldap_user.c b/source/libads/ldap_user.c
index 66d94d29d3a..afbbc0b421a 100644
--- a/source/libads/ldap_user.c
+++ b/source/libads/ldap_user.c
@@ -50,6 +50,7 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
ADS_MODLIST mods;
ADS_STATUS status;
const char *upn, *new_dn, *name, *controlstr;
+ char *name_escaped = NULL;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", NULL};
@@ -63,7 +64,9 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->config.realm)))
goto done;
- if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name, container,
+ if (!(name_escaped = escape_rdn_val_string_alloc(name)))
+ goto done;
+ if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container,
ads->config.bind_path)))
goto done;
if (!(controlstr = talloc_asprintf(ctx, "%u", (UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE))))
@@ -81,6 +84,7 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
status = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(name_escaped);
talloc_destroy(ctx);
return status;
}
@@ -92,6 +96,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
ADS_MODLIST mods;
ADS_STATUS status;
char *new_dn;
+ char *name_escaped = NULL;
const char *objectClass[] = {"top", "group", NULL};
if (!(ctx = talloc_init("ads_add_group_acct")))
@@ -99,7 +104,9 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
status = ADS_ERROR(LDAP_NO_MEMORY);
- if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", group, container,
+ if (!(name_escaped = escape_rdn_val_string_alloc(group)))
+ goto done;
+ if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container,
ads->config.bind_path)))
goto done;
if (!(mods = ads_init_mods(ctx)))
@@ -114,6 +121,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
status = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(name_escaped);
talloc_destroy(ctx);
return status;
}
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 812f3961f19..013985a1215 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -311,9 +311,9 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
int gss_rc, rc;
uint8 *p;
uint32 max_msg_size = 0;
- char *sname;
+ char *sname = NULL;
ADS_STATUS status;
- krb5_principal principal;
+ krb5_principal principal = NULL;
krb5_context ctx = NULL;
krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC
@@ -331,25 +331,40 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
initialize_krb5_error_table();
status = ADS_ERROR_KRB5(krb5_init_context(&ctx));
if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(sname);
return status;
}
status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types));
if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(sname);
+ krb5_free_context(ctx);
return status;
}
status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal));
if (!ADS_ERR_OK(status)) {
+ SAFE_FREE(sname);
+ krb5_free_context(ctx);
return status;
}
- free(sname);
- krb5_free_context(ctx);
-
input_name.value = &principal;
input_name.length = sizeof(principal);
gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name);
+
+ /*
+ * The MIT libraries have a *HORRIBLE* bug - input_value.value needs
+ * to point to the *address* of the krb5_principal, and the gss libraries
+ * to a shallow copy of the krb5_principal pointer - so we need to keep
+ * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* !
+ * Just one more way in which MIT engineers screwed me over.... JRA.
+ */
+
+ SAFE_FREE(sname);
+
if (gss_rc) {
+ krb5_free_principal(ctx, principal);
+ krb5_free_context(ctx);
return ADS_ERROR_GSS(gss_rc, minor_status);
}
@@ -407,8 +422,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
if (gss_rc == 0) break;
}
- gss_release_name(&minor_status, &serv_name);
-
gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
(int *)&conf_state,NULL);
if (gss_rc) {
@@ -463,6 +476,11 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_buffer(&minor_status, &input_token);
failed:
+
+ gss_release_name(&minor_status, &serv_name);
+ krb5_free_principal(ctx, principal);
+ krb5_free_context(ctx);
+
if(scred)
ber_bvfree(scred);
return status;
diff --git a/source/libads/smb_krb5_locator.c b/source/libads/smb_krb5_locator.c
new file mode 100644
index 00000000000..be14a126974
--- /dev/null
+++ b/source/libads/smb_krb5_locator.c
@@ -0,0 +1,386 @@
+/*
+ Unix SMB/CIFS implementation.
+ kerberos locator plugin
+ Copyright (C) Guenther Deschner 2007
+
+ 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"
+
+#if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
+
+#include <krb5/locate_plugin.h>
+
+static const char *get_service_from_locate_service_type(enum locate_service_type svc)
+{
+ switch (svc) {
+ case locate_service_kdc:
+ case locate_service_master_kdc:
+ return "88";
+ case locate_service_kadmin:
+ case locate_service_krb524:
+ /* not supported */
+ return NULL;
+ case locate_service_kpasswd:
+ return "464";
+ default:
+ break;
+ }
+ return NULL;
+
+}
+
+static const char *locate_service_type_name(enum locate_service_type svc)
+{
+ switch (svc) {
+ case locate_service_kdc:
+ return "locate_service_kdc";
+ case locate_service_master_kdc:
+ return "locate_service_master_kdc";
+ case locate_service_kadmin:
+ return "locate_service_kadmin";
+ case locate_service_krb524:
+ return "locate_service_krb524";
+ case locate_service_kpasswd:
+ return "locate_service_kpasswd";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static const char *socktype_name(int socktype)
+{
+ switch (socktype) {
+ case SOCK_STREAM:
+ return "SOCK_STREAM";
+ case SOCK_DGRAM:
+ return "SOCK_DGRAM";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
+static const char *family_name(int family)
+{
+ switch (family) {
+ case AF_UNSPEC:
+ return "AF_UNSPEC";
+ case AF_INET:
+ return "AF_INET";
+ case AF_INET6:
+ return "AF_INET6";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
+/**
+ * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
+ *
+ * @param svc
+ * @param realm string
+ * @param socktype integer
+ * @param family integer
+ *
+ * @return integer.
+ */
+
+static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
+ const char *realm,
+ int socktype,
+ int family)
+{
+ if (!realm || strlen(realm) == 0) {
+ return EINVAL;
+ }
+
+ switch (svc) {
+ case locate_service_kdc:
+ case locate_service_master_kdc:
+ case locate_service_kpasswd:
+ break;
+ case locate_service_kadmin:
+ case locate_service_krb524:
+#ifdef KRB5_PLUGIN_NO_HANDLE
+ return KRB5_PLUGIN_NO_HANDLE;
+#else
+ return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+ default:
+ return EINVAL;
+ }
+
+ switch (family) {
+ case AF_UNSPEC:
+ case AF_INET:
+ break;
+ case AF_INET6: /* not yet */
+#ifdef KRB5_PLUGIN_NO_HANDLE
+ return KRB5_PLUGIN_NO_HANDLE;
+#else
+ return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+ default:
+ return EINVAL;
+ }
+
+ switch (socktype) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ case 0: /* Heimdal uses that */
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * Try to get addrinfo for a given host and call the krb5 callback
+ *
+ * @param name string
+ * @param service string
+ * @param in struct addrinfo hint
+ * @param cbfunc krb5 callback function
+ * @param cbdata void pointer cbdata
+ *
+ * @return krb5_error_code.
+ */
+
+static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name,
+ const char *service,
+ struct addrinfo *in,
+ int (*cbfunc)(void *, int, struct sockaddr *),
+ void *cbdata)
+{
+ struct addrinfo *out;
+ int ret;
+ int count = 3;
+
+ while (count) {
+
+ ret = getaddrinfo(name, service, in, &out);
+ if (ret == 0) {
+ break;
+ }
+
+ if (ret == EAI_AGAIN) {
+ count--;
+ continue;
+ }
+
+ DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n",
+ gai_strerror(ret), ret));
+#ifdef KRB5_PLUGIN_NO_HANDLE
+ return KRB5_PLUGIN_NO_HANDLE;
+#else
+ return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+ }
+
+ ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
+ if (ret) {
+ DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n",
+ error_message(ret), ret));
+ }
+
+ freeaddrinfo(out);
+
+ return ret;
+}
+
+/**
+ * PUBLIC INTERFACE: locate init
+ *
+ * @param context krb5_context
+ * @param privata_data pointer to private data pointer
+ *
+ * @return krb5_error_code.
+ */
+
+krb5_error_code smb_krb5_locator_init(krb5_context context,
+ void **private_data)
+{
+ setup_logging("smb_krb5_locator", True);
+ load_case_tables();
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
+
+ DEBUG(10,("smb_krb5_locator_init: called\n"));
+
+ return 0;
+}
+
+/**
+ * PUBLIC INTERFACE: close locate
+ *
+ * @param private_data pointer to private data
+ *
+ * @return void.
+ */
+
+void smb_krb5_locator_close(void *private_data)
+{
+ DEBUG(10,("smb_krb5_locator_close: called\n"));
+
+ /* gfree_all(); */
+}
+
+/**
+ * PUBLIC INTERFACE: locate lookup
+ *
+ * @param private_data pointer to private data
+ * @param svc enum locate_service_type.
+ * @param realm string
+ * @param socktype integer
+ * @param family integer
+ * @param cbfunc callback function to send back entries
+ * @param cbdata void pointer to cbdata
+ *
+ * @return krb5_error_code.
+ */
+
+krb5_error_code smb_krb5_locator_lookup(void *private_data,
+ enum locate_service_type svc,
+ const char *realm,
+ int socktype,
+ int family,
+ int (*cbfunc)(void *, int, struct sockaddr *),
+ void *cbdata)
+{
+ NTSTATUS status;
+ krb5_error_code ret;
+ char *sitename = NULL;
+ struct ip_service *ip_list;
+ int count = 0;
+ struct addrinfo aihints;
+ char *saf_name = NULL;
+ int i;
+
+ DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
+ DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n",
+ locate_service_type_name(svc), svc, realm));
+ DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n",
+ socktype_name(socktype), socktype,
+ family_name(family), family));
+
+ ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, family);
+ if (ret) {
+ DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n",
+ error_message(ret), ret));
+ return ret;
+ }
+
+ /* first try to fetch from SAF cache */
+
+ saf_name = saf_fetch(realm);
+ if (!saf_name || strlen(saf_name) == 0) {
+ DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n",
+ realm));
+ goto find_kdc;
+ }
+
+ DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n",
+ saf_name, realm));
+
+ ZERO_STRUCT(aihints);
+
+ aihints.ai_family = family;
+ aihints.ai_socktype = socktype;
+
+ ret = smb_krb5_locator_call_cbfunc(saf_name,
+ get_service_from_locate_service_type(svc),
+ &aihints,
+ cbfunc, cbdata);
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+
+ find_kdc:
+
+ /* now try to find via site-aware DNS SRV query */
+
+ sitename = sitename_fetch(realm);
+ status = get_kdc_list(realm, sitename, &ip_list, &count);
+
+ /* if we didn't found any KDCs on our site go to the main list */
+
+ if (NT_STATUS_IS_OK(status) && sitename && (count == 0)) {
+ SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
+ status = get_kdc_list(realm, NULL, &ip_list, &count);
+ }
+
+ SAFE_FREE(sitename);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
+ nt_errstr(status),
+ error_message(nt_status_to_krb5(status))));
+#ifdef KRB5_PLUGIN_NO_HANDLE
+ return KRB5_PLUGIN_NO_HANDLE;
+#else
+ return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+ }
+
+ for (i=0; i<count; i++) {
+
+ const char *host = NULL;
+ const char *port = NULL;
+
+ ZERO_STRUCT(aihints);
+
+ aihints.ai_family = family;
+ aihints.ai_socktype = socktype;
+
+ host = inet_ntoa(ip_list[i].ip);
+ port = get_service_from_locate_service_type(svc);
+
+ ret = smb_krb5_locator_call_cbfunc(host,
+ port,
+ &aihints,
+ cbfunc, cbdata);
+ if (ret) {
+ /* got error */
+ break;
+ }
+ }
+
+ SAFE_FREE(ip_list);
+
+ return ret;
+}
+
+#ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
+#define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
+#else
+#define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
+#endif
+
+const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
+ 0, /* version */
+ smb_krb5_locator_init,
+ smb_krb5_locator_close,
+ smb_krb5_locator_lookup,
+};
+
+#endif
diff --git a/source/librpc/ndr/libndr.h b/source/librpc/ndr/libndr.h
index 32dd0ef6c59..faa7c56455d 100644
--- a/source/librpc/ndr/libndr.h
+++ b/source/librpc/ndr/libndr.h
@@ -223,7 +223,7 @@ enum ndr_compression_alg {
} \
} while(0)
-#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, n))
#define NDR_PUSH_ALIGN(ndr, n) do { \
if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
diff --git a/source/librpc/ndr/ndr.c b/source/librpc/ndr/ndr.c
index f6a132c1861..4f0599e5c03 100644
--- a/source/librpc/ndr/ndr.c
+++ b/source/librpc/ndr/ndr.c
@@ -160,10 +160,18 @@ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
/*
- expand the available space in the buffer to 'size'
+ expand the available space in the buffer to ndr->offset + extra_size
*/
-NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size)
+NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
{
+ uint32_t size = extra_size + ndr->offset;
+
+ if (size < ndr->offset) {
+ /* extra_size overflowed the offset */
+ return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
+ size);
+ }
+
if (ndr->alloc_size > size) {
return NT_STATUS_OK;
}
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index e2213c1fcde..0f09747dbf1 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -693,8 +693,6 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
nt_status = NT_STATUS_UNSUCCESSFUL;
} else {
- data_blob_free(&msg1);
-
blob = cli_session_setup_blob_receive(cli);
nt_status = cli_nt_error(cli);
@@ -706,6 +704,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
}
}
}
+ data_blob_free(&msg1);
}
if (!blob.length) {
@@ -736,6 +735,8 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
turn++;
} while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+ data_blob_free(&blob_in);
+
if (NT_STATUS_IS_OK(nt_status)) {
DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
index 916e4cefc6e..4009b98b418 100644
--- a/source/libsmb/clidfs.c
+++ b/source/libsmb/clidfs.c
@@ -3,6 +3,7 @@
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Gerald (Jerry) Carter 2004
+ Copyright (C) Jeremy Allison 2007
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
@@ -21,6 +22,16 @@
#include "includes.h"
+/********************************************************************
+ Important point.
+
+ DFS paths are *always* of the form \server\share\<pathname> (the \ characters
+ are not C escaped here).
+
+ - but if we're using POSIX paths then <pathname> may contain
+ '/' separators, not '\\' separators. So cope with '\\' or '/'
+ as a separator when looking at the pathname part.... JRA.
+********************************************************************/
struct client_connection {
struct client_connection *prev, *next;
@@ -194,14 +205,14 @@ static void cli_cm_set_mntpoint( struct cli_state *c, const char *mnt )
if ( p ) {
pstrcpy( p->mount, mnt );
- dos_clean_name( p->mount );
+ clean_name(p->mount);
}
}
/****************************************************************************
****************************************************************************/
-const char * cli_cm_get_mntpoint( struct cli_state *c )
+const char *cli_cm_get_mntpoint( struct cli_state *c )
{
struct client_connection *p;
int i;
@@ -221,8 +232,9 @@ const char * cli_cm_get_mntpoint( struct cli_state *c )
Add a new connection to the list
********************************************************************/
-static struct cli_state* cli_cm_connect( const char *server, const char *share,
- BOOL show_hdr )
+static struct cli_state *cli_cm_connect( const char *server,
+ const char *share,
+ BOOL show_hdr)
{
struct client_connection *node;
@@ -247,7 +259,7 @@ static struct cli_state* cli_cm_connect( const char *server, const char *share,
Return a connection to a server.
********************************************************************/
-static struct cli_state* cli_cm_find( const char *server, const char *share )
+static struct cli_state *cli_cm_find( const char *server, const char *share )
{
struct client_connection *p;
@@ -264,7 +276,9 @@ static struct cli_state* cli_cm_find( const char *server, const char *share )
global variable as a side-effect (but only if the connection is successful).
****************************************************************************/
-struct cli_state* cli_cm_open( const char *server, const char *share, BOOL show_hdr )
+struct cli_state *cli_cm_open(const char *server,
+ const char *share,
+ BOOL show_hdr)
{
struct cli_state *c;
@@ -272,8 +286,9 @@ struct cli_state* cli_cm_open( const char *server, const char *share, BOOL show_
c = cli_cm_find( server, share );
- if ( !c )
- c = cli_cm_connect( server, share, show_hdr );
+ if ( !c ) {
+ c = cli_cm_connect(server, share, show_hdr);
+ }
return c;
}
@@ -295,7 +310,6 @@ void cli_cm_shutdown( void )
}
connections = NULL;
-
return;
}
@@ -354,110 +368,104 @@ void cli_cm_set_dest_ip(struct in_addr ip )
have_ip = True;
}
-/********************************************************************
- split a dfs path into the server and share name components
-********************************************************************/
+/**********************************************************************
+ split a dfs path into the server, share name, and extrapath components
+**********************************************************************/
-static void split_dfs_path( const char *nodepath, fstring server, fstring share )
+static void split_dfs_path( const char *nodepath, fstring server, fstring share, pstring extrapath )
{
- char *p;
+ char *p, *q;
pstring path;
pstrcpy( path, nodepath );
- if ( path[0] != '\\' )
+ if ( path[0] != '\\' ) {
return;
+ }
- p = strrchr_m( path, '\\' );
-
- if ( !p )
+ p = strchr_m( path + 1, '\\' );
+ if ( !p ) {
return;
+ }
*p = '\0';
p++;
+ /* Look for any extra/deep path */
+ q = strchr_m(p, '\\');
+ if (q != NULL) {
+ *q = '\0';
+ q++;
+ pstrcpy( extrapath, q );
+ } else {
+ pstrcpy( extrapath, '\0' );
+ }
+
fstrcpy( share, p );
fstrcpy( server, &path[1] );
}
/****************************************************************************
- return the original path truncated at the first wildcard character
- (also strips trailing \'s). Trust the caller to provide a NULL
+ Return the original path truncated at the directory component before
+ the first wildcard character. Trust the caller to provide a NULL
terminated string
****************************************************************************/
-static void clean_path( pstring clean, const char *path )
+static void clean_path(const char *path, pstring path_out)
{
- int len;
- char *p;
- pstring newpath;
-
- pstrcpy( newpath, path );
- p = newpath;
-
- while ( p ) {
- /* first check for '*' */
+ size_t len;
+ char *p1, *p2, *p;
- p = strrchr_m( newpath, '*' );
- if ( p ) {
- *p = '\0';
- p = newpath;
- continue;
+ /* No absolute paths. */
+ while (IS_DIRECTORY_SEP(*path)) {
+ path++;
+ }
+
+ pstrcpy(path_out, path);
+
+ p1 = strchr_m(path_out, '*');
+ p2 = strchr_m(path_out, '?');
+
+ if (p1 || p2) {
+ if (p1 && p2) {
+ p = MIN(p1,p2);
+ } else if (!p1) {
+ p = p2;
+ } else {
+ p = p1;
}
-
- /* first check for '?' */
-
- p = strrchr_m( newpath, '?' );
- if ( p ) {
+ *p = '\0';
+
+ /* Now go back to the start of this component. */
+ p1 = strrchr_m(path_out, '/');
+ p2 = strrchr_m(path_out, '\\');
+ p = MAX(p1,p2);
+ if (p) {
*p = '\0';
- p = newpath;
}
}
-
- /* strip a trailing backslash */
-
- len = strlen( newpath );
- if ( (len > 0) && (newpath[len-1] == '\\') )
- newpath[len-1] = '\0';
-
- pstrcpy( clean, newpath );
+
+ /* Strip any trailing separator */
+
+ len = strlen(path_out);
+ if ( (len > 0) && IS_DIRECTORY_SEP(path_out[len-1])) {
+ path_out[len-1] = '\0';
+ }
}
/****************************************************************************
****************************************************************************/
-BOOL cli_dfs_make_full_path( pstring path, const char *server, const char *share,
- const char *dir )
+static void cli_dfs_make_full_path( struct cli_state *cli,
+ const char *dir,
+ pstring path_out)
{
- pstring servicename;
- char *sharename;
- const char *directory;
-
-
- /* make a copy so we don't modify the global string 'service' */
-
- pstrcpy(servicename, share);
- sharename = servicename;
-
- if (*sharename == '\\') {
-
- server = sharename+2;
- sharename = strchr_m(server,'\\');
-
- if (!sharename)
- return False;
-
- *sharename = 0;
- sharename++;
+ /* Ensure the extrapath doesn't start with a separator. */
+ while (IS_DIRECTORY_SEP(*dir)) {
+ dir++;
}
- directory = dir;
- if ( *directory == '\\' )
- directory++;
-
- pstr_sprintf( path, "\\%s\\%s\\%s", server, sharename, directory );
-
- return True;
+ pstr_sprintf( path_out, "\\%s\\%s\\%s", cli->desthost, cli->share, dir);
}
/********************************************************************
@@ -483,9 +491,11 @@ static BOOL cli_dfs_check_error( struct cli_state *cli, NTSTATUS status )
get the dfs referral link
********************************************************************/
-BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
- CLIENT_DFS_REFERRAL**refs, size_t *num_refs,
- uint16 *consumed)
+BOOL cli_dfs_get_referral( struct cli_state *cli,
+ const char *path,
+ CLIENT_DFS_REFERRAL**refs,
+ size_t *num_refs,
+ uint16 *consumed)
{
unsigned int data_len = 0;
unsigned int param_len = 0;
@@ -529,10 +539,9 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
uint16 ref_size;
int i;
uint16 node_offset;
-
-
+
referrals = SMB_XMALLOC_ARRAY( CLIENT_DFS_REFERRAL, num_referrals );
-
+
/* start at the referrals array */
p = rdata+8;
@@ -554,7 +563,6 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
p += ref_size;
}
-
}
*num_refs = num_referrals;
@@ -566,115 +574,167 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
return True;
}
+
/********************************************************************
********************************************************************/
-BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const char *path,
- struct cli_state **targetcli, pstring targetpath )
+BOOL cli_resolve_path( const char *mountpt,
+ struct cli_state *rootcli,
+ const char *path,
+ struct cli_state **targetcli,
+ pstring targetpath)
{
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs;
uint16 consumed;
struct cli_state *cli_ipc;
- pstring fullpath, cleanpath;
+ pstring dfs_path, cleanpath, extrapath;
int pathlen;
fstring server, share;
struct cli_state *newcli;
pstring newpath;
pstring newmount;
- char *ppath;
+ char *ppath, *temppath = NULL;
SMB_STRUCT_STAT sbuf;
uint32 attributes;
- if ( !rootcli || !path || !targetcli )
+ if ( !rootcli || !path || !targetcli ) {
return False;
+ }
- *targetcli = NULL;
-
- /* send a trans2_query_path_info to check for a referral */
-
- clean_path( cleanpath, path );
- cli_dfs_make_full_path( fullpath, rootcli->desthost, rootcli->share, cleanpath );
+ /* Don't do anything if this is not a DFS root. */
- /* don't bother continuing if this is not a dfs root */
-
- if ( !rootcli->dfsroot || cli_qpathinfo_basic( rootcli, cleanpath, &sbuf, &attributes ) ) {
+ if ( !rootcli->dfsroot) {
*targetcli = rootcli;
pstrcpy( targetpath, path );
return True;
}
- /* special case where client asked for a path that does not exist */
+ *targetcli = NULL;
+
+ /* Send a trans2_query_path_info to check for a referral. */
+
+ clean_path(path, cleanpath);
+ cli_dfs_make_full_path(rootcli, cleanpath, dfs_path );
+
+ if (cli_qpathinfo_basic( rootcli, dfs_path, &sbuf, &attributes ) ) {
+ /* This is an ordinary path, just return it. */
+ *targetcli = rootcli;
+ pstrcpy( targetpath, path );
+ goto done;
+ }
+
+ /* Special case where client asked for a path that does not exist */
if ( cli_dfs_check_error(rootcli, NT_STATUS_OBJECT_NAME_NOT_FOUND) ) {
*targetcli = rootcli;
pstrcpy( targetpath, path );
- return True;
+ goto done;
}
- /* we got an error, check for DFS referral */
-
- if ( !cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED) )
+ /* We got an error, check for DFS referral. */
+
+ if ( !cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED)) {
return False;
+ }
- /* check for the referral */
+ /* Check for the referral. */
- if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) )
+ if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) ) {
return False;
+ }
- if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed)
- || !num_refs )
- {
+ if ( !cli_dfs_get_referral(cli_ipc, dfs_path, &refs, &num_refs, &consumed)
+ || !num_refs ) {
return False;
}
- /* just store the first referral for now
- Make sure to recreate the original string including any wildcards */
+ /* Just store the first referral for now. */
+
+ split_dfs_path( refs[0].dfspath, server, share, extrapath );
+ SAFE_FREE(refs);
+
+ /* Make sure to recreate the original string including any wildcards. */
- cli_dfs_make_full_path( fullpath, rootcli->desthost, rootcli->share, path );
- pathlen = strlen( fullpath )*2;
+ cli_dfs_make_full_path( rootcli, path, dfs_path);
+ pathlen = strlen( dfs_path )*2;
consumed = MIN(pathlen, consumed );
- pstrcpy( targetpath, &fullpath[consumed/2] );
+ pstrcpy( targetpath, &dfs_path[consumed/2] );
+ dfs_path[consumed/2] = '\0';
- split_dfs_path( refs[0].dfspath, server, share );
- SAFE_FREE( refs );
-
- /* open the connection to the target path */
+ /*
+ * targetpath is now the unconsumed part of the path.
+ * dfs_path is now the consumed part of the path (in \server\share\path format).
+ */
+
+ /* Open the connection to the target server & share */
if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) {
- d_printf("Unable to follow dfs referral [//%s/%s]\n",
+ d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
server, share );
-
return False;
}
+ if (strlen(extrapath) > 0) {
+ string_append(&temppath, extrapath);
+ string_append(&temppath, targetpath);
+ pstrcpy( targetpath, temppath );
+ }
+
/* parse out the consumed mount path */
/* trim off the \server\share\ */
- fullpath[consumed/2] = '\0';
- dos_clean_name( fullpath );
- if ((ppath = strchr_m( fullpath, '\\' )) == NULL)
+ ppath = dfs_path;
+
+ if (*ppath != '\\') {
+ d_printf("cli_resolve_path: dfs_path (%s) not in correct format.\n",
+ dfs_path );
return False;
- if ((ppath = strchr_m( ppath+1, '\\' )) == NULL)
+ }
+
+ ppath++; /* Now pointing at start of server name. */
+
+ if ((ppath = strchr_m( dfs_path, '\\' )) == NULL) {
return False;
- if ((ppath = strchr_m( ppath+1, '\\' )) == NULL)
+ }
+
+ ppath++; /* Now pointing at start of share name. */
+
+ if ((ppath = strchr_m( ppath+1, '\\' )) == NULL) {
return False;
- ppath++;
-
+ }
+
+ ppath++; /* Now pointing at path component. */
+
pstr_sprintf( newmount, "%s\\%s", mountpt, ppath );
+
cli_cm_set_mntpoint( *targetcli, newmount );
- /* check for another dfs referral, note that we are not
- checking for loops here */
+ /* Check for another dfs referral, note that we are not
+ checking for loops here. */
- if ( !strequal( targetpath, "\\" ) ) {
+ if ( !strequal( targetpath, "\\" ) && !strequal( targetpath, "/")) {
if ( cli_resolve_path( newmount, *targetcli, targetpath, &newcli, newpath ) ) {
+ /*
+ * When cli_resolve_path returns true here it's always
+ * returning the complete path in newpath, so we're done
+ * here.
+ */
*targetcli = newcli;
pstrcpy( targetpath, newpath );
+ return True;
}
}
+ done:
+
+ /* If returning True ensure we return a dfs root full path. */
+ if ( (*targetcli)->dfsroot ) {
+ pstrcpy(dfs_path, targetpath );
+ cli_dfs_make_full_path( *targetcli, dfs_path, targetpath);
+ }
+
return True;
}
@@ -690,6 +750,7 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
pstring fullpath;
BOOL res;
uint16 cnum;
+ pstring newextrapath;
if ( !cli || !sharename )
return False;
@@ -698,8 +759,9 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
/* special case. never check for a referral on the IPC$ share */
- if ( strequal( sharename, "IPC$" ) )
+ if ( strequal( sharename, "IPC$" ) ) {
return False;
+ }
/* send a trans2_query_path_info to check for a referral */
@@ -719,13 +781,13 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
}
cli->cnum = cnum;
-
+
if (!res || !num_refs ) {
SAFE_FREE( refs );
return False;
}
- split_dfs_path( refs[0].dfspath, newserver, newshare );
+ split_dfs_path( refs[0].dfspath, newserver, newshare, newextrapath );
/* check that this is not a self-referral */
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index 2fe9eb17259..ce2081a81e1 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -1775,3 +1775,200 @@ BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
}
+
+/****************************************************************************
+ Convert open "flags" arg to uint32 on wire.
+****************************************************************************/
+
+static uint32 open_flags_to_wire(int flags)
+{
+ int open_mode = flags & O_ACCMODE;
+ uint32 ret = 0;
+
+ switch (open_mode) {
+ case O_WRONLY:
+ ret |= SMB_O_WRONLY;
+ break;
+ case O_RDWR:
+ ret |= SMB_O_RDWR;
+ break;
+ default:
+ case O_RDONLY:
+ ret |= SMB_O_RDONLY;
+ break;
+ }
+
+ if (flags & O_CREAT) {
+ ret |= SMB_O_CREAT;
+ }
+ if (flags & O_EXCL) {
+ ret |= SMB_O_EXCL;
+ }
+ if (flags & O_TRUNC) {
+ ret |= SMB_O_TRUNC;
+ }
+#if defined(O_SYNC)
+ if (flags & O_SYNC) {
+ ret |= SMB_O_SYNC;
+ }
+#endif /* O_SYNC */
+ if (flags & O_APPEND) {
+ ret |= SMB_O_APPEND;
+ }
+#if defined(O_DIRECT)
+ if (flags & O_DIRECT) {
+ ret |= SMB_O_DIRECT;
+ }
+#endif
+#if defined(O_DIRECTORY)
+ if (flags & O_DIRECTORY) {
+ ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+ ret |= SMB_O_DIRECTORY;
+ }
+#endif
+ return ret;
+}
+
+/****************************************************************************
+ Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
+****************************************************************************/
+
+static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, BOOL is_dir)
+{
+ unsigned int data_len = 0;
+ unsigned int param_len = 0;
+ uint16 setup = TRANSACT2_SETPATHINFO;
+ char param[sizeof(pstring)+6];
+ char data[18];
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ int fnum = -1;
+ uint32 wire_flags = open_flags_to_wire(flags);
+
+ memset(param, 0, sizeof(param));
+ SSVAL(param,0, SMB_POSIX_PATH_OPEN);
+ p = &param[6];
+
+ p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ if (is_dir) {
+ wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+ wire_flags |= SMB_O_DIRECTORY;
+ }
+
+ p = data;
+ SIVAL(p,0,0); /* No oplock. */
+ SIVAL(p,4,wire_flags);
+ SIVAL(p,8,unix_perms_to_wire(mode));
+ SIVAL(p,12,0); /* Top bits of perms currently undefined. */
+ SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
+
+ data_len = 18;
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 2, /* param, length, max */
+ (char *)&data, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ return -1;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ return -1;
+ }
+
+ fnum = SVAL(rdata,2);
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return fnum;
+}
+
+/****************************************************************************
+ open - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
+{
+ return cli_posix_open_internal(cli, fname, flags, mode, False);
+}
+
+/****************************************************************************
+ mkdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
+{
+ return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
+}
+
+/****************************************************************************
+ unlink or rmdir - POSIX semantics.
+****************************************************************************/
+
+static BOOL cli_posix_unlink_internal(struct cli_state *cli, const char *fname, BOOL is_dir)
+{
+ unsigned int data_len = 0;
+ unsigned int param_len = 0;
+ uint16 setup = TRANSACT2_SETPATHINFO;
+ char param[sizeof(pstring)+6];
+ char data[2];
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+
+ memset(param, 0, sizeof(param));
+ SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
+ p = &param[6];
+
+ p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
+ SMB_POSIX_UNLINK_FILE_TARGET);
+ data_len = 2;
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 2, /* param, length, max */
+ (char *)&data, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ return False;
+ }
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return True;
+}
+
+/****************************************************************************
+ unlink - POSIX semantics.
+****************************************************************************/
+
+BOOL cli_posix_unlink(struct cli_state *cli, const char *fname)
+{
+ return cli_posix_unlink_internal(cli, fname, False);
+}
+
+/****************************************************************************
+ rmdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_rmdir(struct cli_state *cli, const char *fname)
+{
+ return cli_posix_unlink_internal(cli, fname, True);
+}
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index f06a19b345c..5018e146cad 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -75,6 +75,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
krb5_error_code ret;
char *utf8_name;
+ *principal = NULL;
if (push_utf8_allocate(&utf8_name, name) == (size_t)-1) {
return ENOMEM;
}
@@ -97,6 +98,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
krb5_error_code ret;
char *utf8_name;
+ *unix_name = NULL;
ret = krb5_unparse_name(context, principal, &utf8_name);
if (ret) {
return ret;
@@ -1415,6 +1417,43 @@ done:
}
#endif
+ krb5_error_code smb_krb5_mk_error(krb5_context context,
+ krb5_error_code error_code,
+ const krb5_principal server,
+ krb5_data *reply)
+{
+#ifdef HAVE_SHORT_KRB5_MK_ERROR_INTERFACE /* MIT */
+ /*
+ * The MIT interface is *terrible*.
+ * We have to construct this ourselves...
+ */
+ krb5_error e;
+
+ memset(&e, 0, sizeof(e));
+ krb5_us_timeofday(context, &e.stime, &e.susec);
+ e.server = server;
+#if defined(krb5_err_base)
+ e.error = error_code - krb5_err_base;
+#elif defined(ERROR_TABLE_BASE_krb5)
+ e.error = error_code - ERROR_TABLE_BASE_krb5;
+#else
+ e.error = error_code; /* Almost certainly wrong, but what can we do... ? */
+#endif
+
+ return krb5_mk_error(context, &e, reply);
+#else /* Heimdal. */
+ return krb5_mk_error(context,
+ error_code,
+ NULL,
+ NULL, /* e_data */
+ NULL,
+ server,
+ NULL,
+ NULL,
+ reply);
+#endif
+}
+
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 22cb5930c26..3e76cd47754 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -44,6 +44,7 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
*p_resume_key = 0;
}
memcpy(finfo,&def_finfo,sizeof(*finfo));
+ finfo->cli = cli;
switch (level) {
case 1: /* OS/2 understands this */
@@ -185,13 +186,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
/* NT uses 260, OS/2 uses 2. Both accept 1. */
info_level = (cli->capabilities&CAP_NT_SMBS)?260:1;
- /* when getting a directory listing from a 2k dfs root share,
- we have to include the full path (\server\share\mask) here */
-
- if ( cli->dfsroot )
- pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
- else
- pstrcpy(mask,Mask);
+ pstrcpy(mask,Mask);
while (ff_eos == 0) {
loop_count++;
@@ -377,6 +372,7 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
*finfo = def_finfo;
+ finfo->cli = cli;
finfo->mode = CVAL(p,21);
/* this date is converted to GMT by make_unix_date */
diff --git a/source/libsmb/cliquota.c b/source/libsmb/cliquota.c
index 25c36c214fc..5627d28bb5d 100644
--- a/source/libsmb/cliquota.c
+++ b/source/libsmb/cliquota.c
@@ -323,11 +323,13 @@ BOOL cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST
if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
DEBUG(0,("talloc_zero() failed\n"));
+ talloc_destroy(mem_ctx);
return (-1);
}
if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
DEBUG(0,("talloc_zero() failed\n"));
+ talloc_destroy(mem_ctx);
return (-1);
}
diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c
index 61cdd79f36b..05dc36e91c3 100644
--- a/source/libsmb/clirap.c
+++ b/source/libsmb/clirap.c
@@ -21,10 +21,10 @@
#include "includes.h"
-
/****************************************************************************
-Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
+ Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
****************************************************************************/
+
BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
uint16 *setup, uint32 setup_count, uint32 max_setup_count,
char *params, uint32 param_count, uint32 max_param_count,
@@ -32,28 +32,29 @@ BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
char **rparam, uint32 *rparam_count,
char **rdata, uint32 *rdata_count)
{
- cli_send_trans(cli, SMBtrans,
+ cli_send_trans(cli, SMBtrans,
pipe_name,
0,0, /* fid, flags */
setup, setup_count, max_setup_count,
params, param_count, max_param_count,
data, data_count, max_data_count);
- return (cli_receive_trans(cli, SMBtrans,
+ return (cli_receive_trans(cli, SMBtrans,
rparam, (unsigned int *)rparam_count,
rdata, (unsigned int *)rdata_count));
}
/****************************************************************************
-call a remote api
+ Call a remote api
****************************************************************************/
+
BOOL cli_api(struct cli_state *cli,
char *param, int prcnt, int mprcnt,
char *data, int drcnt, int mdrcnt,
char **rparam, unsigned int *rprcnt,
char **rdata, unsigned int *rdrcnt)
{
- cli_send_trans(cli,SMBtrans,
+ cli_send_trans(cli,SMBtrans,
PIPE_LANMAN, /* Name */
0,0, /* fid, flags */
NULL,0,0, /* Setup, length, max */
@@ -61,15 +62,15 @@ BOOL cli_api(struct cli_state *cli,
data, drcnt, mdrcnt /* Data, length, max */
);
- return (cli_receive_trans(cli,SMBtrans,
+ return (cli_receive_trans(cli,SMBtrans,
rparam, rprcnt,
rdata, rdrcnt));
}
-
/****************************************************************************
-perform a NetWkstaUserLogon
+ Perform a NetWkstaUserLogon.
****************************************************************************/
+
BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
{
char *rparam = NULL;
@@ -129,8 +130,9 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
}
/****************************************************************************
-call a NetShareEnum - try and browse available connections on a host
+ Call a NetShareEnum - try and browse available connections on a host.
****************************************************************************/
+
int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
{
char *rparam = NULL;
@@ -196,14 +198,14 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co
return count;
}
-
/****************************************************************************
-call a NetServerEnum for the specified workgroup and servertype mask. This
-function then calls the specified callback function for each name returned.
+ Call a NetServerEnum for the specified workgroup and servertype mask. This
+ function then calls the specified callback function for each name returned.
-The callback function takes 4 arguments: the machine name, the server type,
-the comment and a state pointer.
+ The callback function takes 4 arguments: the machine name, the server type,
+ the comment and a state pointer.
****************************************************************************/
+
BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
void (*fn)(const char *, uint32, const char *, void *),
void *state)
@@ -286,99 +288,99 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
return(count > 0);
}
-
-
/****************************************************************************
-Send a SamOEMChangePassword command
+ Send a SamOEMChangePassword command.
****************************************************************************/
+
BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
const char *old_password)
{
- pstring param;
- unsigned char data[532];
- char *p = param;
- unsigned char old_pw_hash[16];
- unsigned char new_pw_hash[16];
- unsigned int data_len;
- unsigned int param_len = 0;
- char *rparam = NULL;
- char *rdata = NULL;
- unsigned int rprcnt, rdrcnt;
-
- if (strlen(user) >= sizeof(fstring)-1) {
- DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
- return False;
- }
-
- SSVAL(p,0,214); /* SamOEMChangePassword command. */
- p += 2;
- pstrcpy_base(p, "zsT", param);
- p = skip_string(p,1);
- pstrcpy_base(p, "B516B16", param);
- p = skip_string(p,1);
- pstrcpy_base(p,user, param);
- p = skip_string(p,1);
- SSVAL(p,0,532);
- p += 2;
-
- param_len = PTR_DIFF(p,param);
-
- /*
- * Get the Lanman hash of the old password, we
- * use this as the key to make_oem_passwd_hash().
- */
- E_deshash(old_password, old_pw_hash);
-
- encode_pw_buffer(data, new_password, STR_ASCII);
+ pstring param;
+ unsigned char data[532];
+ char *p = param;
+ unsigned char old_pw_hash[16];
+ unsigned char new_pw_hash[16];
+ unsigned int data_len;
+ unsigned int param_len = 0;
+ char *rparam = NULL;
+ char *rdata = NULL;
+ unsigned int rprcnt, rdrcnt;
+
+ if (strlen(user) >= sizeof(fstring)-1) {
+ DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
+ return False;
+ }
+
+ SSVAL(p,0,214); /* SamOEMChangePassword command. */
+ p += 2;
+ pstrcpy_base(p, "zsT", param);
+ p = skip_string(p,1);
+ pstrcpy_base(p, "B516B16", param);
+ p = skip_string(p,1);
+ pstrcpy_base(p,user, param);
+ p = skip_string(p,1);
+ SSVAL(p,0,532);
+ p += 2;
+
+ param_len = PTR_DIFF(p,param);
+
+ /*
+ * Get the Lanman hash of the old password, we
+ * use this as the key to make_oem_passwd_hash().
+ */
+ E_deshash(old_password, old_pw_hash);
+
+ encode_pw_buffer(data, new_password, STR_ASCII);
#ifdef DEBUG_PASSWORD
- DEBUG(100,("make_oem_passwd_hash\n"));
- dump_data(100, (char *)data, 516);
+ DEBUG(100,("make_oem_passwd_hash\n"));
+ dump_data(100, (char *)data, 516);
#endif
- SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
+ SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
- /*
- * Now place the old password hash in the data.
- */
- E_deshash(new_password, new_pw_hash);
+ /*
+ * Now place the old password hash in the data.
+ */
+ E_deshash(new_password, new_pw_hash);
- E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
+ E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
- data_len = 532;
+ data_len = 532;
- if (cli_send_trans(cli,SMBtrans,
+ if (cli_send_trans(cli,SMBtrans,
PIPE_LANMAN, /* name */
0,0, /* fid, flags */
NULL,0,0, /* setup, length, max */
param,param_len,2, /* param, length, max */
(char *)data,data_len,0 /* data, length, max */
) == False) {
- DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
- user ));
- return False;
- }
+ DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
+ user ));
+ return False;
+ }
- if (!cli_receive_trans(cli,SMBtrans,
+ if (!cli_receive_trans(cli,SMBtrans,
&rparam, &rprcnt,
&rdata, &rdrcnt)) {
- DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
- user ));
- return False;
- }
+ DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
+ user ));
+ return False;
+ }
- if (rparam)
- cli->rap_error = SVAL(rparam,0);
+ if (rparam) {
+ cli->rap_error = SVAL(rparam,0);
+ }
- SAFE_FREE(rparam);
- SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
- return (cli->rap_error == 0);
+ return (cli->rap_error == 0);
}
-
/****************************************************************************
-send a qpathinfo call
+ Send a qpathinfo call.
****************************************************************************/
+
BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
time_t *change_time,
time_t *access_time,
@@ -458,10 +460,10 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
return True;
}
-
/****************************************************************************
-send a setpathinfo call
+ Send a setpathinfo call.
****************************************************************************/
+
BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
time_t create_time,
time_t access_time,
@@ -556,9 +558,8 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
return True;
}
-
/****************************************************************************
-send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
+ Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
****************************************************************************/
BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
@@ -631,10 +632,10 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
return True;
}
-
/****************************************************************************
-send a qfileinfo QUERY_FILE_NAME_INFO call
+ Send a qfileinfo QUERY_FILE_NAME_INFO call.
****************************************************************************/
+
BOOL cli_qfilename(struct cli_state *cli, int fnum,
pstring name)
{
@@ -674,10 +675,10 @@ BOOL cli_qfilename(struct cli_state *cli, int fnum,
return True;
}
-
/****************************************************************************
-send a qfileinfo call
+ Send a qfileinfo call.
****************************************************************************/
+
BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
uint16 *mode, SMB_OFF_T *size,
struct timespec *create_time,
@@ -749,10 +750,10 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
return True;
}
-
/****************************************************************************
-send a qpathinfo BASIC_INFO call
+ Send a qpathinfo BASIC_INFO call.
****************************************************************************/
+
BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
SMB_STRUCT_STAT *sbuf, uint32 *attributes )
{
@@ -765,18 +766,12 @@ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
pstring path;
int len;
- /* send full paths to dfs root shares */
-
- if ( cli->dfsroot )
- pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name );
- else
- pstrcpy( path, name );
-
+ pstrcpy( path, name );
/* cleanup */
len = strlen( path );
- if ( path[len] == '\\' )
- path[len] = '\0';
+ if ( path[len-1] == '\\' || path[len-1] == '/')
+ path[len-1] = '\0';
p = param;
memset(p, 0, 6);
@@ -820,7 +815,7 @@ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
}
/****************************************************************************
-send a qfileinfo call
+ Send a qfileinfo call.
****************************************************************************/
BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
@@ -875,11 +870,10 @@ BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutd
return True;
}
-
-
/****************************************************************************
-send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
+ Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
****************************************************************************/
+
NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
{
unsigned int data_len = 0;
diff --git a/source/libsmb/doserr.c b/source/libsmb/doserr.c
index 8628db3abc9..414c2d49168 100644
--- a/source/libsmb/doserr.c
+++ b/source/libsmb/doserr.c
@@ -68,6 +68,7 @@ werror_code_struct dos_errs[] =
{ "WERR_DFS_CANT_CREATE_JUNCT", WERR_DFS_CANT_CREATE_JUNCT },
{ "WERR_MACHINE_LOCKED", WERR_MACHINE_LOCKED },
{ "WERR_NO_LOGON_SERVERS", WERR_NO_LOGON_SERVERS },
+ { "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
{ "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
{ "WERR_INVALID_SECURITY_DESCRIPTOR", WERR_INVALID_SECURITY_DESCRIPTOR },
{ "WERR_INVALID_OWNER", WERR_INVALID_OWNER },
@@ -83,8 +84,9 @@ werror_code_struct dos_errs[] =
};
/*****************************************************************************
- returns a DOS error message. not amazingly helpful, but better than a number.
+ Returns a DOS error message. not amazingly helpful, but better than a number.
*****************************************************************************/
+
const char *dos_errstr(WERROR werror)
{
static pstring msg;
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index 6745c0e23a3..cb5e8311cad 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -1511,7 +1511,6 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
{ EACCES, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
{ ENOENT, ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND },
{ ENOTDIR, ERRDOS, ERRbadpath, NT_STATUS_NOT_A_DIRECTORY },
- { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
{ EIO, ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
{ EBADF, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
{ EINVAL, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
@@ -1534,6 +1533,9 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
#ifdef EROFS
{ EROFS, ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
#endif
+#ifdef ENAMETOOLONG
+ { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
+#endif
#ifdef EFBIG
{ EFBIG, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
#endif
diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index 6a154aa68e2..7fbf5a10c54 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/libsmb/libsmbclient.c
@@ -1116,13 +1116,6 @@ smbc_open_ctx(SMBCCTX *context,
}
/*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
- if ( targetcli->dfsroot )
- {
- pstring temppath;
- pstrcpy(temppath, targetpath);
- cli_dfs_make_full_path( targetpath, targetcli->desthost, targetcli->share, temppath);
- }
-
if ((fd = cli_open(targetcli, targetpath, flags,
context->internal->_share_mode)) < 0) {
@@ -1519,14 +1512,6 @@ smbc_getatr(SMBCCTX * context,
return False;
}
- if ( targetcli->dfsroot )
- {
- pstring temppath;
- pstrcpy(temppath, targetpath);
- cli_dfs_make_full_path(targetpath, targetcli->desthost,
- targetcli->share, temppath);
- }
-
if (!srv->no_pathinfo2 &&
cli_qpathinfo2(targetcli, targetpath,
create_time_ts,
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index 872ed2bbeaf..76a4039d823 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -273,6 +273,9 @@ void brl_init(int read_only)
lock_path("brlock.tdb")));
return;
}
+
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
}
/****************************************************************************
diff --git a/source/locking/locking.c b/source/locking/locking.c
index ffac43aff59..37e6dbc4e54 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -222,6 +222,12 @@ struct byte_range_lock *do_lock(files_struct *fsp,
lock_flav,
blocking_lock);
+ /* blocking ie. pending, locks also count here,
+ * as this is an efficiency counter to avoid checking
+ * the lock db. on close. JRA. */
+
+ fsp->current_lock_count++;
+
return br_lck;
}
@@ -268,6 +274,9 @@ NTSTATUS do_unlock(files_struct *fsp,
return NT_STATUS_RANGE_NOT_LOCKED;
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
@@ -315,6 +324,9 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
@@ -330,6 +342,14 @@ void locking_close_file(files_struct *fsp)
return;
}
+ /* If we have not outstanding locks or pending
+ * locks then we don't need to look in the lock db.
+ */
+
+ if (fsp->current_lock_count == 0) {
+ return;
+ }
+
br_lck = brl_get_locks(NULL,fsp);
if (br_lck) {
@@ -363,6 +383,9 @@ BOOL locking_init(int read_only)
return False;
}
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
+
if (!posix_locking_init(read_only))
return False;
@@ -858,15 +881,29 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
return True;
}
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+static int pull_delete_on_close_flag(TDB_DATA key, TDB_DATA dbuf,
+ void *private_data)
{
- BOOL result;
- struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL);
- if (!lck) {
- return False;
+ BOOL *result = (BOOL *)private_data;
+ struct locking_data *data;
+
+ if (dbuf.dsize < sizeof(struct locking_data)) {
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
- result = lck->delete_on_close;
- TALLOC_FREE(lck);
+
+ data = (struct locking_data *)dbuf.dptr;
+
+ *result = data->u.s.delete_on_close;
+ return 0;
+}
+
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+{
+ TDB_DATA key = locking_key(dev, inode);
+ BOOL result = False;
+
+ tdb_parse_record(tdb, key, pull_delete_on_close_flag,
+ (void *)&result);
return result;
}
diff --git a/source/modules/nfs4_acls.c b/source/modules/nfs4_acls.c
index 91ebba1f588..dd452408579 100644
--- a/source/modules/nfs4_acls.c
+++ b/source/modules/nfs4_acls.c
@@ -604,31 +604,33 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp,
if (smbacl4_GetFileOwner(fsp, &sbuf))
return False;
- /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
- if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd))
- {
- DEBUG(8, ("unpack_nt_owners failed"));
- return False;
- }
- if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
- ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
- need_chown = True;
- }
- if (need_chown) {
- if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
- if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
- DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
- fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
- return False;
+ if (params.do_chown) {
+ /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
+ if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd))
+ {
+ DEBUG(8, ("unpack_nt_owners failed"));
+ return False;
+ }
+ if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
+ ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
+ need_chown = True;
+ }
+ if (need_chown) {
+ if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
+ if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+ DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
+ return False;
+ }
+ DEBUG(10,("chown %s, %u, %u succeeded.\n",
+ fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+ if (smbacl4_GetFileOwner(fsp, &sbuf))
+ return False;
+ need_chown = False;
+ } else { /* chown is needed, but _after_ changing acl */
+ sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
+ sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
}
- DEBUG(10,("chown %s, %u, %u succeeded.\n",
- fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
- if (smbacl4_GetFileOwner(fsp, &sbuf))
- return False;
- need_chown = False;
- } else { /* chown is needed, but _after_ changing acl */
- sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
- sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
}
}
diff --git a/source/modules/vfs_cap.c b/source/modules/vfs_cap.c
index e058c9660c7..f89e149d0eb 100644
--- a/source/modules/vfs_cap.c
+++ b/source/modules/vfs_cap.c
@@ -131,11 +131,11 @@ static int cap_chdir(vfs_handle_struct *handle, const char *path)
return SMB_VFS_NEXT_CHDIR(handle, cappath);
}
-static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+static int cap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
{
pstring cappath;
capencode(cappath, path);
- return SMB_VFS_NEXT_UTIME(handle, cappath, times);
+ return SMB_VFS_NEXT_NTIMES(handle, cappath, ts);
}
@@ -327,7 +327,7 @@ static vfs_op_tuple cap_op_tuples[] = {
{SMB_VFS_OP(cap_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(cap_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(cap_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(cap_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(cap_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(cap_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(cap_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(cap_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
diff --git a/source/modules/vfs_catia.c b/source/modules/vfs_catia.c
index 478dab6cbed..fe1ce830f7b 100644
--- a/source/modules/vfs_catia.c
+++ b/source/modules/vfs_catia.c
@@ -184,10 +184,10 @@ static char *catia_getwd(vfs_handle_struct *handle, char *buf)
return SMB_VFS_NEXT_GETWD(handle, buf);
}
-static int catia_utime(vfs_handle_struct *handle,
- const char *path, struct utimbuf *times)
+static int catia_ntimes(vfs_handle_struct *handle,
+ const char *path, const struct timespec ts[2])
{
- return SMB_VFS_NEXT_UTIME(handle, path, times);
+ return SMB_VFS_NEXT_NTIMES(handle, path, ts);
}
static BOOL catia_symlink(vfs_handle_struct *handle,
@@ -278,7 +278,7 @@ SMB_VFS_LAYER_TRANSPARENT},
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(catia_getwd), SMB_VFS_OP_GETWD,
SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(catia_utime), SMB_VFS_OP_UTIME,
+ {SMB_VFS_OP(catia_ntimes), SMB_VFS_OP_NTIMES,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(catia_symlink), SMB_VFS_OP_SYMLINK,
SMB_VFS_LAYER_TRANSPARENT},
diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c
index bd7bea5258a..4febc064d94 100644
--- a/source/modules/vfs_default.c
+++ b/source/modules/vfs_default.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
Wrap disk only vfs functions to sidestep dodgy compilers.
Copyright (C) Tim Potter 1998
+ Copyright (C) Jeremy Allison 2007
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
@@ -612,13 +613,35 @@ static char *vfswrap_getwd(vfs_handle_struct *handle, char *path)
return result;
}
-static int vfswrap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+/*********************************************************************
+ nsec timestamp resolution call. Convert down to whatever the underlying
+ system will support.
+**********************************************************************/
+
+static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
{
int result;
- START_PROFILE(syscall_utime);
- result = utime(path, times);
- END_PROFILE(syscall_utime);
+ START_PROFILE(syscall_ntimes);
+#if defined(HAVE_UTIMES)
+ {
+ struct timeval tv[2];
+ tv[0] = convert_timespec_to_timeval(ts[0]);
+ tv[1] = convert_timespec_to_timeval(ts[1]);
+ result = utimes(path, tv);
+ }
+#elif defined(HAVE_UTIME)
+ {
+ struct utimebuf times;
+ times.actime = convert_timespec_to_time_t(ts[0]);
+ times.modtime = convert_timespec_to_time_t(ts[1]);
+ result = utime(path, times);
+ }
+#else
+ errno = ENOSYS;
+ result = -1;
+#endif
+ END_PROFILE(syscall_ntimes);
return result;
}
@@ -786,7 +809,7 @@ static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd
static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, int fd,
int leasetype)
{
- int result;
+ int result = -1;
START_PROFILE(syscall_linux_setlease);
@@ -796,7 +819,8 @@ static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
return -1;
result = linux_setlease(fd, leasetype);
-
+#else
+ errno = ENOSYS;
#endif
END_PROFILE(syscall_linux_setlease);
return result;
@@ -879,6 +903,12 @@ static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
return NT_STATUS_OK;
}
+static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
{
size_t result;
@@ -1238,7 +1268,7 @@ static vfs_op_tuple vfs_default_ops[] = {
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(vfswrap_getwd), SMB_VFS_OP_GETWD,
SMB_VFS_LAYER_OPAQUE},
- {SMB_VFS_OP(vfswrap_utime), SMB_VFS_OP_UTIME,
+ {SMB_VFS_OP(vfswrap_ntimes), SMB_VFS_OP_NTIMES,
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
SMB_VFS_LAYER_OPAQUE},
@@ -1262,6 +1292,8 @@ static vfs_op_tuple vfs_default_ops[] = {
SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(vfswrap_notify_watch), SMB_VFS_OP_NOTIFY_WATCH,
SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(vfswrap_chflags), SMB_VFS_OP_CHFLAGS,
+ SMB_VFS_LAYER_OPAQUE},
/* NT ACL operations. */
diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c
index 6036e49fc15..62530fb09ce 100644
--- a/source/modules/vfs_full_audit.c
+++ b/source/modules/vfs_full_audit.c
@@ -151,8 +151,8 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle,
const char *path);
static char *smb_full_audit_getwd(vfs_handle_struct *handle,
char *path);
-static int smb_full_audit_utime(vfs_handle_struct *handle,
- const char *path, struct utimbuf *times);
+static int smb_full_audit_ntimes(vfs_handle_struct *handle,
+ const char *path, const struct timespec ts[2]);
static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
int fd, SMB_OFF_T len);
static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int fd,
@@ -174,6 +174,15 @@ static int smb_full_audit_mknod(vfs_handle_struct *handle,
const char *pathname, mode_t mode, SMB_DEV_T dev);
static char *smb_full_audit_realpath(vfs_handle_struct *handle,
const char *path, char *resolved_path);
+static NTSTATUS smb_full_audit_notify_watch(struct vfs_handle_struct *handle,
+ struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data, void *handle_p);
+static int smb_full_audit_chflags(vfs_handle_struct *handle,
+ const char *path, uint flags);
static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
int fd, uint32 security_info,
SEC_DESC **ppdesc);
@@ -375,7 +384,7 @@ static vfs_op_tuple audit_op_tuples[] = {
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_getwd), SMB_VFS_OP_GETWD,
SMB_VFS_LAYER_LOGGER},
- {SMB_VFS_OP(smb_full_audit_utime), SMB_VFS_OP_UTIME,
+ {SMB_VFS_OP(smb_full_audit_ntimes), SMB_VFS_OP_NTIMES,
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_ftruncate), SMB_VFS_OP_FTRUNCATE,
SMB_VFS_LAYER_LOGGER},
@@ -397,6 +406,10 @@ static vfs_op_tuple audit_op_tuples[] = {
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_realpath), SMB_VFS_OP_REALPATH,
SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_notify_watch),SMB_VFS_OP_NOTIFY_WATCH,
+ SMB_VFS_LAYER_LOGGER},
+ {SMB_VFS_OP(smb_full_audit_chflags), SMB_VFS_OP_CHFLAGS,
+ SMB_VFS_LAYER_LOGGER},
/* NT ACL operations. */
@@ -549,7 +562,7 @@ static struct {
{ SMB_VFS_OP_FCHOWN, "fchown" },
{ SMB_VFS_OP_CHDIR, "chdir" },
{ SMB_VFS_OP_GETWD, "getwd" },
- { SMB_VFS_OP_UTIME, "utime" },
+ { SMB_VFS_OP_NTIMES, "ntimes" },
{ SMB_VFS_OP_FTRUNCATE, "ftruncate" },
{ SMB_VFS_OP_LOCK, "lock" },
{ SMB_VFS_OP_KERNEL_FLOCK, "kernel_flock" },
@@ -560,6 +573,8 @@ static struct {
{ SMB_VFS_OP_LINK, "link" },
{ SMB_VFS_OP_MKNOD, "mknod" },
{ SMB_VFS_OP_REALPATH, "realpath" },
+ { SMB_VFS_OP_NOTIFY_WATCH, "notify_watch" },
+ { SMB_VFS_OP_CHFLAGS, "chflags" },
{ SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" },
{ SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" },
{ SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" },
@@ -1267,14 +1282,14 @@ static char *smb_full_audit_getwd(vfs_handle_struct *handle,
return result;
}
-static int smb_full_audit_utime(vfs_handle_struct *handle,
- const char *path, struct utimbuf *times)
+static int smb_full_audit_ntimes(vfs_handle_struct *handle,
+ const char *path, const struct timespec ts[2])
{
int result;
- result = SMB_VFS_NEXT_UTIME(handle, path, times);
+ result = SMB_VFS_NEXT_NTIMES(handle, path, ts);
- do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path);
+ do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", path);
return result;
}
@@ -1405,6 +1420,35 @@ static char *smb_full_audit_realpath(vfs_handle_struct *handle,
return result;
}
+static NTSTATUS smb_full_audit_notify_watch(struct vfs_handle_struct *handle,
+ struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data, void *handle_p)
+{
+ NTSTATUS result;
+
+ result = SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, e, callback, private_data, handle_p);
+
+ do_log(SMB_VFS_OP_NOTIFY_WATCH, NT_STATUS_IS_OK(result), handle, "");
+
+ return result;
+}
+
+static int smb_full_audit_chflags(vfs_handle_struct *handle,
+ const char *path, uint flags)
+{
+ int result;
+
+ result = SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
+
+ do_log(SMB_VFS_OP_CHFLAGS, (result != 0), handle, "%s", path);
+
+ return result;
+}
+
static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
int fd, uint32 security_info,
SEC_DESC **ppdesc)
diff --git a/source/modules/vfs_netatalk.c b/source/modules/vfs_netatalk.c
index 7176919a7dc..efcc9816794 100644
--- a/source/modules/vfs_netatalk.c
+++ b/source/modules/vfs_netatalk.c
@@ -241,7 +241,7 @@ static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, c
if (atalk_build_paths(ctx, handle->conn->origpath, oldname, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
- return ret;
+ goto exit_rename;
if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) {
DEBUG(3, ("ATALK: %s has passed..\n", adbl_path));
@@ -297,7 +297,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, const char *path)
if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
- return ret;
+ goto exit_unlink;
if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) {
DEBUG(3, ("ATALK: %s has passed..\n", adbl_path));
@@ -329,7 +329,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_
if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
- return ret;
+ goto exit_chmod;
if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) {
DEBUG(3, ("ATALK: %s has passed..\n", orig_path));
@@ -361,7 +361,7 @@ static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t
if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
- return ret;
+ goto exit_chown;
if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) {
DEBUG(3, ("ATALK: %s has passed..\n", orig_path));
diff --git a/source/modules/vfs_recycle.c b/source/modules/vfs_recycle.c
index 121454315fb..579cc94cf94 100644
--- a/source/modules/vfs_recycle.c
+++ b/source/modules/vfs_recycle.c
@@ -153,17 +153,30 @@ static const char **recycle_noversions(vfs_handle_struct *handle)
return tmp_lp;
}
-static int recycle_maxsize(vfs_handle_struct *handle)
+static SMB_OFF_T recycle_maxsize(vfs_handle_struct *handle)
{
- int maxsize;
+ SMB_OFF_T maxsize;
- maxsize = lp_parm_int(SNUM(handle->conn), "recycle", "maxsize", -1);
+ maxsize = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+ "recycle", "maxsize", NULL));
- DEBUG(10, ("recycle: maxsize = %d\n", maxsize));
+ DEBUG(10, ("recycle: maxsize = %lu\n", (long unsigned int)maxsize));
return maxsize;
}
+static SMB_OFF_T recycle_minsize(vfs_handle_struct *handle)
+{
+ SMB_OFF_T minsize;
+
+ minsize = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+ "recycle", "minsize", NULL));
+
+ DEBUG(10, ("recycle: minsize = %lu\n", (long unsigned int)minsize));
+
+ return minsize;
+}
+
static mode_t recycle_directory_mode(vfs_handle_struct *handle)
{
int dirmode;
@@ -351,18 +364,16 @@ static BOOL matchparam(const char **haystack_list, const char *needle)
static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL touch_mtime)
{
SMB_STRUCT_STAT st;
- struct utimbuf tb;
- time_t currtime;
+ struct timespec ts[2];
if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
return;
}
- currtime = time(&currtime);
- tb.actime = currtime;
- tb.modtime = touch_mtime ? currtime : st.st_mtime;
+ ts[0] = timespec_current(); /* atime */
+ ts[1] = touch_mtime ? ts[0] : get_mtimespec(&st); /* mtime */
- if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) {
+ if (SMB_VFS_NEXT_NTIMES(handle, fname, ts) == -1 ) {
DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
}
}
@@ -381,7 +392,7 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
const char *base;
char *repository = NULL;
int i = 1;
- int maxsize;
+ SMB_OFF_T maxsize, minsize;
SMB_OFF_T file_size; /* space_avail; */
BOOL exist;
int rc = -1;
@@ -431,6 +442,12 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
goto done;
}
+ minsize = recycle_minsize(handle);
+ if(minsize > 0 && file_size < minsize) {
+ DEBUG(3, ("recycle: File %s lowers minimum recycle size, purging... \n", file_name));
+ rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
+ goto done;
+ }
/* FIXME: this is wrong: moving files with rename does not change the disk space
* allocation
diff --git a/source/nsswitch/idmap.c b/source/nsswitch/idmap.c
index a58959afe4c..c2a38fa9797 100644
--- a/source/nsswitch/idmap.c
+++ b/source/nsswitch/idmap.c
@@ -297,7 +297,6 @@ NTSTATUS idmap_init(void)
char *p = NULL;
const char *q = NULL;
- DEBUG(0, ("WARNING: idmap backend is deprecated!\n"));
compat = 1;
if ( (compat_backend = talloc_strdup( idmap_ctx, *compat_list )) == NULL ) {
@@ -337,6 +336,15 @@ NTSTATUS idmap_init(void)
const char *parm_backend;
char *config_option;
+ /* ignore BUILTIN and local MACHINE domains */
+ if ( strequal(dom_list[i], "BUILTIN")
+ || strequal(dom_list[i], get_global_sam_name() ) )
+ {
+ DEBUG(0,("idmap_init: Ignoring invalid domain %s\n",
+ dom_list[i]));
+ continue;
+ }
+
if (strequal(dom_list[i], lp_workgroup())) {
pri_dom_is_in_list = True;
}
@@ -577,17 +585,22 @@ NTSTATUS idmap_init(void)
alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
}
}
- if ( ! alloc_methods) {
- DEBUG(0, ("ERROR: Could not get methods for alloc backend %s\n", alloc_backend));
- ret = NT_STATUS_UNSUCCESSFUL;
- goto done;
- }
-
- ret = alloc_methods->init(compat_params);
- if ( ! NT_STATUS_IS_OK(ret)) {
- DEBUG(0, ("ERROR: Initialization failed for alloc backend %s\n", alloc_backend));
- ret = NT_STATUS_UNSUCCESSFUL;
- goto done;
+ if ( alloc_methods) {
+ ret = alloc_methods->init(compat_params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("idmap_init: Initialization failed for alloc "
+ "backend %s\n", alloc_backend));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ } else {
+ DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n",
+ alloc_backend));
+ /* certain compat backends are just readonly */
+ if ( compat )
+ ret = NT_STATUS_OK;
+ else
+ ret = NT_STATUS_UNSUCCESSFUL;
}
/* cleanpu temporary strings */
@@ -595,7 +608,7 @@ NTSTATUS idmap_init(void)
backend_init_status = NT_STATUS_OK;
- return NT_STATUS_OK;
+ return ret;
done:
DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
diff --git a/source/nsswitch/idmap_ldap.c b/source/nsswitch/idmap_ldap.c
index 8cccbcecf4c..f74372eceab 100644
--- a/source/nsswitch/idmap_ldap.c
+++ b/source/nsswitch/idmap_ldap.c
@@ -1283,6 +1283,9 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id
sid, (unsigned long)map->xid.id, type));
DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n",
ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
+ if (ld_error) {
+ ldap_memfree(ld_error);
+ }
ret = NT_STATUS_UNSUCCESSFUL;
goto done;
}
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index d21c985feee..66f9a093144 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
/* Fill in request and send down pipe */
init_request(request, req_type);
- if (write_sock(request, sizeof(*request), 0) == -1) {
+ if (write_sock(request, sizeof(*request), 0, 1) == -1) {
_pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!");
close_sock();
return PAM_SERVICE_ERR;
@@ -1517,7 +1517,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
dictionary *d = NULL;
char *username_ret = NULL;
char *new_authtok_required = NULL;
- char *combined_member = NULL;
const char *real_username = NULL;
/* parse arguments */
diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c
index 05d2a660e73..fb84373aa63 100644
--- a/source/nsswitch/wb_common.c
+++ b/source/nsswitch/wb_common.c
@@ -33,6 +33,7 @@ BOOL winbind_on( void );
/* Global variables. These are effectively the client state information */
int winbindd_fd = -1; /* fd for winbindd socket */
+static int is_privileged = 0;
/* Free a response structure */
@@ -287,7 +288,7 @@ static int winbind_named_pipe_sock(const char *dir)
/* Connect to winbindd socket */
-static int winbind_open_pipe_sock(int recursing)
+static int winbind_open_pipe_sock(int recursing, int need_priv)
{
#ifdef HAVE_UNIXSOCKET
static pid_t our_pid;
@@ -300,6 +301,10 @@ static int winbind_open_pipe_sock(int recursing)
close_sock();
our_pid = getpid();
}
+
+ if ((need_priv != 0) && (is_privileged == 0)) {
+ close_sock();
+ }
if (winbindd_fd != -1) {
return winbindd_fd;
@@ -313,6 +318,8 @@ static int winbind_open_pipe_sock(int recursing)
return -1;
}
+ is_privileged = 0;
+
/* version-check the socket */
request.flags = WBFLAG_RECURSE;
@@ -329,9 +336,14 @@ static int winbind_open_pipe_sock(int recursing)
if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) {
close(winbindd_fd);
winbindd_fd = fd;
+ is_privileged = 1;
}
}
+ if ((need_priv != 0) && (is_privileged == 0)) {
+ return -1;
+ }
+
SAFE_FREE(response.extra_data.data);
return winbindd_fd;
@@ -342,7 +354,7 @@ static int winbind_open_pipe_sock(int recursing)
/* Write data to winbindd socket */
-int write_sock(void *buffer, int count, int recursing)
+int write_sock(void *buffer, int count, int recursing, int need_priv)
{
int result, nwritten;
@@ -350,7 +362,7 @@ int write_sock(void *buffer, int count, int recursing)
restart:
- if (winbind_open_pipe_sock(recursing) == -1) {
+ if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
return -1;
}
@@ -536,7 +548,8 @@ BOOL winbind_env_set( void )
* send simple types of requests
*/
-NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
+NSS_STATUS winbindd_send_request(int req_type, int need_priv,
+ struct winbindd_request *request)
{
struct winbindd_request lrequest;
@@ -555,12 +568,14 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
init_request(request, req_type);
- if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) {
+ if (write_sock(request, sizeof(*request),
+ request->flags & WBFLAG_RECURSE, need_priv) == -1) {
return NSS_STATUS_UNAVAIL;
}
if ((request->extra_len != 0) &&
- (write_sock(request->extra_data.data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
+ (write_sock(request->extra_data.data, request->extra_len,
+ request->flags & WBFLAG_RECURSE, need_priv) == -1)) {
return NSS_STATUS_UNAVAIL;
}
@@ -610,7 +625,25 @@ NSS_STATUS winbindd_request_response(int req_type,
int count = 0;
while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
- status = winbindd_send_request(req_type, request);
+ status = winbindd_send_request(req_type, 0, request);
+ if (status != NSS_STATUS_SUCCESS)
+ return(status);
+ status = winbindd_get_response(response);
+ count += 1;
+ }
+
+ return status;
+}
+
+NSS_STATUS winbindd_priv_request_response(int req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response)
+{
+ NSS_STATUS status = NSS_STATUS_UNAVAIL;
+ int count = 0;
+
+ while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
+ status = winbindd_send_request(req_type, 1, request);
if (status != NSS_STATUS_SUCCESS)
return(status);
status = winbindd_get_response(response);
diff --git a/source/nsswitch/winbind_client.h b/source/nsswitch/winbind_client.h
index 1d3d379af00..d80aff37fa1 100644
--- a/source/nsswitch/winbind_client.h
+++ b/source/nsswitch/winbind_client.h
@@ -2,13 +2,16 @@
#include "winbindd_nss.h"
void init_request(struct winbindd_request *req,int rq_type);
-NSS_STATUS winbindd_send_request(int req_type,
+NSS_STATUS winbindd_send_request(int req_type, int need_priv,
struct winbindd_request *request);
NSS_STATUS winbindd_get_response(struct winbindd_response *response);
NSS_STATUS winbindd_request_response(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
-int write_sock(void *buffer, int count, int recursing);
+NSS_STATUS winbindd_priv_request_response(int req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response);
+int write_sock(void *buffer, int count, int recursing, int need_priv);
int read_reply(struct winbindd_response *response);
void close_sock(void);
void free_response(struct winbindd_response *response);
diff --git a/source/nsswitch/winbind_nss_irix.c b/source/nsswitch/winbind_nss_irix.c
index 2fbf3e0df82..5c6679f0442 100644
--- a/source/nsswitch/winbind_nss_irix.c
+++ b/source/nsswitch/winbind_nss_irix.c
@@ -454,7 +454,7 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
nsd_logprintf(NSD_LOG_MIN,
"send_next_request (winbind) %d, timeout = %d sec\n",
rq->f_cmd_data, timeout);
- status = winbindd_send_request((int)rq->f_cmd_data,request);
+ status = winbindd_send_request((int)rq->f_cmd_data,request,0);
SAFE_FREE(request);
if (status != NSS_STATUS_SUCCESS) {
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 3ddb041ba07..3b518fe3206 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -726,6 +726,15 @@ static void process_loop(void)
int maxfd, listen_sock, listen_priv_sock, selret;
struct timeval timeout, ev_timeout;
+ /* Open Sockets here to get stuff going ASAP */
+ listen_sock = open_winbindd_socket();
+ listen_priv_sock = open_winbindd_priv_socket();
+
+ if (listen_sock == -1 || listen_priv_sock == -1) {
+ perror("open_winbind_socket");
+ exit(1);
+ }
+
/* We'll be doing this a lot */
/* Handle messages */
@@ -745,14 +754,6 @@ static void process_loop(void)
/* Initialise fd lists for select() */
- listen_sock = open_winbindd_socket();
- listen_priv_sock = open_winbindd_priv_socket();
-
- if (listen_sock == -1 || listen_priv_sock == -1) {
- perror("open_winbind_socket");
- exit(1);
- }
-
maxfd = MAX(listen_sock, listen_priv_sock);
FD_ZERO(&r_fds);
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index b9e07a2321b..198c655b2d3 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -40,6 +40,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+#define WB_REPLACE_CHAR '_'
+
/* bits for fd_event.flags */
#define EVENT_FD_READ 1
#define EVENT_FD_WRITE 2
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index ea6dc2870a0..3925228efc6 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -40,6 +40,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
{
ADS_STRUCT *ads;
ADS_STATUS status;
+ fstring dc_name;
+ struct in_addr dc_ip;
DEBUG(10,("ads_cached_connection\n"));
@@ -114,6 +116,12 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
+ /* Setup the server affinity cache. We don't reaally care
+ about the name. Just setup affinity and the KRB5_CONFIG
+ file. */
+
+ get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip );
+
status = ads_connect(ads);
if (!ADS_ERR_OK(status) || !ads->config.realm) {
DEBUG(1,("ads_connect for domain %s failed: %s\n",
@@ -607,7 +615,6 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
const char *attrs[] = {"memberOf", NULL};
size_t num_groups = 0;
DOM_SID *group_sids = NULL;
- char *escaped_dn;
int i;
DEBUG(3,("ads: lookup_usergroups_memberof\n"));
@@ -619,16 +626,9 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
goto done;
}
- if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) {
- status = NT_STATUS_NO_MEMORY;
- goto done;
- }
-
- rc = ads_search_retry_extended_dn(ads, &res, escaped_dn, attrs,
+ rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs,
ADS_EXTENDED_DN_HEX_STRING);
- SAFE_FREE(escaped_dn);
-
if (!ADS_ERR_OK(rc) || !res) {
DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n",
user_dn, ads_errstr(rc)));
diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c
index d0904002dd9..f161587e7aa 100644
--- a/source/nsswitch/winbindd_cred_cache.c
+++ b/source/nsswitch/winbindd_cred_cache.c
@@ -517,6 +517,7 @@ static NTSTATUS store_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp, const
if ((mlock(memcredp->nt_hash, memcredp->len)) == -1) {
DEBUG(0,("failed to mlock memory: %s (%d)\n",
strerror(errno), errno));
+ SAFE_FREE(memcredp->nt_hash);
return map_nt_error_from_unix(errno);
}
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index 6324de9a2d9..26debd26745 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -573,8 +573,8 @@ void winbind_msg_online(int msg_type, struct process_id src,
winbindd_flush_negative_conn_cache(domain);
set_domain_online_request(domain);
- /* Send an offline message to the idmap child when our
- primary domain goes offline */
+ /* Send an online message to the idmap child when our
+ primary domain comes back online */
if ( domain->primary ) {
struct winbindd_child *idmap = idmap_child();
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index 7edb755f1c0..9cf6cc12e0f 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -228,10 +228,12 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
* from more than one domain, ie aliases. Thus we have to work it out
* ourselves in a special routine. */
- if (domain->internal)
- return fill_passdb_alias_grmem(domain, group_sid,
+ if (domain->internal) {
+ result = fill_passdb_alias_grmem(domain, group_sid,
num_gr_mem,
gr_mem, gr_mem_len);
+ goto done;
+ }
if ( !((group_name_type==SID_NAME_DOM_GRP) ||
((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
@@ -506,7 +508,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
/* Get rid and name type from name */
- ws_name_replace( name_group, '_' );
+ ws_name_replace( name_group, WB_REPLACE_CHAR );
if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, domain->name,
name_group, &group_sid, &name_type)) {
@@ -1273,6 +1275,8 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
s->state = state;
+ ws_name_return( state->request.data.username, WB_REPLACE_CHAR );
+
if (!parse_domain_user_talloc(state->mem_ctx,
state->request.data.username,
&s->domname, &s->username)) {
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index 2e679c37dcf..6ee548292cc 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -744,6 +744,8 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
/* Parse domain and username */
+ ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
+
if (!canonicalize_username(state->request.data.auth.user,
name_domain, name_user)) {
set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
@@ -1332,6 +1334,8 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
/* Parse domain and username */
+ ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
+
parse_domain_user(state->request.data.auth.user, name_domain, name_user);
if (domain->online == False) {
@@ -2088,7 +2092,9 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
{
struct winbindd_domain *domain;
fstring name_domain, user;
-
+ uid_t caller_uid = (uid_t)-1;
+ uid_t request_uid = state->request.data.logoff.uid;
+
DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
state->request.data.logoff.user));
@@ -2099,6 +2105,10 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
state->request.data.logoff.krb5ccname
[sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
+ if (request_uid == (gid_t)-1) {
+ goto failed;
+ }
+
if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) {
goto failed;
}
@@ -2107,6 +2117,28 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
goto failed;
}
+ if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {
+ DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n",
+ strerror(errno)));
+ goto failed;
+ }
+
+ switch (caller_uid) {
+ case -1:
+ goto failed;
+ case 0:
+ /* root must be able to logoff any user - gd */
+ state->request.data.logoff.uid = request_uid;
+ break;
+ default:
+ if (caller_uid != request_uid) {
+ DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));
+ goto failed;
+ }
+ state->request.data.logoff.uid = caller_uid;
+ break;
+ }
+
sendto_domain(state, domain);
return;
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 11d9fe0dbbd..3707f0311f8 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -262,7 +262,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
return NT_STATUS_NO_MEMORY;
}
- ws_name_return( full_name, '_' );
+ ws_name_return( full_name, WB_REPLACE_CHAR );
DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
@@ -317,7 +317,7 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
*domain_name = domains[0];
*name = names[0];
- ws_name_replace( *name, '_' );
+ ws_name_replace( *name, WB_REPLACE_CHAR );
DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
return NT_STATUS_OK;
@@ -369,7 +369,7 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
ret_names = *names;
for (i=0; i<num_rids; i++) {
if ((*types)[i] != SID_NAME_UNKNOWN) {
- ws_name_replace( ret_names[i], '_' );
+ ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
*domain_name = domains[i];
}
}
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 47a7364e3a7..ce677198fff 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -243,7 +243,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
strlower_m( username );
s->username = talloc_strdup(s->state->mem_ctx, username);
- ws_name_replace( s->username, '_' );
+ ws_name_replace( s->username, WB_REPLACE_CHAR );
s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
@@ -262,7 +262,7 @@ static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid)
talloc_get_type_abort(private_data, struct getpwsid_state);
if (!success) {
- DEBUG(5, ("Could not query user's %s\\%s uid\n",
+ DEBUG(5, ("Could not query uid for user %s\\%s\n",
s->domain->name, s->username));
request_error(s->state);
return;
@@ -289,7 +289,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
if ( s->gid == (gid_t)-1 ) {
if (!success) {
- DEBUG(5, ("Could not query user's %s\\%s\n gid",
+ DEBUG(5, ("Could not query gid for user %s\\%s\n",
s->domain->name, s->username));
goto failed;
}
@@ -345,6 +345,8 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid,
state->request.data.username));
+ ws_name_return( state->request.data.username, WB_REPLACE_CHAR );
+
if (!parse_domain_user(state->request.data.username, domname,
username)) {
DEBUG(5, ("Could not parse domain user: %s\n",
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 5d6a0c4ff54..85c1f4a9b64 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -229,7 +229,6 @@ typedef struct {
int winbind_cache_time;
int winbind_max_idle_children;
char **szWinbindNssInfo;
- int iLockSpinCount;
int iLockSpinTime;
char *szLdapMachineSuffix;
char *szLdapUserSuffix;
@@ -290,6 +289,7 @@ typedef struct {
BOOL bClientNTLMv2Auth;
BOOL bClientPlaintextAuth;
BOOL bClientUseSpnego;
+ BOOL bDebugPrefixTimestamp;
BOOL bDebugHiresTimestamp;
BOOL bDebugPid;
BOOL bDebugUid;
@@ -953,6 +953,7 @@ static struct parm_struct parm_table[] = {
{"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED},
{"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED},
{"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED},
+ {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED},
{"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED},
{"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED},
{"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED},
@@ -1156,7 +1157,6 @@ static struct parm_struct parm_table[] = {
{"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
{"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
- {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
{"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
{"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
@@ -1269,14 +1269,14 @@ static struct parm_struct parm_table[] = {
{"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
{"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED},
- {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
+ {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED },
{"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED},
{"idmap expire time", P_INTEGER, P_GLOBAL, &Globals.iIdmapExpireTime, NULL, NULL, FLAG_ADVANCED},
{"idmap negative time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeTime, NULL, NULL, FLAG_ADVANCED},
- {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
- {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE | FLAG_DEPRECATED },
- {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED },
- {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE | FLAG_DEPRECATED },
+ {"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_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_HIDE },
{"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED},
{"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED},
{"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED},
@@ -1517,6 +1517,7 @@ static void init_globals(BOOL first_time_only)
Globals.bSyslogOnly = False;
Globals.bTimestampLogs = True;
string_set(&Globals.szLogLevel, "0");
+ Globals.bDebugPrefixTimestamp = False;
Globals.bDebugHiresTimestamp = False;
Globals.bDebugPid = False;
Globals.bDebugUid = False;
@@ -1557,7 +1558,6 @@ static void init_globals(BOOL first_time_only)
Globals.map_to_guest = 0; /* By Default, "Never" */
Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
Globals.enhanced_browsing = True;
- Globals.iLockSpinCount = 0; /* Unused. */
Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
#ifdef MMAP_BLACKLIST
Globals.bUseMmap = False;
@@ -1945,6 +1945,7 @@ FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
+FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
@@ -2010,7 +2011,6 @@ FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
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_spin_time, &Globals.iLockSpinTime)
FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index 0b596fc8d7f..d76cc07ce1e 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -411,9 +411,15 @@ static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
names[i] = "";
types[i] = SID_NAME_UNKNOWN;
}
+ TALLOC_FREE(tmp_ctx);
return True;
}
+ if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
+ TALLOC_FREE(tmp_ctx);
+ return False;
+ }
+
/*
* winbind_lookup_rids allocates its own array. We've been given the
* array, so copy it over
@@ -1115,7 +1121,7 @@ void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
*THE LEGACY* convert uid_t to SID function.
*****************************************************************/
-void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
+static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
{
uint32 rid;
BOOL ret;
@@ -1149,7 +1155,7 @@ void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
*THE LEGACY* convert gid_t to SID function.
*****************************************************************/
-void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
+static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
{
BOOL ret;
@@ -1180,7 +1186,7 @@ void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
*THE LEGACY* convert SID to uid function.
*****************************************************************/
-BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
+static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
enum lsa_SidType type;
uint32 rid;
@@ -1229,7 +1235,7 @@ done:
Group mapping is used for gids that maps to Wellknown SIDs
*****************************************************************/
-BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
uint32 rid;
GROUP_MAP map;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 533b936efd9..c4c53c30664 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -2049,14 +2049,25 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
TALLOC_FREE( attr_list );
if (num_result == 0) {
+ char *escape_username;
/* Check if we need to add an entry */
DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
ldap_op = LDAP_MOD_ADD;
+
+ escape_username = escape_rdn_val_string_alloc(username);
+ if (!escape_username) {
+ DEBUG(0, ("Out of memory!\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
if (username[strlen(username)-1] == '$') {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_machine_suffix ());
} else {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_user_suffix ());
}
+
+ SAFE_FREE(escape_username);
}
if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
@@ -2415,11 +2426,22 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
}
for (memberuid = values; *memberuid != NULL; memberuid += 1) {
- filter = talloc_asprintf_append(filter, "(uid=%s)", *memberuid);
+ char *escape_memberuid;
+
+ escape_memberuid = escape_ldap_string_alloc(*memberuid);
+ if (escape_memberuid == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ filter = talloc_asprintf_append(filter, "(uid=%s)", escape_memberuid);
if (filter == NULL) {
+ SAFE_FREE(escape_memberuid);
ret = NT_STATUS_NO_MEMORY;
goto done;
}
+
+ SAFE_FREE(escape_memberuid);
}
filter = talloc_asprintf_append(filter, "))");
@@ -4773,6 +4795,8 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
if (add_posix) {
+ char *escape_name;
+
DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
/* retrieve the Domain Users group gid */
@@ -4799,12 +4823,21 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
}
uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+
+ escape_name = escape_rdn_val_string_alloc(name);
+ if (!escape_name) {
+ DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
if (is_machine) {
- dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_machine_suffix ());
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
} else {
- dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_user_suffix ());
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
}
+ SAFE_FREE(escape_name);
+
if (!homedir || !shell || !uidstr || !gidstr || !dn) {
DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
return NT_STATUS_NO_MEMORY;
@@ -4986,6 +5019,8 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
}
if (num_result == 0) {
+ char *escape_name;
+
DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
is_new_entry = True;
@@ -4997,7 +5032,16 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
}
gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
- dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, lp_ldap_group_suffix());
+
+ escape_name = escape_rdn_val_string_alloc(name);
+ if (!escape_name) {
+ DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
+
+ SAFE_FREE(escape_name);
if (!gidstr || !dn) {
DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
@@ -5335,6 +5379,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
uint32 num_result;
LDAPMod **mods = NULL;
char *filter;
+ char *escape_username;
char *gidstr;
const char *dn = NULL;
gid_t gid;
@@ -5351,14 +5396,22 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
return NT_STATUS_NO_MEMORY;
}
-
+
+ escape_username = escape_ldap_string_alloc(pdb_get_username(sampass));
+ if (escape_username== NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
filter = talloc_asprintf(mem_ctx,
"(&(uid=%s)"
"(objectClass=%s)"
"(objectClass=%s))",
- pdb_get_username(sampass),
+ escape_username,
LDAP_OBJ_POSIXACCOUNT,
LDAP_OBJ_SAMBASAMACCOUNT);
+
+ SAFE_FREE(escape_username);
+
if (filter == NULL) {
return NT_STATUS_NO_MEMORY;
}
@@ -5620,6 +5673,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
+ ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -5636,6 +5690,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
"read as a valid SID\n", domain_sid_string));
+ ldap_msgfree(result);
return NT_STATUS_INVALID_PARAMETER;
}
found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 063e4b3e175..8829ef2b0c2 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -1036,13 +1036,12 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
char *buf = NULL;
ssize_t byte_count;
- if ((buf=(char *)SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
- DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
- fname, PE_HEADER_SIZE));
+ if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
+ DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
+ fname, DOS_HEADER_SIZE));
goto error_exit;
}
- /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
fname, (unsigned long)byte_count));
@@ -1064,7 +1063,8 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
goto no_version_info;
}
- if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
+ /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
+ if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
fname, (unsigned long)byte_count));
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
@@ -1075,13 +1075,13 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
unsigned int num_sections;
unsigned int section_table_bytes;
-
- if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
- DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
- fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
- /* At this point, we assume the file is in error. It still could be somthing
- * else besides a PE file, but it unlikely at this point.
- */
+
+ /* Just skip over optional header to get to section table */
+ if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
+ SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
+ SEEK_CUR) == (SMB_OFF_T)-1) {
+ DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
+ fname, errno));
goto error_exit;
}
@@ -1823,7 +1823,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
driver_unix_convert(new_name, conn, NULL, &st);
- if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@@ -1839,7 +1839,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
driver_unix_convert(new_name, conn, NULL, &st);
- if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@@ -1857,7 +1857,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
driver_unix_convert(new_name, conn, NULL, &st);
- if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@@ -1876,7 +1876,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
driver_unix_convert(new_name, conn, NULL, &st);
- if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+ if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
@@ -1904,7 +1904,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
driver_unix_convert(new_name, conn, NULL, &st);
- if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn,
+ if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
OPENX_FILE_EXISTS_TRUNCATE|
OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -3034,7 +3034,7 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
{
ADS_STATUS ads_rc;
LDAPMessage *res;
- char *prt_dn = NULL, *srv_dn, *srv_cn_0;
+ char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
char *srv_dn_utf8, **srv_cn_utf8;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
@@ -3080,11 +3080,29 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
ldap_memfree(srv_dn_utf8);
ldap_memfree(srv_cn_utf8);
- asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
- printer->info_2->sharename, srv_dn);
+ srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
+ if (!srv_cn_escaped) {
+ SAFE_FREE(srv_cn_0);
+ ldap_memfree(srv_dn_utf8);
+ ads_destroy(&ads);
+ return WERR_SERVER_UNAVAILABLE;
+ }
+ sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
+ if (!sharename_escaped) {
+ SAFE_FREE(srv_cn_escaped);
+ SAFE_FREE(srv_cn_0);
+ ldap_memfree(srv_dn_utf8);
+ ads_destroy(&ads);
+ return WERR_SERVER_UNAVAILABLE;
+ }
+
+
+ asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
SAFE_FREE(srv_dn);
SAFE_FREE(srv_cn_0);
+ SAFE_FREE(srv_cn_escaped);
+ SAFE_FREE(sharename_escaped);
/* build the ads mods */
ctx = talloc_init("nt_printer_publish_ads");
@@ -3725,9 +3743,7 @@ static void map_to_os2_driver(fstring drivername)
****************************************************************************/
static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
{
- int snum;
-
- snum = lp_servicenumber(sharename);
+ int snum = lp_servicenumber(sharename);
slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
@@ -3751,6 +3767,15 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char
fstrcpy(info->printprocessor, "winprint");
fstrcpy(info->datatype, "RAW");
+#ifdef HAVE_CUPS
+ if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
+ /* Pull the location and comment strings from cups if we don't
+ already have one */
+ if ( !strlen(info->location) || !strlen(info->comment) )
+ cups_pull_comment_location( info );
+ }
+#endif
+
info->attributes = PRINTER_ATTRIBUTE_SAMBA;
info->starttime = 0; /* Minutes since 12:00am GMT */
@@ -3846,6 +3871,15 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servern
fstrcpy(info->printername, printername);
+#ifdef HAVE_CUPS
+ if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
+ /* Pull the location and comment strings from cups if we don't
+ already have one */
+ if ( !strlen(info->location) || !strlen(info->comment) )
+ cups_pull_comment_location( info );
+ }
+#endif
+
len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
/*
diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c
index 2c942627c6b..0fa73e5a6ca 100644
--- a/source/printing/print_cups.c
+++ b/source/printing/print_cups.c
@@ -1198,6 +1198,145 @@ struct printif cups_printif =
cups_job_submit,
};
+BOOL cups_pull_comment_location(NT_PRINTER_INFO_LEVEL_2 *printer)
+{
+ http_t *http = NULL; /* HTTP connection to server */
+ ipp_t *request = NULL, /* IPP Request */
+ *response = NULL; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language = NULL; /* Default language */
+ char *name, /* printer-name attribute */
+ *info, /* printer-info attribute */
+ *location; /* printer-location attribute */
+ char uri[HTTP_MAX_URI];
+ static const char *requested[] =/* Requested attributes */
+ {
+ "printer-name",
+ "printer-info",
+ "printer-location"
+ };
+ BOOL ret = False;
+
+ DEBUG(5, ("pulling %s location\n", printer->sharename));
+
+ /*
+ * Make sure we don't ask for passwords...
+ */
+
+ cupsSetPasswordCB(cups_passwd_cb);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((http = cups_connect()) == NULL) {
+ goto out;
+ }
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
+ lp_cups_server(), printer->sharename);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ (sizeof(requested) / sizeof(requested[0])),
+ NULL, requested);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) == NULL) {
+ DEBUG(0,("Unable to get printer attributes - %s\n",
+ ippErrorString(cupsLastError())));
+ goto out;
+ }
+
+ for (attr = response->attrs; attr != NULL;) {
+ /*
+ * Skip leading attributes until we hit a printer...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this printer...
+ */
+
+ name = NULL;
+ info = NULL;
+ location = NULL;
+
+ while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
+ /* Grab the comment if we don't have one */
+ if ( (strcmp(attr->name, "printer-info") == 0)
+ && (attr->value_tag == IPP_TAG_TEXT)
+ && !strlen(printer->comment) )
+ {
+ DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
+ attr->values[0].string.text));
+ pstrcpy(printer->comment,attr->values[0].string.text);
+ }
+
+ /* Grab the location if we don't have one */
+ if ( (strcmp(attr->name, "printer-location") == 0)
+ && (attr->value_tag == IPP_TAG_TEXT)
+ && !strlen(printer->location) )
+ {
+ DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
+ attr->values[0].string.text));
+ fstrcpy(printer->location,attr->values[0].string.text);
+ }
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (name == NULL)
+ break;
+
+ }
+
+ ippDelete(response);
+ response = NULL;
+
+ ret = True;
+
+ out:
+ if (response)
+ ippDelete(response);
+
+ if (language)
+ cupsLangFree(language);
+
+ if (http)
+ httpClose(http);
+
+ return ret;
+}
+
#else
/* this keeps fussy compilers happy */
void print_cups_dummy(void);
diff --git a/source/profile/profile.c b/source/profile/profile.c
index 4568678739f..69c240061e1 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -284,7 +284,7 @@ BOOL profile_setup(BOOL rdonly)
"syscall_fchown", /* PR_VALUE_SYSCALL_FCHOWN */
"syscall_chdir", /* PR_VALUE_SYSCALL_CHDIR */
"syscall_getwd", /* PR_VALUE_SYSCALL_GETWD */
- "syscall_utime", /* PR_VALUE_SYSCALL_UTIME */
+ "syscall_ntimes", /* PR_VALUE_SYSCALL_NTIMES */
"syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */
"syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */
"syscall_kernel_flock", /* PR_VALUE_SYSCALL_KERNEL_FLOCK */
diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c
index 0d50e94d577..7b4818b4b06 100644
--- a/source/rpc_client/cli_srvsvc.c
+++ b/source/rpc_client/cli_srvsvc.c
@@ -5,6 +5,8 @@
Copyright (C) Tim Potter 2001
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
Copyright (C) Jeremy Allison 2005.
+ Copyright (C) Gerald (Jerry) Carter 2006.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -537,38 +539,37 @@ WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_
ZERO_STRUCTP(ctr);
- ctr->switch_value = file_level;
+ ctr->level = file_level;
ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
switch(file_level) {
case 3:
- ctr->file.info3 = TALLOC_ARRAY(mem_ctx, SRV_FILE_INFO_3, ctr->num_entries);
- if (ctr->file.info3 == NULL) {
+ if ( (ctr->file.info3 = TALLOC_ARRAY(mem_ctx, FILE_INFO_3, ctr->num_entries)) == NULL ) {
return WERR_NOMEM;
}
- memset(ctr->file.info3, 0,
- sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
+ memset(ctr->file.info3, 0, sizeof(FILE_INFO_3) * ctr->num_entries);
for (i = 0; i < r.ctr.num_entries; i++) {
- SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
+ FILE_INFO_3 *info3 = &ctr->file.info3[i];
char *s;
/* Copy pointer crap */
- memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3,
- sizeof(FILE_INFO_3));
+ memcpy(info3, &r.ctr.file.info3[i], sizeof(FILE_INFO_3));
/* Duplicate strings */
- s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
- if (s)
- init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE);
+ if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].path)) != NULL ) {
+ info3->path = TALLOC_P( mem_ctx, UNISTR2 );
+ init_unistr2(info3->path, s, UNI_STR_TERMINATE);
+ }
- s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
- if (s)
- init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE);
+ if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].user)) != NULL ) {
+ info3->user = TALLOC_P( mem_ctx, UNISTR2 );
+ init_unistr2(info3->user, s, UNI_STR_TERMINATE);
+ }
}
diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c
index 7d15eda630f..8ed67872430 100644
--- a/source/rpc_parse/parse_srv.c
+++ b/source/rpc_parse/parse_srv.c
@@ -7,6 +7,7 @@
* Copyright (C) Jeremy Allison 1999,
* Copyright (C) Nigel Williams 2001,
* Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2002.
+ * Copyright (C) Gerald (Jerry) Carter 2006.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1588,64 +1589,17 @@ BOOL srv_io_r_net_share_del(const char *desc, SRV_R_NET_SHARE_DEL *q_n, prs_stru
Inits a SESS_INFO_0_STR structure
********************************************************************/
-void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, const char *name)
+void init_srv_sess_info0( SESS_INFO_0 *ss0, const char *name )
{
- DEBUG(5,("init_srv_sess_info0_str\n"));
+ ZERO_STRUCTP( ss0 );
- init_unistr2(&ss0->uni_name, name, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0_str(const char *desc, SESS_INFO_0_STR *ss0, prs_struct *ps, int depth)
-{
- if (ss0 == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_sess_info0_str");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!smb_io_unistr2("", &ss0->uni_name, True, ps, depth))
- return False;
-
- return True;
-}
-
-/*******************************************************************
- Inits a SESS_INFO_0 structure
-********************************************************************/
-
-void init_srv_sess_info0(SESS_INFO_0 *ss0, const char *name)
-{
- DEBUG(5,("init_srv_sess_info0: %s\n", name));
-
- ss0->ptr_name = (name != NULL) ? 1 : 0;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0(const char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth)
-{
- if (ss0 == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_sess_info0");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("ptr_name", ps, depth, &ss0->ptr_name))
- return False;
-
- return True;
+ if ( name ) {
+ if ( (ss0->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+ DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+ return;
+ }
+ init_unistr2( ss0->sharename, name, UNI_STR_TERMINATE );
+ }
}
/*******************************************************************
@@ -1681,13 +1635,15 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
SMB_ASSERT_ARRAY(ss0->info_0, num_entries);
+ /* first the pointers */
for (i = 0; i < num_entries; i++) {
- if(!srv_io_sess_info0("", &ss0->info_0[i], ps, depth))
+ if ( !prs_io_unistr2_p("", ps, depth, &ss0->info_0[i].sharename ) )
return False;
}
+ /* now the strings */
for (i = 0; i < num_entries; i++) {
- if(!srv_io_sess_info0_str("", &ss0->info_0_str[i], ps, depth))
+ if ( !prs_io_unistr2("sharename", ps, depth, ss0->info_0[i].sharename ))
return False;
}
@@ -1699,53 +1655,32 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
}
/*******************************************************************
- Inits a SESS_INFO_1_STR structure
-********************************************************************/
-
-void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char *user)
-{
- DEBUG(5,("init_srv_sess_info1_str\n"));
-
- init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE);
- init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1_str(const char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth)
-{
- if (ss1 == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_sess_info1_str");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!smb_io_unistr2("", &ss1->uni_name, True, ps, depth))
- return False;
- if(!smb_io_unistr2("", &(ss1->uni_user), True, ps, depth))
- return False;
-
- return True;
-}
-
-/*******************************************************************
Inits a SESS_INFO_1 structure
********************************************************************/
-void init_srv_sess_info1(SESS_INFO_1 *ss1,
- const char *name, const char *user,
- uint32 num_opens, uint32 open_time, uint32 idle_time,
- uint32 user_flags)
+void init_srv_sess_info1( SESS_INFO_1 *ss1, const char *name, const char *user,
+ uint32 num_opens, uint32 open_time, uint32 idle_time,
+ uint32 user_flags)
{
DEBUG(5,("init_srv_sess_info1: %s\n", name));
- ss1->ptr_name = (name != NULL) ? 1 : 0;
- ss1->ptr_user = (user != NULL) ? 1 : 0;
+ ZERO_STRUCTP( ss1 );
+
+ if ( name ) {
+ if ( (ss1->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+ DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+ return;
+ }
+ init_unistr2( ss1->sharename, name, UNI_STR_TERMINATE );
+ }
+
+ if ( user ) {
+ if ( (ss1->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+ DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+ return;
+ }
+ init_unistr2( ss1->username, user, UNI_STR_TERMINATE );
+ }
ss1->num_opens = num_opens;
ss1->open_time = open_time;
@@ -1753,37 +1688,6 @@ void init_srv_sess_info1(SESS_INFO_1 *ss1,
ss1->user_flags = user_flags;
}
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1(const char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth)
-{
- if (ss1 == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_sess_info1");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("ptr_name ", ps, depth, &ss1->ptr_name))
- return False;
- if(!prs_uint32("ptr_user ", ps, depth, &ss1->ptr_user))
- return False;
-
- if(!prs_uint32("num_opens ", ps, depth, &ss1->num_opens))
- return False;
- if(!prs_uint32("open_time ", ps, depth, &ss1->open_time))
- return False;
- if(!prs_uint32("idle_time ", ps, depth, &ss1->idle_time))
- return False;
- if(!prs_uint32("user_flags", ps, depth, &ss1->user_flags))
- return False;
-
- return True;
-}
/*******************************************************************
Reads or writes a structure.
@@ -1818,13 +1722,31 @@ static BOOL srv_io_srv_sess_info_1(const char *desc, SRV_SESS_INFO_1 *ss1, prs_s
SMB_ASSERT_ARRAY(ss1->info_1, num_entries);
+ /* first the pointers and flags */
+
for (i = 0; i < num_entries; i++) {
- if(!srv_io_sess_info1("", &ss1->info_1[i], ps, depth))
+
+ if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].sharename ))
+ return False;
+ if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].username ))
+ return False;
+
+ if(!prs_uint32("num_opens ", ps, depth, &ss1->info_1[i].num_opens))
+ return False;
+ if(!prs_uint32("open_time ", ps, depth, &ss1->info_1[i].open_time))
+ return False;
+ if(!prs_uint32("idle_time ", ps, depth, &ss1->info_1[i].idle_time))
+ return False;
+ if(!prs_uint32("user_flags", ps, depth, &ss1->info_1[i].user_flags))
return False;
}
+ /* now the strings */
+
for (i = 0; i < num_entries; i++) {
- if(!srv_io_sess_info1_str("", &ss1->info_1_str[i], ps, depth))
+ if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].sharename ))
+ return False;
+ if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].username ))
return False;
}
@@ -1884,36 +1806,12 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr
}
/*******************************************************************
- Inits a SRV_Q_NET_SESS_ENUM structure.
-********************************************************************/
-
-void init_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n,
- const char *srv_name, const char *qual_name,
- const char *user_name, uint32 sess_level,
- SRV_SESS_INFO_CTR *ctr, uint32 preferred_len,
- ENUM_HND *hnd)
-{
- q_n->ctr = ctr;
-
- DEBUG(5,("init_q_net_sess_enum\n"));
-
- init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
- init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
- init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
-
- q_n->sess_level = sess_level;
- q_n->preferred_len = preferred_len;
-
- memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd));
-}
-
-/*******************************************************************
Reads or writes a structure.
********************************************************************/
-BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_u, prs_struct *ps, int depth)
{
- if (q_n == NULL)
+ if (q_u == NULL)
return False;
prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum");
@@ -1922,41 +1820,36 @@ BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_stru
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+ if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+ if(!prs_pointer("qualifier", ps, depth, (void**)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+
+ if(!prs_pointer("username", ps, depth, (void**)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
if(!prs_align(ps))
return False;
- if(!prs_uint32("sess_level", ps, depth, &q_n->sess_level))
+ if(!prs_uint32("sess_level", ps, depth, &q_u->sess_level))
return False;
- if (q_n->sess_level != (uint32)-1) {
- if(!srv_io_srv_sess_ctr("sess_ctr", &q_n->ctr, ps, depth))
+ if (q_u->sess_level != (uint32)-1) {
+ if(!srv_io_srv_sess_ctr("sess_ctr", &q_u->ctr, ps, depth))
return False;
}
- if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+ if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
return False;
- if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+ if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
return False;
return True;
@@ -2434,22 +2327,10 @@ BOOL srv_io_r_net_conn_enum(const char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_str
}
/*******************************************************************
- Inits a FILE_INFO_3_STR structure
-********************************************************************/
-
-void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const char *path_name)
-{
- DEBUG(5,("init_srv_file_info3_str\n"));
-
- init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE);
- init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
Reads or writes a structure.
********************************************************************/
-static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth)
+static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3 *sh1, prs_struct *ps, int depth)
{
if (sh1 == NULL)
return False;
@@ -2460,10 +2341,15 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
if(!prs_align(ps))
return False;
- if(!smb_io_unistr2("", &sh1->uni_path_name, True, ps, depth))
- return False;
- if(!smb_io_unistr2("", &sh1->uni_user_name, True, ps, depth))
- return False;
+ if ( sh1->path ) {
+ if(!smb_io_unistr2("", sh1->path, True, ps, depth))
+ return False;
+ }
+
+ if ( sh1->user ) {
+ if(!smb_io_unistr2("", sh1->user, True, ps, depth))
+ return False;
+ }
return True;
}
@@ -2472,18 +2358,26 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
Inits a FILE_INFO_3 structure
********************************************************************/
-void init_srv_file_info3(FILE_INFO_3 *fl3,
- uint32 id, uint32 perms, uint32 num_locks,
- const char *path_name, const char *user_name)
+void init_srv_file_info3( FILE_INFO_3 *fl3, uint32 id, uint32 perms, uint32 num_locks,
+ const char *user_name, const char *path_name )
{
- DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name));
-
fl3->id = id;
fl3->perms = perms;
fl3->num_locks = num_locks;
- fl3->ptr_path_name = (path_name != NULL) ? 1 : 0;
- fl3->ptr_user_name = (user_name != NULL) ? 1 : 0;
+ if ( path_name ) {
+ if ( (fl3->path = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+ return;
+ init_unistr2(fl3->path, path_name, UNI_STR_TERMINATE);
+ }
+
+ if ( user_name ) {
+ if ( (fl3->user = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+ return;
+ init_unistr2(fl3->user, user_name, UNI_STR_TERMINATE);
+ }
+
+ return;
}
/*******************************************************************
@@ -2492,6 +2386,8 @@ void init_srv_file_info3(FILE_INFO_3 *fl3,
static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth)
{
+ uint32 uni_p;
+
if (fl3 == NULL)
return False;
@@ -2507,10 +2403,24 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps
return False;
if(!prs_uint32("num_locks ", ps, depth, &fl3->num_locks))
return False;
- if(!prs_uint32("ptr_path_name", ps, depth, &fl3->ptr_path_name))
+
+ uni_p = fl3->path ? (uint32)fl3->path : 0;
+ if(!prs_uint32("ptr", ps, depth, &uni_p))
return False;
- if(!prs_uint32("ptr_user_name", ps, depth, &fl3->ptr_user_name))
+ if (UNMARSHALLING(ps)) {
+ if ( (fl3->path = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+ return False;
+ }
+ }
+
+ uni_p = fl3->user ? (uint32)fl3->user : 0;
+ if(!prs_uint32("ptr", ps, depth, &uni_p))
return False;
+ if (UNMARSHALLING(ps)) {
+ if ( (fl3->user = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+ return False;
+ }
+ }
return True;
}
@@ -2528,55 +2438,53 @@ static BOOL srv_io_srv_file_ctr(const char *desc, SRV_FILE_INFO_CTR *ctr, prs_st
depth++;
if (UNMARSHALLING(ps)) {
- memset(ctr, '\0', sizeof(SRV_FILE_INFO_CTR));
+ ZERO_STRUCTP(ctr);
}
if(!prs_align(ps))
return False;
- if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value))
+ if(!prs_uint32("level", ps, depth, &ctr->level))
return False;
- if (ctr->switch_value != 3) {
- DEBUG(5,("%s File info %d level not supported\n",
- tab_depth(depth), ctr->switch_value));
- }
+
if(!prs_uint32("ptr_file_info", ps, depth, &ctr->ptr_file_info))
return False;
if(!prs_uint32("num_entries", ps, depth, &ctr->num_entries))
return False;
if(!prs_uint32("ptr_entries", ps, depth, &ctr->ptr_entries))
return False;
+
if (ctr->ptr_entries == 0)
return True;
- if(!prs_uint32("num_entries2", ps, depth,
- &ctr->num_entries2))
+
+ if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries2))
return False;
- switch (ctr->switch_value) {
+ switch (ctr->level) {
case 3: {
- SRV_FILE_INFO_3 *info3 = ctr->file.info3;
+ FILE_INFO_3 *info3 = ctr->file.info3;
int num_entries = ctr->num_entries;
int i;
if (UNMARSHALLING(ps)) {
- if (!(info3 = PRS_ALLOC_MEM(ps, SRV_FILE_INFO_3, num_entries)))
+ if (!(info3 = PRS_ALLOC_MEM(ps, FILE_INFO_3, num_entries)))
return False;
ctr->file.info3 = info3;
}
for (i = 0; i < num_entries; i++) {
- if(!srv_io_file_info3("", &ctr->file.info3[i].info_3, ps, depth))
+ if(!srv_io_file_info3("", &ctr->file.info3[i], ps, depth))
return False;
}
+
for (i = 0; i < num_entries; i++) {
- if(!srv_io_file_info3_str("", &ctr->file.info3[i].info_3_str, ps, depth))
+ if(!srv_io_file_info3_str("", &ctr->file.info3[i], ps, depth))
return False;
}
break;
}
default:
- DEBUG(5,("%s no file info at switch_value %d\n",
- tab_depth(depth), ctr->switch_value));
+ DEBUG(5,("%s no file info at switch_value %d\n", tab_depth(depth), ctr->level));
break;
}
@@ -2594,13 +2502,28 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
uint32 preferred_len,
ENUM_HND *hnd)
{
- DEBUG(5,("init_q_net_file_enum\n"));
+ uint32 ptr;
- init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
- init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
- init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
+ if ( srv_name ) {
+ if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+ return;
+ init_buf_unistr2(q_n->servername, &ptr, srv_name);
+ }
+
+ if ( qual_name ) {
+ if ( (q_n->qualifier = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+ return;
+ init_buf_unistr2(q_n->qualifier, &ptr, qual_name);
+ }
+
+ if ( user_name ) {
+ if ( (q_n->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+ return;
+ init_buf_unistr2(q_n->username, &ptr, user_name);
+ }
+
+ q_n->level = q_n->ctr.level = file_level;
- q_n->file_level = q_n->ctr.switch_value = file_level;
q_n->preferred_len = preferred_len;
q_n->ctr.ptr_file_info = 1;
q_n->ctr.num_entries = 0;
@@ -2613,9 +2536,9 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
Reads or writes a structure.
********************************************************************/
-BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_u, prs_struct *ps, int depth)
{
- if (q_n == NULL)
+ if (q_u == NULL)
return False;
prs_debug(ps, depth, desc, "srv_io_q_net_file_enum");
@@ -2624,41 +2547,33 @@ BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_stru
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+ if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
- if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
- return False;
-
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+ if(!prs_pointer("qualifier", ps, depth, (void**)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
-
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+ if(!prs_pointer("username", ps, depth, (void**)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
-
if(!prs_align(ps))
return False;
- if(!prs_uint32("file_level", ps, depth, &q_n->file_level))
+
+ if(!prs_uint32("level", ps, depth, &q_u->level))
return False;
- if (q_n->file_level != (uint32)-1) {
- if(!srv_io_srv_file_ctr("file_ctr", &q_n->ctr, ps, depth))
+ if (q_u->level != (uint32)-1) {
+ if(!srv_io_srv_file_ctr("file_ctr", &q_u->ctr, ps, depth))
return False;
}
- if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+ if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
return False;
- if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+ if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
return False;
return True;
@@ -2679,10 +2594,10 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
if(!prs_align(ps))
return False;
- if(!prs_uint32("file_level", ps, depth, &r_n->file_level))
+ if(!prs_uint32("level", ps, depth, &r_n->level))
return False;
- if (r_n->file_level != 0) {
+ if (r_n->level != 0) {
if(!srv_io_srv_file_ctr("file_ctr", &r_n->ctr, ps, depth))
return False;
}
@@ -2703,63 +2618,17 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server,
uint32 file_id)
{
- q_n->ptr_srv_name = 1;
- init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE);
- q_n->file_id = file_id;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_n,
- prs_struct *ps, int depth)
-{
- if (q_n == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
- return False;
- if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
- return False;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_uint32("file_id", ps, depth, &q_n->file_id))
- return False;
+ if ( server ) {
+ if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+ return;
+ }
+ init_unistr2(q_n->servername, server, UNI_STR_TERMINATE);
+ }
- return True;
+ q_n->file_id = file_id;
}
/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *q_n,
- prs_struct *ps, int depth)
-{
- if (q_n == NULL)
- return False;
-
- prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
- depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!prs_werror("status", ps, depth, &q_n->status))
- return False;
-
- return True;
-}
-
-/*******************************************************************
Inits a SRV_INFO_100 structure.
********************************************************************/
@@ -3411,25 +3280,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru
}
/*******************************************************************
- initialises a structure.
- ********************************************************************/
-
-BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type)
-{
- uint32 ptr_share_name;
-
- DEBUG(5,("init_srv_q_net_name_validate\n"));
-
- init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
- init_buf_unistr2(&q_n->uni_name, &ptr_share_name, share_name);
-
- q_n->type = type;
- q_n->flags = 0;
-
- return True;
-}
-
-/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -3444,16 +3294,13 @@ BOOL srv_io_q_net_name_validate(const char *desc, SRV_Q_NET_NAME_VALIDATE *q_n,
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
- return False;
-
- if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+ if(!prs_pointer("servername", ps, depth, (void**)&q_n->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
return False;
if(!prs_align(ps))
return False;
- if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth))
+ if(!smb_io_unistr2("", &q_n->sharename, True, ps, depth))
return False;
if(!prs_align(ps))
@@ -3663,3 +3510,48 @@ void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server)
q_u->ptr_srv_name = 1;
init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE);
}
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_u, prs_struct *ps, int depth)
+{
+ if (q_u == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+ return False;
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("file_id", ps, depth, &q_u->file_id))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *r_n,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_werror("status", ps, depth, &r_n->status))
+ return False;
+
+ return True;
+}
diff --git a/source/rpc_server/srv_dfs_nt.c b/source/rpc_server/srv_dfs_nt.c
index 1a2ad38910a..e93b0077f0c 100644
--- a/source/rpc_server/srv_dfs_nt.c
+++ b/source/rpc_server/srv_dfs_nt.c
@@ -43,6 +43,8 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
struct current_user user;
struct junction_map jn;
struct referral* old_referral_list = NULL;
+ BOOL self_ref = False;
+ int consumedcnt = 0;
BOOL exists = False;
pstring dfspath, servername, sharename;
@@ -67,7 +69,7 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
pstrcat(altpath, sharename);
/* The following call can change the cwd. */
- if(get_referred_path(p->mem_ctx, dfspath, &jn, NULL, NULL)) {
+ if(get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref)) {
exists = True;
jn.referral_count += 1;
old_referral_list = jn.referral_list;
@@ -106,6 +108,8 @@ WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u,
{
struct current_user user;
struct junction_map jn;
+ BOOL self_ref = False;
+ int consumedcnt = 0;
BOOL found = False;
pstring dfspath, servername, sharename;
@@ -137,7 +141,7 @@ WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u,
DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
dfspath, servername, sharename));
- if(!get_referred_path(p->mem_ctx, dfspath, &jn, NULL, NULL)) {
+ if(!get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref)) {
return WERR_DFS_NO_SUCH_VOL;
}
@@ -346,6 +350,7 @@ WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u,
int consumedcnt = sizeof(pstring);
pstring path;
BOOL ret = False;
+ BOOL self_ref = False;
struct junction_map jn;
unistr2_to_ascii(path, uni_path, sizeof(path)-1);
@@ -353,7 +358,7 @@ WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u,
return WERR_DFS_NO_SUCH_SERVER;
/* The following call can change the cwd. */
- if(!get_referred_path(p->mem_ctx, path, &jn, &consumedcnt, NULL) || consumedcnt < strlen(path)) {
+ if(!get_referred_path(p->mem_ctx, path, &jn, &consumedcnt, &self_ref) || consumedcnt < strlen(path)) {
vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_NO_SUCH_VOL;
}
@@ -489,4 +494,3 @@ WERROR _dfs_SetInfo2(pipes_struct *p, NETDFS_Q_DFS_SETINFO2 *q_u, NETDFS_R_DFS_S
/* FIXME: Implement your code here */
return WERR_NOT_SUPPORTED;
}
-
diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c
index 9cc8b72546f..26e06f60a17 100644
--- a/source/rpc_server/srv_pipe_hnd.c
+++ b/source/rpc_server/srv_pipe_hnd.c
@@ -1169,6 +1169,13 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p)
p->name, p->pnum, pipes_open));
DLIST_REMOVE(Pipes, p);
+
+ /* Remove from pipe open db */
+
+ if ( !delete_pipe_opendb( p ) ) {
+ DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s "
+ "pipe from open db.\n", p->name));
+ }
ZERO_STRUCTP(p);
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index 07a89de5e61..0b2e24fa899 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -3886,7 +3886,7 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
init_samr_r_query_aliasmem(r_u, num_sids, sid, NT_STATUS_OK);
- SAFE_FREE(sids);
+ TALLOC_FREE(sids);
return NT_STATUS_OK;
}
diff --git a/source/rpc_server/srv_srvsvc.c b/source/rpc_server/srv_srvsvc.c
index 0b4eac5cc73..e4f85d0bdb4 100644
--- a/source/rpc_server/srv_srvsvc.c
+++ b/source/rpc_server/srv_srvsvc.c
@@ -6,6 +6,7 @@
* Copyright (C) Paul Ashton 1997,
* Copyright (C) Jeremy Allison 2001,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003.
+ * Copyright (C) Gera;d (Jerry) Carter 2006.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -551,6 +552,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
}
/*******************************************************************
+*******************************************************************/
+
+static BOOL api_srv_net_file_close(pipes_struct *p)
+{
+ SRV_Q_NET_FILE_CLOSE q_u;
+ SRV_R_NET_FILE_CLOSE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* Unmarshall the net file set info from Win9x */
+ if(!srv_io_q_net_file_close("", &q_u, data, 0)) {
+ DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n"));
+ return False;
+ }
+
+ r_u.status = _srv_net_file_close(p, &q_u, &r_u);
+
+ if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
\PIPE\srvsvc commands
********************************************************************/
@@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] =
{ "SRV_NET_DISK_ENUM" , SRV_NET_DISK_ENUM , api_srv_net_disk_enum },
{ "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate },
{ "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc },
- { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc }
+ { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc },
+ { "SRV_NET_FILE_CLOSE" , SRV_NET_FILE_CLOSE , api_srv_net_file_close }
};
void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns )
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 06a8c77098d..d03ab66b50d 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -4,6 +4,7 @@
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Jeremy Allison 2001.
* Copyright (C) Nigel Williams 2001.
+ * Copyright (C) Gerald (Jerry) Carter 2006.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +30,174 @@ extern struct generic_mapping file_generic_mapping;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
+/* Use for enumerating connections, pipes, & files */
+
+struct file_enum_count {
+ TALLOC_CTX *ctx;
+ int count;
+ FILE_INFO_3 *info;
+};
+
+struct sess_file_count {
+ pid_t pid;
+ uid_t uid;
+ int count;
+};
+
+/****************************************************************************
+ Count the entries belonging to a service in the connection db.
+****************************************************************************/
+
+static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p)
+{
+ struct pipe_open_rec prec;
+ struct file_enum_count *fenum = (struct file_enum_count *)p;
+
+ if (dbuf.dsize != sizeof(struct pipe_open_rec))
+ return 0;
+
+ memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec));
+
+ if ( process_exists(prec.pid) ) {
+ FILE_INFO_3 *f;
+ int i = fenum->count;
+ pstring fullpath;
+
+ snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
+
+ f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );
+ if ( !f ) {
+ DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+ return 1;
+ }
+ fenum->info = f;
+
+
+ init_srv_file_info3( &fenum->info[i],
+ (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum),
+ (FILE_READ_DATA|FILE_WRITE_DATA),
+ 0,
+ uidtoname( prec.uid ),
+ fullpath );
+
+ fenum->count++;
+ }
+
+ return 0;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_pipes( TALLOC_CTX *ctx, FILE_INFO_3 **info,
+ uint32 *count, uint32 resume )
+{
+ struct file_enum_count fenum;
+ TDB_CONTEXT *conn_tdb = conn_tdb_ctx();
+
+ if ( !conn_tdb ) {
+ DEBUG(0,("net_enum_pipes: Failed to retrieve the connections tdb handle!\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
+ fenum.ctx = ctx;
+ fenum.count = *count;
+ fenum.info = *info;
+
+ if (tdb_traverse(conn_tdb, pipe_enum_fn, &fenum) == -1) {
+ DEBUG(0,("net_enum_pipes: traverse of connections.tdb failed with error %s.\n",
+ tdb_errorstr(conn_tdb) ));
+ return WERR_NOMEM;
+ }
+
+ *info = fenum.info;
+ *count = fenum.count;
+
+ return WERR_OK;}
+
+/*******************************************************************
+********************************************************************/
+
+/* global needed to make use of the share_mode_forall() callback */
+static struct file_enum_count f_enum_cnt;
+
+static void enum_file_fn( const struct share_mode_entry *e,
+ const char *sharepath, const char *fname, void *state )
+{
+ struct file_enum_count *fenum = &f_enum_cnt;
+
+ /* If the pid was not found delete the entry from connections.tdb */
+
+ if ( process_exists(e->pid) ) {
+ FILE_INFO_3 *f;
+ int i = fenum->count;
+ files_struct fsp;
+ struct byte_range_lock *brl;
+ int num_locks = 0;
+ pstring fullpath;
+ uint32 permissions;
+
+ f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );
+ if ( !f ) {
+ DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+ return;
+ }
+ fenum->info = f;
+
+ /* need to count the number of locks on a file */
+
+ ZERO_STRUCT( fsp );
+ fsp.dev = e->dev;
+ fsp.inode = e->inode;
+
+ if ( (brl = brl_get_locks(NULL,&fsp)) != NULL ) {
+ num_locks = brl->num_locks;
+ TALLOC_FREE( brl );
+ }
+
+ if ( strcmp( fname, "." ) == 0 ) {
+ pstr_sprintf( fullpath, "C:%s", sharepath );
+ } else {
+ pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
+ }
+ string_replace( fullpath, '/', '\\' );
+
+ /* mask out create (what ever that is) */
+ permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
+
+ /* now fill in the FILE_INFO_3 struct */
+ init_srv_file_info3( &fenum->info[i],
+ e->share_file_id,
+ permissions,
+ num_locks,
+ uidtoname(e->uid),
+ fullpath );
+
+ fenum->count++;
+ }
+
+ return;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info,
+ uint32 *count, uint32 resume )
+{
+ f_enum_cnt.ctx = ctx;
+ f_enum_cnt.count = *count;
+ f_enum_cnt.info = *info;
+
+ share_mode_forall( enum_file_fn, NULL );
+
+ *info = f_enum_cnt.info;
+ *count = f_enum_cnt.count;
+
+ return WERR_OK;
+}
+
/*******************************************************************
Utility function to get the 'type' of a share from an snum.
********************************************************************/
@@ -91,8 +260,9 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
pstring passwd;
int max_connections = lp_max_connections(snum);
uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
-
+ int count = 0;
char *net_name = lp_servicename(snum);
+
pstrcpy(remark, lp_comment(snum));
standard_sub_conn(p->conn, remark,sizeof(remark));
pstrcpy(path, "C:");
@@ -107,7 +277,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
pstrcpy(passwd, "");
- init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, max_uses, 1, path, passwd);
+ count = count_current_connections( net_name, False );
+ init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum),
+ remark, 0, max_uses, count, path, passwd);
+
init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
}
@@ -596,16 +769,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
}
/*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
-
-static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name)
-{
- init_srv_sess_info0(se0, name);
- init_srv_sess_info0_str(str0, name);
-}
-
-/*******************************************************************
fill in a sess info level 0 structure.
********************************************************************/
@@ -627,11 +790,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
if (snum) {
for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
- init_srv_sess_0_info(&ss0->info_0[num_entries],
- &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine);
-
- /* move on to creating next session */
- /* move on to creating next sess */
+ init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine);
num_entries++;
}
@@ -652,17 +811,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
}
/*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
+********************************************************************/
+
+/* global needed to make use of the share_mode_forall() callback */
+static struct sess_file_count s_file_cnt;
+
+static void sess_file_fn( const struct share_mode_entry *e,
+ const char *sharepath, const char *fname, void *state )
+{
+ struct sess_file_count *sess = &s_file_cnt;
+
+ if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) {
+ sess->count++;
+ }
+
+ return;
+}
-static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1,
- char *name, char *user,
- uint32 num_opens,
- uint32 open_time, uint32 idle_time,
- uint32 usr_flgs)
+/*******************************************************************
+********************************************************************/
+
+static int net_count_files( uid_t uid, pid_t pid )
{
- init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
- init_srv_sess_info1_str(str1, name, user);
+ s_file_cnt.count = 0;
+ s_file_cnt.uid = uid;
+ s_file_cnt.pid = pid;
+
+ share_mode_forall( sess_file_fn, NULL );
+
+ return s_file_cnt.count;
}
/*******************************************************************
@@ -673,43 +850,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto
{
struct sessionid *session_list;
uint32 num_entries = 0;
- (*stot) = list_sessions(&session_list);
+ time_t now = time(NULL);
+ if ( !snum ) {
+ ss1->num_entries_read = 0;
+ ss1->ptr_sess_info = 0;
+ ss1->num_entries_read2 = 0;
+
+ (*stot) = 0;
+
+ return;
+ }
+
if (ss1 == NULL) {
(*snum) = 0;
- SAFE_FREE(session_list);
return;
}
- DEBUG(5,("init_srv_sess_1_ss1\n"));
-
- if (snum) {
- for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
- init_srv_sess_1_info(&ss1->info_1[num_entries],
- &ss1->info_1_str[num_entries],
- session_list[*snum].remote_machine,
- session_list[*snum].username,
- 1, 10, 5, 0);
-
- /* move on to creating next session */
- /* move on to creating next sess */
- num_entries++;
- }
+ (*stot) = list_sessions(&session_list);
+
- ss1->num_entries_read = num_entries;
- ss1->ptr_sess_info = num_entries > 0 ? 1 : 0;
- ss1->num_entries_read2 = num_entries;
-
- if ((*snum) >= (*stot)) {
- (*snum) = 0;
+ for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
+ uint32 num_files;
+ uint32 connect_time;
+ struct passwd *pw = sys_getpwnam(session_list[*snum].username);
+ BOOL guest;
+
+ if ( !pw ) {
+ DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
+ session_list[*snum].username));
+ continue;
}
-
- } else {
- ss1->num_entries_read = 0;
- ss1->ptr_sess_info = 0;
- ss1->num_entries_read2 = 0;
-
- (*stot) = 0;
+
+ connect_time = (uint32)(now - session_list[*snum].connect_start);
+ num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
+ guest = strequal( session_list[*snum].username, lp_guestaccount() );
+
+ init_srv_sess_info1( &ss1->info_1[num_entries],
+ session_list[*snum].remote_machine,
+ session_list[*snum].username,
+ num_files,
+ connect_time,
+ 0,
+ guest);
+ num_entries++;
+ }
+
+ ss1->num_entries_read = num_entries;
+ ss1->ptr_sess_info = num_entries > 0 ? 1 : 0;
+ ss1->num_entries_read2 = num_entries;
+
+ if ((*snum) >= (*stot)) {
+ (*snum) = 0;
}
SAFE_FREE(session_list);
@@ -929,66 +1121,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
makes a SRV_R_NET_FILE_ENUM structure.
********************************************************************/
-static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
- int switch_value, uint32 *resume_hnd,
- uint32 *total_entries)
+static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd )
{
- WERROR status = WERR_OK;
- TALLOC_CTX *ctx = p->mem_ctx;
- DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
- *total_entries = 1; /* dummy entries only, for */
+ TALLOC_CTX *ctx = get_talloc_ctx();
+ SRV_FILE_INFO_CTR *ctr = &r->ctr;
- ctr->switch_value = switch_value;
- ctr->num_entries = *total_entries - *resume_hnd;
+ /* TODO -- Windows enumerates
+ (b) active pipes
+ (c) open directories and files */
+
+ r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+ if ( !W_ERROR_IS_OK(r->status))
+ goto done;
+
+ r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+ if ( !W_ERROR_IS_OK(r->status))
+ goto done;
+
+ r->level = ctr->level = 3;
+ r->total_entries = ctr->num_entries;
+ /* ctr->num_entries = r->total_entries - resume_hnd; */
ctr->num_entries2 = ctr->num_entries;
+ ctr->ptr_file_info = 1;
- switch (switch_value) {
- case 3: {
- int i;
- if (*total_entries > 0) {
- ctr->ptr_entries = 1;
- ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries);
- }
- for (i=0 ;i<ctr->num_entries;i++) {
- init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user");
- init_srv_file_info3_str(&ctr->file.info3[i].info_3_str, "\\PIPE\\samr", "dummy user");
-
- }
- ctr->ptr_file_info = 1;
- *resume_hnd = 0;
- break;
- }
- default:
- DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value));
- (*resume_hnd = 0);
- (*total_entries) = 0;
- ctr->ptr_entries = 0;
- status = WERR_UNKNOWN_LEVEL;
- break;
- }
+ r->status = WERR_OK;
- return status;
+done:
+ if ( ctr->num_entries > 0 )
+ ctr->ptr_entries = 1;
+
+ init_enum_hnd(&r->enum_hnd, 0);
+
+ return r->status;
}
/*******************************************************************
- makes a SRV_R_NET_FILE_ENUM structure.
-********************************************************************/
+*******************************************************************/
-static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n,
- uint32 resume_hnd, int file_level, int switch_value)
+WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
{
- DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
-
- r_n->file_level = file_level;
- if (file_level == 0)
- r_n->status = WERR_UNKNOWN_LEVEL;
- else
- r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
-
- if (!W_ERROR_IS_OK(r_n->status))
- resume_hnd = 0;
-
- init_enum_hnd(&r_n->enum_hnd, resume_hnd);
+ switch ( q_u->level ) {
+ case 3:
+ return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) );
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ return WERR_OK;
}
/*******************************************************************
@@ -1075,25 +1254,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R
}
/*******************************************************************
-net file enum
-********************************************************************/
-
-WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
-{
- DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
- /* set up the */
- init_srv_r_net_file_enum(p, r_u,
- get_enum_hnd(&q_u->enum_hnd),
- q_u->file_level,
- q_u->ctr.switch_value);
-
- DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
- return r_u->status;
-}
-
-/*******************************************************************
net conn enum
********************************************************************/
@@ -2102,7 +2262,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
switch ( q_u->type ) {
case 0x9:
- rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0);
+ rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0);
if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) {
DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename));
return WERR_INVALID_NAME;
@@ -2115,3 +2275,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
return WERR_OK;
}
+
+
+/********************************************************************
+********************************************************************/
+
+WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u)
+{
+ return WERR_ACCESS_DENIED;
+}
+
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index e2a026c87bf..676d84835de 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -1858,6 +1858,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
if ((argc < 1) || (argc > 3)) {
printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
printf("\tSpecify rid for security on user, -d for security on domain\n");
+ talloc_destroy(ctx);
return NT_STATUS_OK;
}
diff --git a/source/smbd/close.c b/source/smbd/close.c
index b826cd622af..a123a542fd2 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -373,9 +373,9 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
* Ensure pending modtime is set after close.
*/
- if(fsp->pending_modtime && fsp->pending_modtime_owner) {
+ if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
- } else if (fsp->last_write_time) {
+ } else if (!null_timespec(fsp->last_write_time)) {
set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
}
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index 2795b2a24b2..db3e155ae47 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -1017,6 +1017,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
}
if (hide_unreadable || hide_unwriteable || hide_special) {
+ pstring link_target;
char *entry = NULL;
if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
@@ -1026,10 +1027,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
/* If it's a dfs symlink, ignore _hide xxxx_ options */
if (lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
- /* We get away with NULL talloc ctx here as
- we're not interested in the link contents
- so we have nothing to free. */
- is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) {
+ is_msdfs_link(conn, entry, link_target, NULL)) {
SAFE_FREE(entry);
return True;
}
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index ad79bbacddf..71d4fa179d4 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -282,7 +282,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
}
/* We want DOS semantics, ie allow non owner with write permission to change the
- bits on a file. Just like file_utime below.
+ bits on a file. Just like file_ntimes below.
*/
/* Check if we have write access. */
@@ -504,7 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
return -1;
/* We want DOS semantics, ie allow non owner with write permission to change the
- bits on a file. Just like file_utime below.
+ bits on a file. Just like file_ntimes below.
*/
/* Check if we have write access. */
@@ -532,11 +532,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
}
/*******************************************************************
- Wrapper around dos_utime that possibly allows DOS semantics rather
+ Wrapper around the VFS ntimes that possibly allows DOS semantics rather
than POSIX.
*******************************************************************/
-int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times)
+int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
{
SMB_STRUCT_STAT sbuf;
int ret = -1;
@@ -555,14 +555,17 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
return 0;
}
- if(SMB_VFS_UTIME(conn,fname, times) == 0)
+ if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
return 0;
+ }
- if((errno != EPERM) && (errno != EACCES))
+ if((errno != EPERM) && (errno != EACCES)) {
return -1;
+ }
- if(!lp_dos_filetimes(SNUM(conn)))
+ if(!lp_dos_filetimes(SNUM(conn))) {
return -1;
+ }
/* We have permission (given by the Samba admin) to
break POSIX semantics and allow a user to change
@@ -574,7 +577,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
if (can_write_to_file(conn, fname, &sbuf)) {
/* We are allowed to become root and change the filetime. */
become_root();
- ret = SMB_VFS_UTIME(conn,fname, times);
+ ret = SMB_VFS_NTIMES(conn, fname, ts);
unbecome_root();
}
@@ -585,16 +588,19 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
-BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
+BOOL set_filetime(connection_struct *conn, const char *fname,
+ const struct timespec mtime)
{
- struct utimbuf times;
+ struct timespec ts[2];
- if (null_mtime(mtime))
+ if (null_timespec(mtime)) {
return(True);
+ }
- times.modtime = times.actime = mtime;
+ ts[1] = mtime; /* mtime. */
+ ts[0] = ts[1]; /* atime. */
- if (file_utime(conn, fname, &times)) {
+ if (file_ntimes(conn, fname, ts)) {
DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
return False;
}
@@ -602,5 +608,5 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
- return(True);
-}
+ return True;
+}
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index e0945be8893..65238c0e9ee 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -149,13 +149,13 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos
* The 99% solution will hopefully be good enough in this case. JRA.
*/
- if (fsp->pending_modtime) {
+ if (!null_timespec(fsp->pending_modtime)) {
set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime);
/* If we didn't get the "set modtime" call ourselves, we must
store the last write time to restore on close. JRA. */
if (!fsp->pending_modtime_owner) {
- fsp->last_write_time = time(NULL);
+ fsp->last_write_time = timespec_current();
}
}
diff --git a/source/smbd/files.c b/source/smbd/files.c
index 66ef37bb0fa..23fd47671b8 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -383,11 +383,11 @@ files_struct *file_find_print(void)
Record the owner of that modtime.
****************************************************************************/
-void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
+void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod)
{
files_struct *fsp;
- if (null_mtime(pmod)) {
+ if (null_timespec(mod)) {
return;
}
@@ -395,7 +395,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
if ( fsp->fh->fd != -1 &&
fsp->dev == tfsp->dev &&
fsp->inode == tfsp->inode ) {
- fsp->pending_modtime = pmod;
+ fsp->pending_modtime = mod;
fsp->pending_modtime_owner = False;
}
}
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 2a19d6fb418..284061331bf 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -1,8 +1,9 @@
/*
Unix SMB/Netbios implementation.
Version 3.0
- MSDfs services for Samba
+ MSDFS services for Samba
Copyright (C) Shirish Kalele 2000
+ Copyright (C) Jeremy Allison 2007
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
@@ -26,108 +27,142 @@
extern uint32 global_client_caps;
/**********************************************************************
- Parse the pathname of the form \hostname\service\reqpath
- into the dfs_path structure
- **********************************************************************/
+ Parse a DFS pathname of the form \hostname\service\reqpath
+ into the dfs_path structure.
+ If POSIX pathnames is true, the pathname may also be of the
+ form /hostname/service/reqpath.
+ We cope with either here.
+
+ Unfortunately, due to broken clients who might set the
+ SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then
+ send a local path, we have to cope with that too....
-static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp)
+ JRA.
+**********************************************************************/
+
+static NTSTATUS parse_dfs_path(const char *pathname,
+ BOOL allow_wcards,
+ struct dfs_path *pdp,
+ BOOL *ppath_contains_wcard)
{
pstring pathname_local;
- char *p, *temp;
+ char *p,*temp;
+ NTSTATUS status = NT_STATUS_OK;
+ char sepchar;
+
+ ZERO_STRUCTP(pdp);
pstrcpy(pathname_local,pathname);
p = temp = pathname_local;
- ZERO_STRUCTP(pdp);
+ pdp->posix_path = (lp_posix_pathnames() && *pathname == '/');
- trim_char(temp,'\\','\\');
- DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp));
+ sepchar = pdp->posix_path ? '/' : '\\';
- /* now tokenize */
- /* parse out hostname */
- p = strchr_m(temp,'\\');
- if(p == NULL) {
- return False;
- }
- *p = '\0';
- pstrcpy(pdp->hostname,temp);
- DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname));
+ if (*pathname != sepchar) {
+ DEBUG(10,("parse_dfs_path: path %s doesn't start with %c\n",
+ pathname, sepchar ));
+ /*
+ * Possibly client sent a local path by mistake.
+ * Try and convert to a local path.
+ */
- /* parse out servicename */
- temp = p+1;
- p = strchr_m(temp,'\\');
- if(p == NULL) {
- pstrcpy(pdp->servicename,temp);
- pdp->reqpath[0] = '\0';
- return True;
+ pdp->hostname[0] = '\0';
+ pdp->servicename[0] = '\0';
+
+ /* We've got no info about separators. */
+ pdp->posix_path = lp_posix_pathnames();
+ p = temp;
+ DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+ temp));
+ goto local_path;
}
- *p = '\0';
- pstrcpy(pdp->servicename,temp);
- DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
- /* rest is reqpath */
- check_path_syntax(pdp->reqpath, p+1);
+ trim_char(temp,sepchar,sepchar);
- DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
- return True;
-}
+ DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n",
+ temp, sepchar));
-/**********************************************************************
- Parse the pathname of the form /hostname/service/reqpath
- into the dfs_path structure
- This code is dependent on the fact that check_path_syntax() will
- convert '\\' characters to '/'.
- When POSIX pathnames have been selected this doesn't happen, so we
- must look for the unaltered separator of '\\' instead of the modified '/'.
- JRA.
- **********************************************************************/
+ /* Now tokenize. */
+ /* Parse out hostname. */
+ p = strchr_m(temp,sepchar);
+ if(p == NULL) {
+ DEBUG(10,("parse_dfs_path: can't parse hostname from path %s\n",
+ temp));
+ /*
+ * Possibly client sent a local path by mistake.
+ * Try and convert to a local path.
+ */
-static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards)
-{
- pstring pathname_local;
- char *p,*temp;
- const char sepchar = lp_posix_pathnames() ? '\\' : '/';
+ pdp->hostname[0] = '\0';
+ pdp->servicename[0] = '\0';
- pstrcpy(pathname_local,pathname);
- p = temp = pathname_local;
+ p = temp;
+ DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+ temp));
+ goto local_path;
+ }
+ *p = '\0';
+ fstrcpy(pdp->hostname,temp);
+ DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname));
- ZERO_STRUCTP(pdp);
+ /* If we got a hostname, is it ours (or an IP address) ? */
+ if (!is_myname_or_ipaddr(pdp->hostname)) {
+ /* Repair path. */
+ *p = sepchar;
+ DEBUG(10,("parse_dfs_path: hostname %s isn't ours. Try local path from path %s\n",
+ pdp->hostname, temp));
+ /*
+ * Possibly client sent a local path by mistake.
+ * Try and convert to a local path.
+ */
- trim_char(temp,sepchar,sepchar);
- DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp));
+ pdp->hostname[0] = '\0';
+ pdp->servicename[0] = '\0';
- /* now tokenize */
- /* parse out hostname */
- p = strchr_m(temp,sepchar);
- if(p == NULL) {
- return False;
+ p = temp;
+ DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+ temp));
+ goto local_path;
}
- *p = '\0';
- pstrcpy(pdp->hostname,temp);
- DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname));
- /* parse out servicename */
+ /* Parse out servicename. */
temp = p+1;
p = strchr_m(temp,sepchar);
if(p == NULL) {
- pstrcpy(pdp->servicename,temp);
+ fstrcpy(pdp->servicename,temp);
pdp->reqpath[0] = '\0';
- return True;
+ return NT_STATUS_OK;
}
*p = '\0';
- pstrcpy(pdp->servicename,temp);
- DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename));
+ fstrcpy(pdp->servicename,temp);
+ DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
+
+ p++;
+
+ local_path:
+
+ *ppath_contains_wcard = False;
- /* rest is reqpath */
- if (allow_wcards) {
- BOOL path_contains_wcard;
- check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard);
+ /* Rest is reqpath. */
+ if (pdp->posix_path) {
+ status = check_path_syntax_posix(pdp->reqpath, p);
} else {
- check_path_syntax(pdp->reqpath, p+1);
+ if (allow_wcards) {
+ status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard);
+ } else {
+ status = check_path_syntax(pdp->reqpath, p);
+ }
}
- DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath));
- return True;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("parse_dfs_path: '%s' failed with %s\n",
+ p, nt_errstr(status) ));
+ return status;
+ }
+
+ DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
+ return NT_STATUS_OK;
}
/********************************************************
@@ -135,7 +170,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL
Note this CHANGES CWD !!!! JRA.
*********************************************************/
-static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
+static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path)
{
pstring connpath;
@@ -145,19 +180,19 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
pstring_sub(connpath , "%S", lp_servicename(snum));
/* needed for smbd_vfs_init() */
-
- if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) {
- DEBUG(0,("talloc_init(connection_struct) failed!\n"));
- return False;
- }
- if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) {
+ if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) {
+ DEBUG(0,("talloc_init(connection_struct) failed!\n"));
+ return False;
+ }
+
+ if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) {
DEBUG(0, ("TALLOC failed\n"));
return False;
}
-
+
conn->params->service = snum;
-
+
set_conn_connectpath(conn, connpath);
if (!smbd_vfs_init(conn)) {
@@ -184,11 +219,27 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
/**********************************************************************
Parse the contents of a symlink to verify if it is an msdfs referral
- A valid referral is of the form: msdfs:server1\share1,server2\share2
- talloc CTX can be NULL here if preflist and refcount pointers are null.
+ A valid referral is of the form:
+
+ msdfs:server1\share1,server2\share2
+ msdfs:server1\share1\pathname,server2\share2\pathname
+ msdfs:server1/share1,server2/share2
+ msdfs:server1/share1/pathname,server2/share2/pathname.
+
+ Note that the alternate paths returned here must be of the canonicalized
+ form:
+
+ \server\share or
+ \server\share\path\to\file,
+
+ even in posix path mode. This is because we have no knowledge if the
+ server we're referring to understands posix paths.
**********************************************************************/
-static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount)
+static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx,
+ char *target,
+ struct referral **preflist,
+ int *refcount)
{
pstring temp;
char *prot;
@@ -196,45 +247,28 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist
int count = 0, i;
struct referral *reflist;
- pstrcpy(temp,buf);
-
+ pstrcpy(temp,target);
prot = strtok(temp,":");
- if (!strequal(prot, "msdfs")) {
- return False;
- }
-
- /* No referral list requested. Just yes/no. */
- if (!preflist) {
- return True;
- }
-
- if (!ctx) {
- DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n"));
- return True;
- }
-
/* parse out the alternate paths */
while((count<MAX_REFERRAL_COUNT) &&
((alt_path[count] = strtok(NULL,",")) != NULL)) {
count++;
}
- DEBUG(10,("parse_symlink: count=%d\n", count));
+ DEBUG(10,("parse_msdfs_symlink: count=%d\n", count));
- reflist = *preflist = TALLOC_ARRAY(ctx, struct referral, count);
+ reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count);
if(reflist == NULL) {
- DEBUG(0,("parse_symlink: talloc failed!\n"));
+ DEBUG(0,("parse_msdfs_symlink: talloc failed!\n"));
return False;
}
for(i=0;i<count;i++) {
char *p;
- /* replace all /'s in the alternate path by a \ */
- for(p = alt_path[i]; *p && ((p = strchr_m(p,'/'))!=NULL); p++) {
- *p = '\\';
- }
+ /* Canonicalize link target. Replace all /'s in the path by a \ */
+ string_replace(alt_path[i], '/', '\\');
/* Remove leading '\\'s */
p = alt_path[i];
@@ -244,35 +278,29 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist
pstrcpy(reflist[i].alternate_path, "\\");
pstrcat(reflist[i].alternate_path, p);
+
reflist[i].proximity = 0;
reflist[i].ttl = REFERRAL_TTL;
- DEBUG(10, ("parse_symlink: Created alt path: %s\n", reflist[i].alternate_path));
- }
-
- if(refcount) {
- *refcount = count;
+ DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", reflist[i].alternate_path));
+ *refcount += 1;
}
return True;
}
/**********************************************************************
- Returns true if the unix path is a valid msdfs symlink
- talloc CTX can be NULL here if reflistp and refcnt pointers are null.
- **********************************************************************/
+ Returns true if the unix path is a valid msdfs symlink and also
+ returns the target string from inside the link.
+**********************************************************************/
-BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path,
- struct referral **reflistp, int *refcnt,
- SMB_STRUCT_STAT *sbufp)
+BOOL is_msdfs_link(connection_struct *conn,
+ const char *path,
+ pstring link_target,
+ SMB_STRUCT_STAT *sbufp)
{
SMB_STRUCT_STAT st;
- pstring referral;
int referral_len = 0;
- if (!path || !conn) {
- return False;
- }
-
if (sbufp == NULL) {
sbufp = &st;
}
@@ -282,76 +310,59 @@ BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path,
return False;
}
- if (S_ISLNK(sbufp->st_mode)) {
- /* open the link and read it */
- referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1);
- if (referral_len == -1) {
- DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno)));
- return False;
- }
+ if (!S_ISLNK(sbufp->st_mode)) {
+ DEBUG(5,("is_msdfs_link: %s is not a link.\n",path));
+ return False;
+ }
- referral[referral_len] = '\0';
- DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral));
- if (parse_symlink(ctx, referral, reflistp, refcnt)) {
- return True;
- }
+ /* open the link and read it */
+ referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1);
+ if (referral_len == -1) {
+ DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n",
+ path, strerror(errno)));
+ return False;
+ }
+ link_target[referral_len] = '\0';
+
+ DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target));
+
+ if (!strnequal(link_target, "msdfs:", 6)) {
+ return False;
}
- return False;
+ return True;
}
/*****************************************************************
Used by other functions to decide if a dfs path is remote,
-and to get the list of referred locations for that remote path.
+ and to get the list of referred locations for that remote path.
-findfirst_flag: For findfirsts, dfs links themselves are not
-redirected, but paths beyond the links are. For normal smb calls,
-even dfs links need to be redirected.
+ search_flag: For findfirsts, dfs links themselves are not
+ redirected, but paths beyond the links are. For normal smb calls,
+ even dfs links need to be redirected.
-self_referralp: clients expect a dfs referral for the same share when
-they request referrals for dfs roots on a server.
+ consumedcntp: how much of the dfs path is being redirected. the client
+ should try the remaining path on the redirected server.
-consumedcntp: how much of the dfs path is being redirected. the client
-should try the remaining path on the redirected server.
-
-TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp
-are also NULL.
+ If this returns NT_STATUS_PATH_NOT_COVERED the contents of the msdfs
+ link redirect are in targetpath.
*****************************************************************/
-static BOOL resolve_dfs_path(TALLOC_CTX *ctx,
- const char *dfspath,
- struct dfs_path *dp,
- connection_struct *conn,
- BOOL search_flag,
- struct referral **reflistpp,
- int *refcntp,
- BOOL *self_referralp,
- int *consumedcntp)
+static NTSTATUS dfs_path_lookup(connection_struct *conn,
+ const char *dfspath, /* Incoming complete dfs path */
+ const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */
+ BOOL search_flag, /* Called from a findfirst ? */
+ int *consumedcntp,
+ pstring targetpath)
{
- pstring localpath;
- int consumed_level = 1;
- char *p;
+ char *p = NULL;
+ char *q = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
- pstring reqpath;
-
- if (!dp || !conn) {
- DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n"));
- return False;
- }
-
- if (!ctx && (reflistpp || refcntp)) {
- DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n"));
- }
-
- if (dp->reqpath[0] == '\0') {
- if (self_referralp) {
- DEBUG(6,("resolve_dfs_path: self-referral. returning False\n"));
- *self_referralp = True;
- }
- return False;
- }
+ pstring localpath;
+ pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */
- DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath));
+ DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n",
+ conn->connectpath, pdp->reqpath));
/*
* Note the unix path conversion here we're doing we can
@@ -365,144 +376,189 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx,
* think this is needed. JRA.
*/
- pstrcpy(localpath, dp->reqpath);
-
- status = unix_convert(conn, localpath, False, NULL, &sbuf);
+ pstrcpy(localpath, pdp->reqpath);
+ status = unix_convert(conn, localpath, search_flag, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- return False;
+ return status;
}
- /* check if need to redirect */
- if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) {
- if ( search_flag ) {
- DEBUG(6,("resolve_dfs_path (FindFirst) No redirection "
+ /* Optimization - check if we can redirect the whole path. */
+
+ if (is_msdfs_link(conn, localpath, targetpath, NULL)) {
+ if (search_flag) {
+ DEBUG(6,("dfs_path_lookup (FindFirst) No redirection "
"for dfs link %s.\n", dfspath));
- return False;
+ return NT_STATUS_OK;
}
- DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath));
+ DEBUG(6,("dfs_path_lookup: %s resolves to a "
+ "valid dfs link %s.\n", dfspath, targetpath));
+
if (consumedcntp) {
*consumedcntp = strlen(dfspath);
}
- return True;
+ return NT_STATUS_PATH_NOT_COVERED;
+ }
+
+ /* Prepare to test only for '/' components in the given path,
+ * so if a Windows path replace all '\\' characters with '/'.
+ * For a POSIX DFS path we know all separators are already '/'. */
+
+ pstrcpy(canon_dfspath, dfspath);
+ if (!pdp->posix_path) {
+ string_replace(canon_dfspath, '\\', '/');
+ }
+
+ /*
+ * Redirect if any component in the path is a link.
+ * We do this by walking backwards through the
+ * local path, chopping off the last component
+ * in both the local path and the canonicalized
+ * DFS path. If we hit a DFS link then we're done.
+ */
+
+ p = strrchr_m(localpath, '/');
+ if (consumedcntp) {
+ q = strrchr_m(canon_dfspath, '/');
}
- /* redirect if any component in the path is a link */
- pstrcpy(reqpath, localpath);
- p = strrchr_m(reqpath, '/');
while (p) {
*p = '\0';
- pstrcpy(localpath, reqpath);
- if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) {
- DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath));
-
- /* To find the path consumed, we truncate the original
- DFS pathname passed to use to remove the last
- component. The length of the resulting string is
- the path consumed
- */
-
+ if (q) {
+ *q = '\0';
+ }
+
+ if (is_msdfs_link(conn, localpath, targetpath, NULL)) {
+ DEBUG(4, ("dfs_path_lookup: Redirecting %s because "
+ "parent %s is dfs link\n", dfspath, localpath));
+
if (consumedcntp) {
- char *q;
- pstring buf;
- pstrcpy(buf, dfspath);
- trim_char(buf, '\0', '\\');
- for (; consumed_level; consumed_level--) {
- q = strrchr_m(buf, '\\');
- if (q) {
- *q = 0;
- }
- }
- *consumedcntp = strlen(buf);
- DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp));
+ *consumedcntp = strlen(canon_dfspath);
+ DEBUG(10, ("dfs_path_lookup: Path consumed: %s "
+ "(%d)\n", canon_dfspath, *consumedcntp));
}
-
- return True;
+
+ return NT_STATUS_PATH_NOT_COVERED;
+ }
+
+ /* Step back on the filesystem. */
+ p = strrchr_m(localpath, '/');
+
+ if (consumedcntp) {
+ /* And in the canonicalized dfs path. */
+ q = strrchr_m(canon_dfspath, '/');
}
- p = strrchr_m(reqpath, '/');
- consumed_level++;
}
- return False;
+ return NT_STATUS_OK;
}
/*****************************************************************
- Decides if a dfs pathname should be redirected or not.
- If not, the pathname is converted to a tcon-relative local unix path
-
- search_wcard_flag: this flag performs 2 functions bother related
- to searches. See resolve_dfs_path() and parse_processed_dfs_path()
- for details.
+ Decides if a dfs pathname should be redirected or not.
+ If not, the pathname is converted to a tcon-relative local unix path
+
+ search_wcard_flag: this flag performs 2 functions bother related
+ to searches. See resolve_dfs_path() and parse_dfs_path_XX()
+ for details.
+
+ This function can return NT_STATUS_OK, meaning use the returned path as-is
+ (mapped into a local path).
+ or NT_STATUS_NOT_COVERED meaning return a DFS redirect, or
+ any other NT_STATUS error which is a genuine error to be
+ returned to the client.
*****************************************************************/
-BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag )
+static NTSTATUS dfs_redirect( connection_struct *conn,
+ pstring dfs_path,
+ BOOL search_wcard_flag,
+ BOOL *ppath_contains_wcard)
{
+ NTSTATUS status;
struct dfs_path dp;
+ pstring targetpath;
- if (!conn || !pathname) {
- return False;
+ status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (dp.reqpath[0] == '\0') {
+ pstrcpy(dfs_path, dp.reqpath);
+ DEBUG(5,("dfs_redirect: self-referral.\n"));
+ return NT_STATUS_OK;
}
- parse_processed_dfs_path(pathname, &dp, search_wcard_flag);
+ /* If dfs pathname for a non-dfs share, convert to tcon-relative
+ path and return OK */
- /* if dfs pathname for a non-dfs share, convert to tcon-relative
- path and return false */
if (!lp_msdfs_root(SNUM(conn))) {
- pstrcpy(pathname, dp.reqpath);
- return False;
+ pstrcpy(dfs_path, dp.reqpath);
+ return NT_STATUS_OK;
}
-
- if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn)))
- || ( strequal(dp.servicename, HOMES_NAME)
- && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) )
- {
- return False;
+
+ /* If it looked like a local path (zero hostname/servicename)
+ * just treat as a tcon-relative path. */
+
+ if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') {
+ pstrcpy(dfs_path, dp.reqpath);
+ return NT_STATUS_OK;
}
- if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag,
- NULL, NULL, NULL, NULL)) {
- DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname));
- return True;
- } else {
- DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname));
+ if (!( strequal(dp.servicename, lp_servicename(SNUM(conn)))
+ || (strequal(dp.servicename, HOMES_NAME)
+ && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) {
- /* Form non-dfs tcon-relative path */
- pstrcpy(pathname, dp.reqpath);
+ /* The given sharename doesn't match this connection. */
- DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname));
- return False;
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ status = dfs_path_lookup(conn, dfs_path, &dp,
+ search_wcard_flag, NULL, targetpath);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
+ DEBUG(3,("dfs_redirect: Redirecting %s\n", dfs_path));
+ } else {
+ DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n",
+ dfs_path, nt_errstr(status) ));
+ }
+ return status;
}
- /* never reached */
+ DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path));
+
+ /* Form non-dfs tcon-relative path */
+ pstrcpy(dfs_path, dp.reqpath);
+
+ DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path));
+ return NT_STATUS_OK;
}
/**********************************************************************
Return a self referral.
**********************************************************************/
-static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
- int *consumedcntp, BOOL *self_referralp)
+static BOOL self_ref(TALLOC_CTX *ctx,
+ const char *dfs_path,
+ struct junction_map *jucn,
+ int *consumedcntp,
+ BOOL *self_referralp)
{
struct referral *ref;
- if (self_referralp != NULL) {
- *self_referralp = True;
- }
+ *self_referralp = True;
jucn->referral_count = 1;
- if((ref = TALLOC_P(ctx, struct referral)) == NULL) {
- DEBUG(0,("self_ref: malloc failed for referral\n"));
+ if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
+ DEBUG(0,("self_ref: talloc failed for referral\n"));
return False;
}
- pstrcpy(ref->alternate_path,pathname);
+ pstrcpy(ref->alternate_path,dfs_path);
ref->proximity = 0;
ref->ttl = REFERRAL_TTL;
jucn->referral_list = ref;
- if (consumedcntp) {
- *consumedcntp = strlen(pathname);
- }
-
+ *consumedcntp = strlen(dfs_path);
return True;
}
@@ -511,40 +567,39 @@ static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map
junction_map structure.
**********************************************************************/
-BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
- int *consumedcntp, BOOL *self_referralp)
+BOOL get_referred_path(TALLOC_CTX *ctx,
+ const char *dfs_path,
+ struct junction_map *jucn,
+ int *consumedcntp,
+ BOOL *self_referralp)
{
- struct dfs_path dp;
-
struct connection_struct conns;
struct connection_struct *conn = &conns;
+ struct dfs_path dp;
pstring conn_path;
+ pstring targetpath;
int snum;
+ NTSTATUS status;
BOOL ret = False;
- BOOL self_referral = False;
-
- if (!pathname || !jucn) {
- return False;
- }
+ BOOL dummy;
ZERO_STRUCT(conns);
- if (self_referralp) {
- *self_referralp = False;
- } else {
- self_referralp = &self_referral;
- }
+ *self_referralp = False;
- parse_dfs_path(pathname, &dp);
+ status = parse_dfs_path(dfs_path, False, &dp, &dummy);
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
/* Verify hostname in path */
if (!is_myname_or_ipaddr(dp.hostname)) {
DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n",
- dp.hostname, pathname));
+ dp.hostname, dfs_path));
return False;
}
- pstrcpy(jucn->service_name, dp.servicename);
+ fstrcpy(jucn->service_name, dp.servicename);
pstrcpy(jucn->volume_name, dp.reqpath);
/* Verify the share is a dfs root */
@@ -556,8 +611,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
}
if (!lp_msdfs_root(snum)) {
- DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n",
- dp.servicename, pathname));
+ DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n",
+ dp.servicename, dfs_path));
goto out;
}
@@ -569,15 +624,23 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
*/
if (dp.reqpath[0] == '\0') {
-
- struct referral* ref;
+ struct referral *ref;
if (*lp_msdfs_proxy(snum) == '\0') {
- return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp);
+ return self_ref(ctx,
+ dfs_path,
+ jucn,
+ consumedcntp,
+ self_referralp);
}
+ /*
+ * It's an msdfs proxy share. Redirect to
+ * the configured target share.
+ */
+
jucn->referral_count = 1;
- if ((ref = TALLOC_P(ctx, struct referral)) == NULL) {
+ if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
DEBUG(0, ("malloc failed for referral\n"));
goto out;
}
@@ -589,9 +652,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
ref->proximity = 0;
ref->ttl = REFERRAL_TTL;
jucn->referral_list = ref;
- if (consumedcntp) {
- *consumedcntp = strlen(pathname);
- }
+ *consumedcntp = strlen(dfs_path);
ret = True;
goto out;
}
@@ -601,23 +662,27 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
return False;
}
- /* If not remote & not a self referral, return False */
- if (!resolve_dfs_path(ctx, pathname, &dp, conn, False,
- &jucn->referral_list, &jucn->referral_count,
- self_referralp, consumedcntp)) {
- if (!*self_referralp) {
- DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname));
- goto out;
- }
+ /* If this is a DFS path dfs_lookup should return
+ * NT_STATUS_PATH_NOT_COVERED. */
+
+ status = dfs_path_lookup(conn, dfs_path, &dp,
+ False, consumedcntp, targetpath);
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
+ DEBUG(3,("get_referred_path: No valid referrals for path %s\n",
+ dfs_path));
+ goto out;
}
-
- /* if self_referral, fill up the junction map */
- if (*self_referralp) {
- if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) {
- goto out;
- }
+
+ /* We know this is a valid dfs link. Parse the targetpath. */
+ if (!parse_msdfs_symlink(ctx, targetpath,
+ &jucn->referral_list,
+ &jucn->referral_count)) {
+ DEBUG(3,("get_referred_path: failed to parse symlink "
+ "target %s\n", targetpath ));
+ goto out;
}
-
+
ret = True;
out:
@@ -626,10 +691,11 @@ out:
return ret;
}
-static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
- struct junction_map *junction,
- int consumedcnt,
- BOOL self_referral)
+static int setup_ver2_dfs_referral(const char *pathname,
+ char **ppdata,
+ struct junction_map *junction,
+ int consumedcnt,
+ BOOL self_referral)
{
char* pdata = *ppdata;
@@ -641,7 +707,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
int reply_size = 0;
int i=0;
- DEBUG(10,("setting up version2 referral\nRequested path:\n"));
+ DEBUG(10,("Setting up version2 referral\nRequested path:\n"));
requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring),
STR_TERMINATE);
@@ -675,7 +741,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
pdata = (char *)SMB_REALLOC(pdata,reply_size);
if(pdata == NULL) {
- DEBUG(0,("malloc failed for Realloc!\n"));
+ DEBUG(0,("Realloc failed!\n"));
return -1;
}
*ppdata = pdata;
@@ -726,10 +792,11 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
return reply_size;
}
-static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
- struct junction_map *junction,
- int consumedcnt,
- BOOL self_referral)
+static int setup_ver3_dfs_referral(const char *pathname,
+ char **ppdata,
+ struct junction_map *junction,
+ int consumedcnt,
+ BOOL self_referral)
{
char* pdata = *ppdata;
@@ -810,17 +877,23 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
}
/******************************************************************
- Set up the Dfs referral for the dfs pathname
+ Set up the DFS referral for the dfs pathname. This call returns
+ the amount of the path covered by this server, and where the
+ client should be redirected to. This is the meat of the
+ TRANS2_GET_DFS_REFERRAL call.
******************************************************************/
-int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata)
+int setup_dfs_referral(connection_struct *orig_conn,
+ const char *dfs_path,
+ int max_referral_level,
+ char **ppdata)
{
struct junction_map junction;
- int consumedcnt;
+ int consumedcnt = 0;
BOOL self_referral = False;
- pstring buf;
int reply_size = 0;
- char *pathnamep = pathname;
+ char *pathnamep = NULL;
+ pstring local_dfs_path;
TALLOC_CTX *ctx;
if (!(ctx=talloc_init("setup_dfs_referral"))) {
@@ -830,21 +903,24 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref
ZERO_STRUCT(junction);
/* get the junction entry */
- if (!pathnamep) {
+ if (!dfs_path) {
talloc_destroy(ctx);
return -1;
}
- /* Trim pathname sent by client so it begins with only one backslash.
- Two backslashes confuse some dfs clients
+ /*
+ * Trim pathname sent by client so it begins with only one backslash.
+ * Two backslashes confuse some dfs clients
*/
- while (pathnamep[0] == '\\' && pathnamep[1] == '\\') {
+
+ pstrcpy(local_dfs_path, dfs_path);
+ pathnamep = local_dfs_path;
+ while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) {
pathnamep++;
}
- pstrcpy(buf, pathnamep);
/* The following call can change cwd. */
- if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) {
+ if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) {
vfs_ChDir(orig_conn,orig_conn->connectpath);
talloc_destroy(ctx);
return -1;
@@ -902,31 +978,40 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref
**********************************************************************/
/*********************************************************************
- Creates a junction structure from a Dfs pathname
+ Creates a junction structure from a DFS pathname
**********************************************************************/
-BOOL create_junction(const char *pathname, struct junction_map *jucn)
+BOOL create_junction(const char *dfs_path, struct junction_map *jucn)
{
- struct dfs_path dp;
+ int snum;
+ BOOL dummy;
+ struct dfs_path dp;
- parse_dfs_path(pathname,&dp);
+ NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return False;
+ }
- /* check if path is dfs : validate first token */
+ /* check if path is dfs : validate first token */
if (!is_myname_or_ipaddr(dp.hostname)) {
DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n",
- dp.hostname, pathname));
+ dp.hostname, dfs_path));
return False;
}
/* Check for a non-DFS share */
- if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) {
- DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename));
+ snum = lp_servicenumber(dp.servicename);
+
+ if(snum < 0 || !lp_msdfs_root(snum)) {
+ DEBUG(4,("create_junction: %s is not an msdfs root.\n",
+ dp.servicename));
return False;
}
- pstrcpy(jucn->service_name,dp.servicename);
+ fstrcpy(jucn->service_name,dp.servicename);
pstrcpy(jucn->volume_name,dp.reqpath);
- pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename)));
+ pstrcpy(jucn->comment, lp_comment(snum));
return True;
}
@@ -934,16 +1019,14 @@ BOOL create_junction(const char *pathname, struct junction_map *jucn)
Forms a valid Unix pathname from the junction
**********************************************************************/
-static BOOL junction_to_local_path(struct junction_map *jucn, char *path,
- int max_pathlen, connection_struct *conn)
+static BOOL junction_to_local_path(struct junction_map *jucn,
+ char *path,
+ int max_pathlen,
+ connection_struct *conn_out)
{
int snum;
pstring conn_path;
- if(!path || !jucn) {
- return False;
- }
-
snum = lp_servicenumber(jucn->service_name);
if(snum < 0) {
return False;
@@ -954,7 +1037,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, char *path,
safe_strcat(path, jucn->volume_name, max_pathlen-1);
pstrcpy(conn_path, lp_pathname(snum));
- if (!create_conn_struct(conn, snum, conn_path)) {
+ if (!create_conn_struct(conn_out, snum, conn_path)) {
return False;
}
@@ -977,11 +1060,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
return False;
}
- /* form the msdfs_link contents */
+ /* Form the msdfs_link contents */
pstrcpy(msdfs_link, "msdfs:");
for(i=0; i<jucn->referral_count; i++) {
char* refpath = jucn->referral_list[i].alternate_path;
+ /* Alternate paths always use Windows separators. */
trim_char(refpath, '\\', '\\');
if(*refpath == '\0') {
if (i == 0) {
@@ -999,7 +1083,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
}
}
- DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link));
+ DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n",
+ path, msdfs_link));
if(exists) {
if(SMB_VFS_UNLINK(conn,path)!=0) {
@@ -1015,7 +1100,7 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
ret = True;
-
+
out:
conn_free_internal(conn);
@@ -1042,13 +1127,16 @@ BOOL remove_msdfs_link(struct junction_map *jucn)
return ret;
}
-static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain)
+static int form_junctions(TALLOC_CTX *ctx,
+ int snum,
+ struct junction_map *jucn,
+ int jn_remain)
{
int cnt = 0;
SMB_STRUCT_DIR *dirp;
- char* dname;
+ char *dname;
pstring connect_path;
- char* service_name = lp_servicename(snum);
+ char *service_name = lp_servicename(snum);
connection_struct conn;
struct referral *ref = NULL;
@@ -1076,13 +1164,13 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
DO NOT REMOVE THIS: NT clients will not work with us
if this is not present
*/
- pstrcpy(jucn[cnt].service_name, service_name);
+ fstrcpy(jucn[cnt].service_name, service_name);
jucn[cnt].volume_name[0] = '\0';
jucn[cnt].referral_count = 1;
- ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral);
+ ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral);
if (jucn[cnt].referral_list == NULL) {
- DEBUG(0, ("Malloc failed!\n"));
+ DEBUG(0, ("talloc failed!\n"));
goto out;
}
@@ -1093,9 +1181,10 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
cnt++;
goto out;
}
-
- slprintf(ref->alternate_path, sizeof(pstring)-1,
- "\\\\%s\\%s", get_local_machine_name(), service_name);
+
+ pstr_sprintf(ref->alternate_path, "\\\\%s\\%s",
+ get_local_machine_name(),
+ service_name);
cnt++;
/* Now enumerate all dfs links */
@@ -1105,16 +1194,22 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
}
while ((dname = vfs_readdirname(&conn, dirp)) != NULL) {
+ pstring link_target;
if (cnt >= jn_remain) {
SMB_VFS_CLOSEDIR(&conn,dirp);
DEBUG(2, ("ran out of MSDFS junction slots"));
goto out;
}
- if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list,
- &jucn[cnt].referral_count, NULL)) {
- pstrcpy(jucn[cnt].service_name, service_name);
- pstrcpy(jucn[cnt].volume_name, dname);
- cnt++;
+ if (is_msdfs_link(&conn, dname, link_target, NULL)) {
+ if (parse_msdfs_symlink(ctx,
+ link_target,
+ &jucn[cnt].referral_list,
+ &jucn[cnt].referral_count)) {
+
+ fstrcpy(jucn[cnt].service_name, service_name);
+ pstrcpy(jucn[cnt].volume_name, dname);
+ cnt++;
+ }
}
}
@@ -1148,3 +1243,33 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
}
return jn_count;
}
+
+/******************************************************************************
+ Core function to resolve a dfs pathname.
+******************************************************************************/
+
+NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ BOOL dummy;
+ if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+ status = dfs_redirect(conn, name, False, &dummy);
+ }
+ return status;
+}
+
+/******************************************************************************
+ Core function to resolve a dfs pathname possibly containing a wildcard.
+ This function is identical to the above except for the BOOL param to
+ dfs_redirect but I need this to be separate so it's really clear when
+ we're allowing wildcards and when we're not. JRA.
+******************************************************************************/
+
+NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+ status = dfs_redirect(conn, name, True, ppath_contains_wcard);
+ }
+ return status;
+}
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index fb5610b20bb..bc7c75aab4c 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -259,7 +259,9 @@ static int reply_nt1(char *inbuf, char *outbuf)
if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) )
{
- set_remote_arch( RA_VISTA );
+ if (get_remote_arch() != RA_SAMBA) {
+ set_remote_arch( RA_VISTA );
+ }
}
/* do spnego in user level security if the client
diff --git a/source/smbd/notify_inotify.c b/source/smbd/notify_inotify.c
index 5fb414de4cc..ff17d455f39 100644
--- a/source/smbd/notify_inotify.c
+++ b/source/smbd/notify_inotify.c
@@ -26,6 +26,10 @@
#ifdef HAVE_INOTIFY
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
#include <linux/inotify.h>
#include <asm/unistd.h>
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 19710d1dcdd..2a49e1f4a64 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -353,7 +353,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
return(ERROR_DOS(ERRSRV,ERRnofids));
}
- /* TODO: Add pipe to db */
+ /* Add pipe to db */
if ( !store_pipe_opendb( p ) ) {
DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
@@ -469,7 +469,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
int info = 0;
- files_struct *fsp=NULL;
+ files_struct *fsp = NULL;
char *p = NULL;
struct timespec c_timespec;
struct timespec a_timespec;
@@ -491,7 +491,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
(unsigned int)create_options,
(unsigned int)root_dir_fid ));
- /* If it's an IPC, use the pipe handler. */
+ /*
+ * If it's an IPC, use the pipe handler.
+ */
if (IS_IPC(conn)) {
if (lp_nt_pipe_support()) {
@@ -502,7 +504,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
return(ERROR_DOS(ERRDOS,ERRnoaccess));
}
}
-
+
if (create_options & FILE_OPEN_BY_FILE_ID) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -522,7 +524,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
if(!dir_fsp) {
END_PROFILE(SMBntcreateX);
- return(ERROR_DOS(ERRDOS,ERRbadfid));
+ return ERROR_DOS(ERRDOS,ERRbadfid);
}
if(!dir_fsp->is_directory) {
@@ -533,7 +535,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
return ERROR_NT(status);
}
- /*
+ /*
* Check to see if this is a mac fork of some kind.
*/
@@ -564,7 +566,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
* Ensure it ends in a '\'.
*/
- if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
+ if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
pstrcat(fname, "/");
dir_name_len++;
}
@@ -582,7 +584,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
return ERROR_NT(status);
}
- /*
+ /*
* Check to see if this is a mac fork of some kind.
*/
@@ -613,7 +615,14 @@ int reply_ntcreate_and_X(connection_struct *conn,
* Now contruct the smb_open_mode value from the filename,
* desired access and the share access.
*/
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntcreateX);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
if (oplock_request) {
@@ -664,19 +673,19 @@ int reply_ntcreate_and_X(connection_struct *conn,
}
}
- /*
+ /*
* If it's a request for a directory open, deal with it separately.
*/
if(create_options & FILE_DIRECTORY_FILE) {
- oplock_request = 0;
-
+
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
+ oplock_request = 0;
status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
@@ -695,7 +704,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
+
} else {
+
/*
* Ordinary file case.
*/
@@ -721,6 +732,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
new_file_attributes,
oplock_request,
&info, &fsp);
+
if (!NT_STATUS_IS_OK(status)) {
/* We cheat here. There are two cases we
* care about. One is a directory rename,
@@ -773,7 +785,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
return ERROR_NT(status);
}
} else {
-
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -786,7 +797,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
}
restore_case_semantics(conn, file_attributes);
-
+
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
if(fattr == 0) {
@@ -827,11 +838,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
* and we granted one (by whatever means) - set the
* correct bit for extended oplock reply.
*/
-
+
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
extended_oplock_granted = True;
}
-
+
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
extended_oplock_granted = True;
}
@@ -871,8 +882,8 @@ int reply_ntcreate_and_X(connection_struct *conn,
SIVAL(p,0,info);
}
p += 4;
-
- /* Create time. */
+
+ /* Create time. */
c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
a_timespec = get_atimespec(&sbuf);
m_timespec = get_mtimespec(&sbuf);
@@ -883,7 +894,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
dos_filetime_timespec(&m_timespec);
}
- put_long_date_timespec(p, c_timespec);
+ put_long_date_timespec(p, c_timespec); /* create time. */
p += 8;
put_long_date_timespec(p, a_timespec); /* access time */
p += 8;
@@ -1252,15 +1263,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
- oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+ if (oplock_request) {
+ oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+ }
/*
+ * Ordinary file or directory.
+ */
+
+ /*
* Check if POSIX semantics are wanted.
*/
-
+
new_file_attributes = set_posix_case_semantics(conn, file_attributes);
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -1273,7 +1296,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
-
+
/* This is the correct thing to do (check every time) but can_delete is
expensive (it may have to read the parent directory permissions). So
for now we're not doing it unless we have a strong hint the client
@@ -1317,14 +1340,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- oplock_request = 0;
-
/*
* We will get a create directory here if the Win32
* app specified a security descriptor in the
* CreateDirectory() call.
*/
+ oplock_request = 0;
status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
@@ -1464,11 +1486,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* and we granted one (by whatever means) - set the
* correct bit for extended oplock reply.
*/
-
+
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
extended_oplock_granted = True;
}
-
+
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
extended_oplock_granted = True;
}
@@ -1592,15 +1614,15 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
return status;
}
- /* Source must already exist. */
- if (!VALID_STAT(sbuf1)) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
status = check_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+ /* Source must already exist. */
+ if (!VALID_STAT(sbuf1)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
/* Ensure attributes match. */
fattr = dos_mode(conn,oldname,&sbuf1);
if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
@@ -1612,16 +1634,16 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
return status;
}
- /* Disallow if newname already exists. */
- if (VALID_STAT(sbuf2)) {
- return NT_STATUS_OBJECT_NAME_COLLISION;
- }
-
status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
+ /* Disallow if newname already exists. */
+ if (VALID_STAT(sbuf2)) {
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
/* No links from a directory. */
if (S_ISDIR(sbuf1.st_mode)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -1675,7 +1697,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
+ fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1));
status = close_file(fsp2,NORMAL_CLOSE);
@@ -1708,15 +1730,15 @@ int reply_ntrename(connection_struct *conn,
pstring newname;
char *p;
NTSTATUS status;
- BOOL path1_contains_wcard = False;
- BOOL path2_contains_wcard = False;
+ BOOL src_has_wcard = False;
+ BOOL dest_has_wcard = False;
uint32 attrs = SVAL(inbuf,smb_vwv0);
uint16 rename_type = SVAL(inbuf,smb_vwv1);
START_PROFILE(SMBntrename);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@@ -1734,23 +1756,38 @@ int reply_ntrename(connection_struct *conn,
}
p++;
- p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf);
- RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
-
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntrename);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntrename);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
switch(rename_type) {
case RENAME_FLAG_RENAME:
- status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard);
+ status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
break;
case RENAME_FLAG_HARD_LINK:
- if (path1_contains_wcard || path2_contains_wcard) {
+ if (src_has_wcard || dest_has_wcard) {
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
@@ -1758,7 +1795,7 @@ int reply_ntrename(connection_struct *conn,
}
break;
case RENAME_FLAG_COPY:
- if (path1_contains_wcard || path2_contains_wcard) {
+ if (src_has_wcard || dest_has_wcard) {
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
@@ -1899,7 +1936,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
pstring new_name;
files_struct *fsp = NULL;
BOOL replace_if_exists = False;
- BOOL path_contains_wcard = False;
+ BOOL dest_has_wcard = False;
NTSTATUS status;
if(parameter_count < 5) {
@@ -1909,13 +1946,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
- srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard);
+ srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
+ STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = rename_internals(conn, fsp->fsp_name,
- new_name, 0, replace_if_exists, path_contains_wcard);
+ new_name, 0, replace_if_exists, False, dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 13ec9f952fe..c7a7086894e 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -1903,7 +1903,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
uint32 file_attributes,
SMB_STRUCT_STAT *psbuf)
{
- int ret= -1;
mode_t mode;
char *parent_dir;
const char *dirname;
@@ -1931,7 +1930,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
mode = unix_mode(conn, aDIR, name, parent_dir);
}
- if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
+ if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
return map_nt_error_from_unix(errno);
}
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 52660da2ffe..58756a0b5a6 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -300,7 +300,5 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
return ERROR_DOS(ERRDOS,ERRbadfid);
}
- /* TODO: REMOVE PIPE FROM DB */
-
return(outsize);
}
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 14941e64990..836801ba82c 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -1148,6 +1148,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
char *inbuf2, *outbuf2;
int outsize2;
+ int new_size;
char inbuf_saved[smb_wct];
char outbuf_saved[smb_wct];
int outsize = smb_len(outbuf) + 4;
@@ -1198,6 +1199,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
/* create the in buffer */
SCVAL(inbuf2,smb_com,smb_com2);
+ /* work out the new size for the in buffer. */
+ new_size = size - (inbuf2 - inbuf);
+ if (new_size < 0) {
+ DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, "
+ "offset = %d)\n",
+ size,
+ (inbuf2 - inbuf) ));
+ exit_server_cleanly("Bad chained packet");
+ return(-1);
+ }
+
+ /* And set it in the header. */
+ smb_setlen(inbuf2, new_size);
+
/* create the out buffer */
construct_reply_common(inbuf2, outbuf2);
@@ -1205,7 +1220,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
show_msg(inbuf2);
/* process the request */
- outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
+ outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size,
bufsize-chain_size);
/* copy the new reply and request headers over the old ones, but
@@ -1219,8 +1234,10 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
{
int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
- if (ofs < 0) ofs = 0;
- memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
+ if (ofs < 0) {
+ ofs = 0;
+ }
+ memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
}
return outsize2;
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index c48bebb0c6c..14b16e1ae23 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -44,9 +44,12 @@ extern BOOL global_encrypted_passwords_negotiated;
set.
****************************************************************************/
+/* Custom version for processing POSIX paths. */
+#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
+
NTSTATUS check_path_syntax_internal(pstring destname,
const pstring srcname,
- BOOL windows_path,
+ BOOL posix_path,
BOOL *p_last_component_contains_wcard)
{
char *d = destname;
@@ -57,12 +60,12 @@ NTSTATUS check_path_syntax_internal(pstring destname,
*p_last_component_contains_wcard = False;
while (*s) {
- if (IS_DIRECTORY_SEP(*s)) {
+ if (IS_PATH_SEP(*s,posix_path)) {
/*
* Safe to assume is not the second part of a mb char as this is handled below.
*/
/* Eat multiple '/' or '\\' */
- while (IS_DIRECTORY_SEP(*s)) {
+ while (IS_PATH_SEP(*s,posix_path)) {
s++;
}
if ((d != destname) && (*s != '\0')) {
@@ -77,7 +80,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
}
if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+ if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
/* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
/*
@@ -107,8 +110,8 @@ NTSTATUS check_path_syntax_internal(pstring destname,
/* We're still at the start of a name component, just the previous one. */
continue;
- } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
- if (!windows_path) {
+ } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
+ if (posix_path) {
/* Eat the '.' */
s++;
continue;
@@ -118,7 +121,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
}
if (!(*s & 0x80)) {
- if (windows_path) {
+ if (!posix_path) {
if (*s <= 0x1f) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
@@ -176,7 +179,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
BOOL ignore;
- return check_path_syntax_internal(destname, srcname, True, &ignore);
+ return check_path_syntax_internal(destname, srcname, False, &ignore);
}
/****************************************************************************
@@ -187,7 +190,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
{
- return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
+ return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
}
/****************************************************************************
@@ -196,10 +199,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
set (a safe assumption).
****************************************************************************/
-static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
{
BOOL ignore;
- return check_path_syntax_internal(destname, srcname, False, &ignore);
+ return check_path_syntax_internal(destname, srcname, True, &ignore);
}
/****************************************************************************
@@ -224,6 +227,16 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
*contains_wcard = False;
+ if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+ /*
+ * For a DFS path the function parse_dfs_path()
+ * will do the path processing, just make a copy.
+ */
+ pstrcpy(dest, tmppath);
+ *err = NT_STATUS_OK;
+ return ret;
+ }
+
if (lp_posix_pathnames()) {
*err = check_path_syntax_posix(dest, tmppath);
} else {
@@ -251,6 +264,17 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
} else {
ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
+
+ if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+ /*
+ * For a DFS path the function parse_dfs_path()
+ * will do the path processing, just make a copy.
+ */
+ pstrcpy(dest, tmppath);
+ *err = NT_STATUS_OK;
+ return ret;
+ }
+
if (lp_posix_pathnames()) {
*err = check_path_syntax_posix(dest, tmppath);
} else {
@@ -631,7 +655,14 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ END_PROFILE(SMBcheckpath);
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ goto path_err;
+ }
DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
@@ -710,7 +741,14 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBgetatr);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
@@ -789,7 +827,14 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -797,6 +842,12 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(status);
+ }
+
if (fname[0] == '.' && fname[1] == '\0') {
/*
* Not sure here is the right place to catch this
@@ -806,12 +857,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBsetatr);
- return ERROR_NT(status);
- }
-
mode = SVAL(inbuf,smb_vwv0);
mtime = srv_make_unix_date3(inbuf+smb_vwv1);
@@ -827,7 +872,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
}
- if (!set_filetime(conn,fname,mtime)) {
+ if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
END_PROFILE(SMBsetatr);
return UNIXERROR(ERRDOS, ERRnoaccess);
}
@@ -944,7 +989,14 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(nt_status);
}
- RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
+ nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ END_PROFILE(SMBsearch);
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(nt_status);
+ }
p++;
status_len = SVAL(p, 0);
@@ -954,16 +1006,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (status_len == 0) {
SMB_STRUCT_STAT sbuf;
- pstring dir2;
pstrcpy(directory,path);
- pstrcpy(dir2,path);
nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
}
- unix_format(dir2);
nt_status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -971,23 +1020,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(nt_status);
}
- p = strrchr_m(dir2,'/');
- if (p == NULL) {
- pstrcpy(mask,dir2);
- *dir2 = 0;
- } else {
- *p = 0;
- pstrcpy(mask,p+1);
- }
-
p = strrchr_m(directory,'/');
if (!p) {
- *directory = 0;
+ pstrcpy(mask,directory);
+ pstrcpy(directory,".");
} else {
*p = 0;
+ pstrcpy(mask,p+1);
}
- if (strlen(directory) == 0) {
+ if (*directory == '\0') {
pstrcpy(directory,".");
}
memset((char *)status,'\0',21);
@@ -1007,6 +1049,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
string_set(&conn->dirpath,dptr_path(dptr_num));
pstrcpy(mask, dptr_wcard(dptr_num));
+ /*
+ * For a 'continue' search we have no string. So
+ * check from the initial saved string.
+ */
+ mask_contains_wcard = ms_has_wild(mask);
}
p = smb_buf(outbuf) + 3;
@@ -1202,7 +1249,14 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopen);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -1210,6 +1264,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopen);
+ return ERROR_NT(status);
+ }
+
if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
&access_mask, &share_mode, &create_disposition, &create_options)) {
END_PROFILE(SMBopen);
@@ -1320,7 +1380,14 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -1328,6 +1395,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
+ return ERROR_NT(status);
+ }
+
if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
&access_mask,
&share_mode,
@@ -1470,7 +1543,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int com;
int outsize = 0;
uint32 fattr = SVAL(inbuf,smb_vwv0);
- struct utimbuf times;
+ struct timespec ts[2];
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
@@ -1484,7 +1557,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
com = SVAL(inbuf,smb_com);
- times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
@@ -1492,7 +1565,14 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -1500,6 +1580,12 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ return ERROR_NT(status);
+ }
+
if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
}
@@ -1531,8 +1617,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- times.actime = sbuf.st_atime;
- file_utime(conn, fname, &times);
+ ts[0] = get_atimespec(&sbuf); /* atime. */
+ file_ntimes(conn, fname, ts);
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
@@ -1582,13 +1668,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
pstrcat(fname,"TMXXXXXX");
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBctemp);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
return ERROR_NT(status);
}
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBctemp);
+ return ERROR_NT(status);
+ }
tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
@@ -1858,6 +1957,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
if (dirtype == 0) {
dirtype = FILE_ATTRIBUTE_NORMAL;
}
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = can_delete(conn,directory,dirtype,can_defer);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -1920,6 +2025,13 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ CloseDir(dir_hnd);
+ return status;
+ }
+
status = can_delete(conn, fname, dirtype, can_defer);
if (!NT_STATUS_IS_OK(status)) {
continue;
@@ -1966,8 +2078,15 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
END_PROFILE(SMBunlink);
return ERROR_NT(status);
}
-
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBunlink);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
DEBUG(3,("reply_unlink : %s\n",name));
@@ -3109,7 +3228,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
{
NTSTATUS status = NT_STATUS_OK;
int outsize = 0;
- time_t mtime;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
@@ -3151,8 +3269,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
* Take care of any time sent in the close.
*/
- mtime = srv_make_unix_date3(inbuf+smb_vwv1);
- fsp_set_pending_modtime(fsp, mtime);
+ fsp_set_pending_modtime(fsp,
+ convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
/*
* close_file() returns the unix errno if an error
@@ -3185,7 +3303,7 @@ int reply_writeclose(connection_struct *conn,
NTSTATUS close_status = NT_STATUS_OK;
SMB_OFF_T startpos;
char *data;
- time_t mtime;
+ struct timespec mtime;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBwriteclose);
@@ -3196,7 +3314,7 @@ int reply_writeclose(connection_struct *conn,
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- mtime = srv_make_unix_date3(inbuf+smb_vwv4);
+ mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
data = smb_buf(inbuf) + 1;
if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
@@ -3206,7 +3324,7 @@ int reply_writeclose(connection_struct *conn,
nwritten = write_file(fsp,data,startpos,numtowrite);
- set_filetime(conn, fsp->fsp_name,mtime);
+ set_filetime(conn, fsp->fsp_name, mtime);
/*
* More insanity. W2K only closes the file if writelen > 0.
@@ -3598,7 +3716,14 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmkdir);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, directory, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -3606,6 +3731,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmkdir);
+ return ERROR_NT(status);
+ }
+
status = create_directory(conn, directory);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -3810,7 +3941,14 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBrmdir);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, directory, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -3854,7 +3992,6 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
char *p,*p2, *pname1, *pname2;
int available_space, actual_space;
-
pname1 = strrchr_m(name1,'/');
pname2 = strrchr_m(name2,'/');
@@ -4008,6 +4145,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
return status;
}
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* Ensure newname contains a '/' */
if(strrchr_m(newname,'/') == 0) {
pstring tmpstr;
@@ -4152,9 +4294,13 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, pstring name,
- pstring newname, uint32 attrs,
- BOOL replace_if_exists, BOOL has_wild)
+NTSTATUS rename_internals(connection_struct *conn,
+ pstring name,
+ pstring newname,
+ uint32 attrs,
+ BOOL replace_if_exists,
+ BOOL src_has_wild,
+ BOOL dest_has_wild)
{
pstring directory;
pstring mask;
@@ -4165,20 +4311,22 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf1, sbuf2;
struct share_mode_lock *lck = NULL;
+ struct smb_Dir *dir_hnd = NULL;
+ const char *dname;
+ long offset = 0;
+ pstring destname;
*directory = *mask = 0;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- status = unix_convert(conn, name, has_wild, last_component_src,
- &sbuf1);
+ status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = unix_convert(conn, newname, True, last_component_dest,
- &sbuf2);
+ status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4212,10 +4360,11 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ }
- if (!has_wild) {
+ if (!src_has_wild) {
/*
* No wildcards - just process the one file.
*/
@@ -4242,6 +4391,21 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
conn->short_case_preserve, directory,
newname, last_component_dest, is_short_name));
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* The dest name still may have wildcards. */
+ if (dest_has_wild) {
+ if (!resolve_wildcards(directory,newname)) {
+ DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
+ directory,newname));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
/*
* Check for special case with case preserving and not
* case sensitive, if directory and newname are identical,
@@ -4276,8 +4440,12 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
}
}
- resolve_wildcards(directory,newname);
-
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/*
* The source object must exist.
*/
@@ -4369,136 +4537,130 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
nt_errstr(status), directory,newname));
return status;
- } else {
- /*
- * Wildcards - process each file that matches.
- */
- struct smb_Dir *dir_hnd = NULL;
- const char *dname;
- long offset = 0;
- pstring destname;
-
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
+ }
+
+ /*
+ * Wildcards - process each file that matches.
+ */
+ if (strequal(mask,"????????.???")) {
+ pstrcpy(mask,"*");
+ }
- status = check_name(conn, directory);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- dir_hnd = OpenDir(conn, directory, mask, attrs);
- if (dir_hnd == NULL) {
- return map_nt_error_from_unix(errno);
- }
+ dir_hnd = OpenDir(conn, directory, mask, attrs);
+ if (dir_hnd == NULL) {
+ return map_nt_error_from_unix(errno);
+ }
- status = NT_STATUS_NO_SUCH_FILE;
- /*
- * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- * - gentest fix. JRA
- */
+ status = NT_STATUS_NO_SUCH_FILE;
+ /*
+ * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ * - gentest fix. JRA
+ */
- while ((dname = ReadDirName(dir_hnd, &offset))) {
- pstring fname;
- BOOL sysdir_entry = False;
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ pstring fname;
+ BOOL sysdir_entry = False;
- pstrcpy(fname,dname);
+ pstrcpy(fname,dname);
- /* Quick check for "." and ".." */
- if (fname[0] == '.') {
- if (!fname[1]
- || (fname[1] == '.' && !fname[2])) {
- if (attrs & aDIR) {
- sysdir_entry = True;
- } else {
- continue;
- }
+ /* Quick check for "." and ".." */
+ if (fname[0] == '.') {
+ if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+ if (attrs & aDIR) {
+ sysdir_entry = True;
+ } else {
+ continue;
}
}
+ }
- if (!is_visible_file(conn, directory, dname, &sbuf1,
- False)) {
- continue;
- }
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+ continue;
+ }
- if(!mask_match(fname, mask, conn->case_sensitive)) {
- continue;
- }
+ if(!mask_match(fname, mask, conn->case_sensitive)) {
+ continue;
+ }
- if (sysdir_entry) {
- status = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- }
+ if (sysdir_entry) {
+ status = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
+ }
- status = NT_STATUS_ACCESS_DENIED;
- slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
- dname);
- if (!vfs_object_exist(conn, fname, &sbuf1)) {
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(6, ("rename %s failed. Error %s\n",
- fname, nt_errstr(status)));
- continue;
- }
- status = can_rename(conn,fname,attrs,&sbuf1);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(6, ("rename %s refused\n", fname));
- continue;
- }
- pstrcpy(destname,newname);
+ status = NT_STATUS_ACCESS_DENIED;
+ slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!vfs_object_exist(conn, fname, &sbuf1)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6, ("rename %s failed. Error %s\n",
+ fname, nt_errstr(status)));
+ continue;
+ }
+ status = can_rename(conn,fname,attrs,&sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused\n", fname));
+ continue;
+ }
+ pstrcpy(destname,newname);
- if (!resolve_wildcards(fname,destname)) {
- DEBUG(6, ("resolve_wildcards %s %s failed\n",
- fname, destname));
- continue;
- }
+ if (!resolve_wildcards(fname,destname)) {
+ DEBUG(6, ("resolve_wildcards %s %s failed\n",
+ fname, destname));
+ continue;
+ }
- if (strcsequal(fname,destname)) {
- rename_open_files(conn, NULL, sbuf1.st_dev,
- sbuf1.st_ino, newname);
- DEBUG(3,("rename_internals: identical names "
- "in wildcard rename %s - success\n",
- fname));
- count++;
- status = NT_STATUS_OK;
- continue;
- }
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, destname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- if (!replace_if_exists
- && vfs_file_exist(conn,destname, NULL)) {
- DEBUG(6,("file_exist %s\n", destname));
- status = NT_STATUS_OBJECT_NAME_COLLISION;
- continue;
- }
+ if (strcsequal(fname,destname)) {
+ rename_open_files(conn, NULL, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: identical names "
+ "in wildcard rename %s - success\n",
+ fname));
+ count++;
+ status = NT_STATUS_OK;
+ continue;
+ }
+
+ if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+ DEBUG(6,("file_exist %s\n", destname));
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ continue;
+ }
- if (rename_path_prefix_equal(fname, destname)) {
- return NT_STATUS_SHARING_VIOLATION;
- }
+ if (rename_path_prefix_equal(fname, destname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- lck = get_share_mode_lock(NULL, sbuf1.st_dev,
- sbuf1.st_ino, NULL, NULL);
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+ sbuf1.st_ino, NULL, NULL);
- if (!SMB_VFS_RENAME(conn,fname,destname)) {
- rename_open_files(conn, lck, sbuf1.st_dev,
- sbuf1.st_ino, newname);
- count++;
- status = NT_STATUS_OK;
- }
- TALLOC_FREE(lck);
- DEBUG(3,("rename_internals: doing rename on %s -> "
- "%s\n",fname,destname));
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ count++;
+ status = NT_STATUS_OK;
}
- CloseDir(dir_hnd);
+ TALLOC_FREE(lck);
+ DEBUG(3,("rename_internals: doing rename on %s -> "
+ "%s\n",fname,destname));
}
-
-#if 0
- /* Don't think needed any more - JRA. */
- if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
- if (!rcdest && bad_path_dest) {
- if (ms_has_wild(last_component_dest))
- return NT_STATUS_OBJECT_NAME_INVALID;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
- }
-#endif
+ CloseDir(dir_hnd);
if (count == 0 && NT_STATUS_IS_OK(status)) {
status = map_nt_error_from_unix(errno);
@@ -4520,30 +4682,45 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
char *p;
uint32 attrs = SVAL(inbuf,smb_vwv0);
NTSTATUS status;
- BOOL path1_contains_wcard = False;
- BOOL path2_contains_wcard = False;
+ BOOL src_has_wcard = False;
+ BOOL dest_has_wcard = False;
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
p++;
- p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmv);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
+
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBmv);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
+ status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4567,8 +4744,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
* TODO: check error codes on all callers
*/
-NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
- int count, BOOL target_is_directory)
+NTSTATUS copy_file(connection_struct *conn,
+ char *src,
+ char *dest1,
+ int ofun,
+ int count,
+ BOOL target_is_directory)
{
SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
@@ -4653,7 +4834,7 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
+ fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
/*
* As we are opening fsp1 read-only we only expect
@@ -4688,14 +4869,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int count=0;
int error = ERRnoaccess;
int err = 0;
- BOOL has_wild;
- BOOL exists=False;
int tid2 = SVAL(inbuf,smb_vwv0);
int ofun = SVAL(inbuf,smb_vwv1);
int flags = SVAL(inbuf,smb_vwv2);
BOOL target_is_directory=False;
- BOOL path_contains_wcard1 = False;
- BOOL path_contains_wcard2 = False;
+ BOOL source_has_wild = False;
+ BOOL dest_has_wild = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
START_PROFILE(SMBcopy);
@@ -4703,12 +4882,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
+ p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
}
- p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
@@ -4723,16 +4902,31 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_DOS(ERRSRV,ERRinvdevice);
}
- RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
- status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
return ERROR_NT(status);
}
- status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
+ status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ }
+
+ status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
@@ -4776,25 +4970,38 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ }
- has_wild = path_contains_wcard1;
-
- if (!has_wild) {
+ if (!source_has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- if (resolve_wildcards(directory,newname)
- && NT_STATUS_IS_OK(status = copy_file(
- directory,newname,conn,ofun,
- count,target_is_directory)))
- count++;
- if(!count && !NT_STATUS_IS_OK(status)) {
- END_PROFILE(SMBcopy);
+ if (dest_has_wild) {
+ if (!resolve_wildcards(directory,newname)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- if (!count) {
- exists = vfs_file_exist(conn,directory,NULL);
+
+ status = copy_file(conn,directory,newname,ofun,
+ count,target_is_directory);
+
+ if(!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcopy);
+ return ERROR_NT(status);
+ } else {
+ count++;
}
} else {
struct smb_Dir *dir_hnd = NULL;
@@ -4833,13 +5040,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
error = ERRnoaccess;
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
pstrcpy(destname,newname);
- if (resolve_wildcards(fname,destname) &&
- NT_STATUS_IS_OK(status = copy_file(
- fname,destname,conn,ofun,
- count,target_is_directory))) {
+ if (!resolve_wildcards(fname,destname)) {
+ continue;
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ status = check_name(conn, destname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
+ DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+
+ status = copy_file(conn,fname,destname,ofun,
+ count,target_is_directory);
+ if (NT_STATUS_IS_OK(status)) {
count++;
}
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
}
CloseDir(dir_hnd);
}
@@ -4888,7 +5109,14 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(pathworks_setdir);
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
if (strlen(newdir) != 0) {
if (!vfs_directory_exist(conn,newdir,NULL)) {
@@ -5440,7 +5668,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- struct utimbuf unix_times;
+ struct timespec ts[2];
int outsize = 0;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBsetattrE);
@@ -5457,15 +5685,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
* time as UNIX can't set this.
*/
- unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
- unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
+ ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
/*
* Patch from Ray Frush <frush@engr.colostate.edu>
* Sometimes times are sent as zero - ignore them.
*/
- if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ if (null_timespec(ts[0]) && null_timespec(ts[1])) {
/* Ignore request */
if( DEBUGLVL( 3 ) ) {
dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
@@ -5473,20 +5701,22 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
END_PROFILE(SMBsetattrE);
return(outsize);
- } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
/* set modify time = to access time if modify time was unset */
- unix_times.modtime = unix_times.actime;
+ ts[1] = ts[0];
}
/* Set the date on this file */
/* Should we set pending modtime here ? JRA */
- if(file_utime(conn, fsp->fsp_name, &unix_times)) {
+ if(file_ntimes(conn, fsp->fsp_name, ts)) {
END_PROFILE(SMBsetattrE);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
- fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
+ DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
+ fsp->fnum,
+ (unsigned int)ts[0].tv_sec,
+ (unsigned int)ts[1].tv_sec));
END_PROFILE(SMBsetattrE);
return(outsize);
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 7a5f8be47ff..ff1b2821cca 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -158,13 +158,76 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
#ifdef HAVE_KRB5
+
+#if 0
+/* Experiment that failed. See "only happens with a KDC" comment below. */
+/****************************************************************************
+ Cerate a clock skew error blob for a Windows client.
+****************************************************************************/
+
+static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
+{
+ krb5_context context = NULL;
+ krb5_error_code kerr = 0;
+ krb5_data reply;
+ krb5_principal host_princ = NULL;
+ char *host_princ_s = NULL;
+ BOOL ret = False;
+
+ *pblob_out = data_blob(NULL,0);
+
+ initialize_krb5_error_table();
+ kerr = krb5_init_context(&context);
+ if (kerr) {
+ return False;
+ }
+ /* Create server principal. */
+ asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
+ if (!host_princ_s) {
+ goto out;
+ }
+ strlower_m(host_princ_s);
+
+ kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
+ if (kerr) {
+ DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
+ host_princ_s, error_message(kerr) ));
+ goto out;
+ }
+
+ kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
+ if (kerr) {
+ DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
+ error_message(kerr) ));
+ goto out;
+ }
+
+ *pblob_out = data_blob(reply.data, reply.length);
+ kerberos_free_data_contents(context,&reply);
+ ret = True;
+
+ out:
+
+ if (host_princ_s) {
+ SAFE_FREE(host_princ_s);
+ }
+ if (host_princ) {
+ krb5_free_principal(context, host_princ);
+ }
+ krb5_free_context(context);
+ return ret;
+}
+#endif
+
/****************************************************************************
-reply to a session setup spnego negotiate packet for kerberos
+ Reply to a session setup spnego negotiate packet for kerberos.
****************************************************************************/
+
static int reply_spnego_kerberos(connection_struct *conn,
char *inbuf, char *outbuf,
int length, int bufsize,
- DATA_BLOB *secblob)
+ DATA_BLOB *secblob,
+ BOOL *p_invalidate_vuid)
{
TALLOC_CTX *mem_ctx;
DATA_BLOB ticket;
@@ -191,9 +254,13 @@ static int reply_spnego_kerberos(connection_struct *conn,
ZERO_STRUCT(ap_rep_wrapped);
ZERO_STRUCT(response);
+ /* Normally we will always invalidate the intermediate vuid. */
+ *p_invalidate_vuid = True;
+
mem_ctx = talloc_init("reply_spnego_kerberos");
- if (mem_ctx == NULL)
+ if (mem_ctx == NULL) {
return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
+ }
if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
talloc_destroy(mem_ctx);
@@ -205,9 +272,50 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ticket);
if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(1,("Failed to verify incoming ticket!\n"));
+#if 0
+ /* Experiment that failed. See "only happens with a KDC" comment below. */
+
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
+
+ /*
+ * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
+ * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
+ * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
+ * clock and continues rather than giving an error. JRA.
+ * -- Looks like this only happens with a KDC. JRA.
+ */
+
+ BOOL ok = make_krb5_skew_error(&ap_rep);
+ if (!ok) {
+ talloc_destroy(mem_ctx);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ }
+ ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
+ response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
+ reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+
+ /*
+ * In this one case we don't invalidate the intermediate vuid.
+ * as we're expecting the client to re-use it for the next
+ * sessionsetupX packet. JRA.
+ */
+
+ *p_invalidate_vuid = False;
+
+ data_blob_free(&ap_rep);
+ data_blob_free(&ap_rep_wrapped);
+ data_blob_free(&response);
+ talloc_destroy(mem_ctx);
+ return -1; /* already replied */
+ }
+#else
+ if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
+ ret = NT_STATUS_LOGON_FAILURE;
+ }
+#endif
+ DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
talloc_destroy(mem_ctx);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ return ERROR_NT(nt_status_squash(ret));
}
DEBUG(3,("Ticket name is [%s]\n", client));
@@ -523,32 +631,19 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
}
/****************************************************************************
- Reply to a session setup spnego negotiate packet.
+ Is this a krb5 mechanism ?
****************************************************************************/
-static int reply_spnego_negotiate(connection_struct *conn,
- char *inbuf,
- char *outbuf,
- uint16 vuid,
- int length, int bufsize,
- DATA_BLOB blob1,
- AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
{
char *OIDs[ASN1_MAX_OIDS];
- DATA_BLOB secblob;
int i;
- DATA_BLOB chal;
-#ifdef HAVE_KRB5
- BOOL got_kerberos_mechanism = False;
-#endif
- NTSTATUS nt_status;
- /* parse out the OIDs and the first sec blob */
- if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ *p_is_krb5 = False;
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ /* parse out the OIDs and the first sec blob */
+ if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
+ return NT_STATUS_LOGON_FAILURE;
}
/* only look at the first OID for determining the mechToken --
@@ -564,24 +659,53 @@ static int reply_spnego_negotiate(connection_struct *conn,
#ifdef HAVE_KRB5
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
- got_kerberos_mechanism = True;
+ *p_is_krb5 = True;
}
#endif
for (i=0;OIDs[i];i++) {
- DEBUG(3,("Got OID %s\n", OIDs[i]));
+ DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
free(OIDs[i]);
}
- DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Reply to a session setup spnego negotiate packet.
+****************************************************************************/
+
+static int reply_spnego_negotiate(connection_struct *conn,
+ char *inbuf,
+ char *outbuf,
+ uint16 vuid,
+ int length, int bufsize,
+ DATA_BLOB blob1,
+ AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+{
+ DATA_BLOB secblob;
+ DATA_BLOB chal;
+ BOOL got_kerberos_mechanism = False;
+ NTSTATUS status;
+
+ status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ return ERROR_NT(nt_status_squash(status));
+ }
+
+ DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
#ifdef HAVE_KRB5
if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
+ BOOL destroy_vuid = True;
int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
- length, bufsize, &secblob);
+ length, bufsize, &secblob, &destroy_vuid);
data_blob_free(&secblob);
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
-
+ if (destroy_vuid) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ }
return ret;
}
#endif
@@ -590,28 +714,27 @@ static int reply_spnego_negotiate(connection_struct *conn,
auth_ntlmssp_end(auth_ntlmssp_state);
}
- nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
- if (!NT_STATUS_IS_OK(nt_status)) {
+ status = auth_ntlmssp_start(auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
-
- return ERROR_NT(nt_status_squash(nt_status));
+ return ERROR_NT(nt_status_squash(status));
}
- nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
+ status = auth_ntlmssp_update(*auth_ntlmssp_state,
secblob, &chal);
data_blob_free(&secblob);
reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
- &chal, nt_status, True);
+ &chal, status, True);
data_blob_free(&chal);
/* already replied */
return -1;
}
-
+
/****************************************************************************
Reply to a session setup spnego auth packet.
****************************************************************************/
@@ -622,8 +745,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
- DATA_BLOB auth, auth_reply;
- NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
+ DATA_BLOB auth = data_blob(NULL,0);
+ DATA_BLOB auth_reply = data_blob(NULL,0);
+ DATA_BLOB secblob = data_blob(NULL,0);
+ NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
@@ -634,6 +759,33 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
+
+ if (auth.data[0] == ASN1_APPLICATION(0)) {
+ /* Might be a second negTokenTarg packet */
+
+ BOOL got_krb5_mechanism = False;
+ status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
+ if (NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
+#ifdef HAVE_KRB5
+ if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
+ BOOL destroy_vuid = True;
+ int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
+ length, bufsize, &secblob, &destroy_vuid);
+ data_blob_free(&secblob);
+ data_blob_free(&auth);
+ if (destroy_vuid) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ }
+ return ret;
+ }
+#endif
+ }
+ }
+
+ /* If we get here it wasn't a negTokenTarg auth packet. */
+ data_blob_free(&secblob);
if (!*auth_ntlmssp_state) {
/* Kill the intermediate vuid */
@@ -643,14 +795,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
- nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
+ status = auth_ntlmssp_update(*auth_ntlmssp_state,
auth, &auth_reply);
data_blob_free(&auth);
reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
auth_ntlmssp_state,
- &auth_reply, nt_status, True);
+ &auth_reply, status, True);
data_blob_free(&auth_reply);
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 5bbd618231b..deb5db1bafe 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -5,6 +5,7 @@
Copyright (C) Stefan (metze) Metzmacher 2003
Copyright (C) Volker Lendecke 2005
Copyright (C) Steve French 2005
+ Copyright (C) James Peach 2007
Extensively modified by Andrew Tridgell, 1995
@@ -34,6 +35,16 @@ extern struct current_user current_user;
#define get_file_size(sbuf) ((sbuf).st_size)
#define DIR_ENTRY_SAFETY_MARGIN 4096
+static char *store_file_unix_basic(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf);
+
+static char *store_file_unix_basic_info2(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf);
+
/********************************************************************
Roundup a value to the nearest allocation roundup size boundary.
Only do this for Windows clients.
@@ -56,7 +67,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
account sparse files.
********************************************************************/
-SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
{
SMB_BIG_UINT ret;
@@ -1191,15 +1202,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
continue;
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+ pstring link_target;
/* Needed to show the msdfs symlinks as
* directories */
if(lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
- ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
-
- DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
+ ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
+ DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
+ "as a directory\n",
+ pathreal));
sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
} else {
@@ -1578,51 +1591,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
/* CIFS UNIX Extension. */
case SMB_FIND_FILE_UNIX:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ case SMB_FIND_FILE_UNIX_INFO2:
p+= 4;
SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
- SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
- p+= 8;
-
- SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
- p+= 8;
-
- put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
- put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
- put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
- p+= 24;
-
- SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,sbuf.st_gid); /* group id of owner */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,unix_filetype(sbuf.st_mode));
- p+= 4;
-
- SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
- SIVAL(p,4,0);
- p+= 8;
-
- SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
- p+= 8;
- SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
- SIVAL(p,4,0);
- p+= 8;
+ if (info_level == SMB_FIND_FILE_UNIX) {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ p = store_file_unix_basic(conn, p,
+ NULL, &sbuf);
+ } else {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
+ p = store_file_unix_basic_info2(conn, p,
+ NULL, &sbuf);
+ }
len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
p += len;
@@ -1732,6 +1715,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
if (!lp_unix_extensions()) {
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
@@ -1745,7 +1729,13 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return ERROR_NT(ntstatus);
}
- RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
+ ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(ntstatus);
+ }
ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
if (!NT_STATUS_IS_OK(ntstatus)) {
@@ -2037,6 +2027,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
if (!lp_unix_extensions()) {
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
@@ -2232,7 +2223,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
char **pparams, int total_params, char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- char *pdata = *ppdata;
+ char *pdata;
char *params = *pparams;
uint16 info_level;
int data_len, len;
@@ -2530,6 +2521,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
CIFS_UNIX_POSIX_ACLS_CAP|
CIFS_UNIX_POSIX_PATHNAMES_CAP|
CIFS_UNIX_FCNTL_LOCKS_CAP|
+ CIFS_UNIX_EXTATTR_CAP|
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
break;
@@ -2566,6 +2558,114 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
break;
}
+ case SMB_QUERY_POSIX_WHOAMI:
+ {
+ uint32_t flags = 0;
+ uint32_t sid_bytes;
+ int i;
+
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
+ if (max_data_bytes < 40) {
+ return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* We ARE guest if global_sid_Builtin_Guests is
+ * in our list of SIDs.
+ */
+ if (nt_token_check_sid(&global_sid_Builtin_Guests,
+ current_user.nt_user_token)) {
+ flags |= SMB_WHOAMI_GUEST;
+ }
+
+ /* We are NOT guest if global_sid_Authenticated_Users
+ * is in our list of SIDs.
+ */
+ if (nt_token_check_sid(&global_sid_Authenticated_Users,
+ current_user.nt_user_token)) {
+ flags &= ~SMB_WHOAMI_GUEST;
+ }
+
+ /* NOTE: 8 bytes for UID/GID, irrespective of native
+ * platform size. This matches
+ * SMB_QUERY_FILE_UNIX_BASIC and friends.
+ */
+ data_len = 4 /* flags */
+ + 4 /* flag mask */
+ + 8 /* uid */
+ + 8 /* gid */
+ + 4 /* ngroups */
+ + 4 /* num_sids */
+ + 4 /* SID bytes */
+ + 4 /* pad/reserved */
+ + (current_user.ut.ngroups * 8)
+ /* groups list */
+ + (current_user.nt_user_token->num_sids *
+ SID_MAX_SIZE)
+ /* SID list */;
+
+ SIVAL(pdata, 0, flags);
+ SIVAL(pdata, 4, SMB_WHOAMI_MASK);
+ SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
+ SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
+
+
+ if (data_len >= max_data_bytes) {
+ /* Potential overflow, skip the GIDs and SIDs. */
+
+ SIVAL(pdata, 24, 0); /* num_groups */
+ SIVAL(pdata, 28, 0); /* num_sids */
+ SIVAL(pdata, 32, 0); /* num_sid_bytes */
+ SIVAL(pdata, 36, 0); /* reserved */
+
+ data_len = 40;
+ break;
+ }
+
+ SIVAL(pdata, 24, current_user.ut.ngroups);
+ SIVAL(pdata, 28,
+ current_user.nt_user_token->num_sids);
+
+ /* We walk the SID list twice, but this call is fairly
+ * infrequent, and I don't expect that it's performance
+ * sensitive -- jpeach
+ */
+ for (i = 0, sid_bytes = 0;
+ i < current_user.nt_user_token->num_sids; ++i) {
+ sid_bytes +=
+ sid_size(&current_user.nt_user_token->user_sids[i]);
+ }
+
+ /* SID list byte count */
+ SIVAL(pdata, 32, sid_bytes);
+
+ /* 4 bytes pad/reserved - must be zero */
+ SIVAL(pdata, 36, 0);
+ data_len = 40;
+
+ /* GID list */
+ for (i = 0; i < current_user.ut.ngroups; ++i) {
+ SBIG_UINT(pdata, data_len,
+ (SMB_BIG_UINT)current_user.ut.groups[i]);
+ data_len += 8;
+ }
+
+ /* SID list */
+ for (i = 0;
+ i < current_user.nt_user_token->num_sids; ++i) {
+ int sid_len =
+ sid_size(&current_user.nt_user_token->user_sids[i]);
+
+ sid_linearize(pdata + data_len, sid_len,
+ &current_user.nt_user_token->user_sids[i]);
+ data_len += sid_len;
+ }
+
+ break;
+ }
+
case SMB_MAC_QUERY_FS_INFO:
/*
* Thursby MAC extension... ONLY on NTFS filesystems
@@ -2871,7 +2971,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
static char *store_file_unix_basic(connection_struct *conn,
char *pdata,
files_struct *fsp,
- SMB_STRUCT_STAT *psbuf)
+ const SMB_STRUCT_STAT *psbuf)
{
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
@@ -2920,6 +3020,121 @@ static char *store_file_unix_basic(connection_struct *conn,
return pdata;
}
+/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
+ * the chflags(2) (or equivalent) flags.
+ *
+ * XXX: this really should be behind the VFS interface. To do this, we would
+ * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
+ * Each VFS module could then implement it's own mapping as appropriate for the
+ * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
+ */
+static const struct {unsigned stat_fflag; unsigned smb_fflag;}
+ info2_flags_map[] =
+{
+#ifdef UF_NODUMP
+ { UF_NODUMP, EXT_DO_NOT_BACKUP },
+#endif
+
+#ifdef UF_IMMUTABLE
+ { UF_IMMUTABLE, EXT_IMMUTABLE },
+#endif
+
+#ifdef UF_APPEND
+ { UF_APPEND, EXT_OPEN_APPEND_ONLY },
+#endif
+
+#ifdef UF_HIDDEN
+ { UF_HIDDEN, EXT_HIDDEN },
+#endif
+
+ /* Do not remove. We need to guarantee that this array has at least one
+ * entry to build on HP-UX.
+ */
+ { 0, 0 }
+
+};
+
+static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
+ uint32 *smb_fflags, uint32 *smb_fmask)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+ *smb_fmask |= info2_flags_map[i].smb_fflag;
+ if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
+ *smb_fflags |= info2_flags_map[i].smb_fflag;
+ }
+ }
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
+ const uint32 smb_fflags,
+ const uint32 smb_fmask,
+ int *stat_fflags)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+ uint32 max_fmask = 0;
+ int i;
+
+ *stat_fflags = psbuf->st_flags;
+
+ /* For each flags requested in smb_fmask, check the state of the
+ * corresponding flag in smb_fflags and set or clear the matching
+ * stat flag.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+ max_fmask |= info2_flags_map[i].smb_fflag;
+ if (smb_fmask & info2_flags_map[i].smb_fflag) {
+ if (smb_fflags & info2_flags_map[i].smb_fflag) {
+ *stat_fflags |= info2_flags_map[i].stat_fflag;
+ } else {
+ *stat_fflags &= ~info2_flags_map[i].stat_fflag;
+ }
+ }
+ }
+
+ /* If smb_fmask is asking to set any bits that are not supported by
+ * our flag mappings, we should fail.
+ */
+ if ((smb_fmask & max_fmask) != smb_fmask) {
+ return False;
+ }
+
+ return True;
+#else
+ return False;
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+
+/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
+ * of file flags and birth (create) time.
+ */
+static char *store_file_unix_basic_info2(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf)
+{
+ uint32 file_flags = 0;
+ uint32 flags_mask = 0;
+
+ pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
+
+ /* Create (birth) time 64 bit */
+ put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
+ pdata += 8;
+
+ map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
+ SIVAL(pdata, 0, file_flags); /* flags */
+ SIVAL(pdata, 4, flags_mask); /* mask */
+ pdata += 8;
+
+ return pdata;
+}
+
/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
file name or file id).
@@ -2970,6 +3185,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
if(fsp && (fsp->fake_file_handle)) {
/*
* This is actually for the QUOTA_FAKE_FILE --metze
@@ -3026,12 +3245,22 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -3175,18 +3404,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
allocation_size = get_allocation_size(conn,fsp,&sbuf);
if (fsp) {
- if (fsp->pending_modtime) {
+ if (!null_timespec(fsp->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- mtime_ts.tv_sec = fsp->pending_modtime;
- mtime_ts.tv_nsec = 0;
+ mtime_ts = fsp->pending_modtime;
}
} else {
/* Do we have this path open ? */
files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
- if (fsp1 && fsp1->pending_modtime) {
+ if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- mtime_ts.tv_sec = fsp1->pending_modtime;
- mtime_ts.tv_nsec = 0;
+ mtime_ts = fsp1->pending_modtime;
}
if (fsp1 && fsp1->initial_allocation_size) {
allocation_size = get_allocation_size(conn, fsp1, &sbuf);
@@ -3539,6 +3766,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
break;
+ case SMB_QUERY_FILE_UNIX_INFO2:
+
+ pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
+ data_size = PTR_DIFF(pdata,(*ppdata));
+
+ {
+ int i;
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
+
+ for (i=0; i<100; i++)
+ DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
+ DEBUG(4,("\n"));
+ }
+
+ break;
+
case SMB_QUERY_FILE_UNIX_LINK:
{
pstring buffer;
@@ -3743,17 +3986,22 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
return status;
}
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* source must already exist. */
if (!VALID_STAT(sbuf1)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- status = check_name(conn, oldname);
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
+ return status;
}
- status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -3763,11 +4011,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- status = check_name(conn, newname);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* No links from a directory. */
if (S_ISDIR(sbuf1.st_mode)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -3798,7 +4041,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
files_struct *fsp,
const char *fname,
const SMB_STRUCT_STAT *psbuf,
- struct utimbuf tvs)
+ struct timespec ts[2])
{
uint32 action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -3810,26 +4053,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_mtime(tvs.actime)) {
- tvs.actime = psbuf->st_atime;
+ if (null_timespec(ts[0])) {
+ ts[0] = get_atimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = psbuf->st_mtime;
+ if (null_timespec(ts[1])) {
+ ts[1] = get_mtimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
- DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
+ DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
+ DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
/*
* Try and set the times of this file if
* they are different from the current values.
*/
- if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
- return NT_STATUS_OK;
+ {
+ struct timespec mts = get_mtimespec(psbuf);
+ struct timespec ats = get_atimespec(psbuf);
+ if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+ return NT_STATUS_OK;
+ }
}
if(fsp != NULL) {
@@ -3843,15 +4090,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
* away and will set it on file close and after a write. JRA.
*/
- if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
- DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
- fsp_set_pending_modtime(fsp, tvs.modtime);
+ if (!null_timespec(ts[1])) {
+ DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+ time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ fsp_set_pending_modtime(fsp, ts[1]);
}
}
DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
- if(file_utime(conn, fname, &tvs)!=0) {
+ if(file_ntimes(conn, fname, ts)!=0) {
return map_nt_error_from_unix(errno);
}
if (action != 0) {
@@ -4030,6 +4278,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
delete_on_close = (CVAL(pdata,0) ? True : False);
dosmode = dos_mode(conn, fname, psbuf);
+ DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
+ "delete_on_close = %u\n",
+ fsp->fsp_name,
+ (unsigned int)dosmode,
+ (unsigned int)delete_on_close ));
+
status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
if (!NT_STATUS_IS_OK(status)) {
@@ -4132,7 +4386,6 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
pstring rel_name;
char *last_dirp = NULL;
- unix_format(link_target);
if (*link_target == '/') {
/* No absolute paths allowed. */
return NT_STATUS_ACCESS_DENIED;
@@ -4186,7 +4439,10 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
return status;
}
- RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
fname, oldname));
@@ -4211,6 +4467,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
uint32 len;
pstring newname;
pstring base_name;
+ BOOL dest_has_wcard = False;
NTSTATUS status = NT_STATUS_OK;
char *p;
@@ -4226,12 +4483,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+ srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
/* Check the new name has no '/' characters. */
if (strchr_m(newname, '/')) {
@@ -4255,7 +4515,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
} else {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, newname ));
- status = rename_internals(conn, fname, base_name, 0, overwrite, False);
+ status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
}
return status;
@@ -4305,6 +4565,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
+ DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
+ fname ? fname : fsp->fsp_name,
+ (unsigned int)num_file_acls,
+ (unsigned int)num_def_acls));
+
if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
return map_nt_error_from_unix(errno);
@@ -4386,6 +4651,14 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
#endif /* HAVE_LONGLONG */
+ DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
+ "lock_pid = %u, count = %.0f, offset = %.0f\n",
+ fsp->fsp_name,
+ (unsigned int)lock_type,
+ (unsigned int)lock_pid,
+ (double)count,
+ (double)offset ));
+
if (lock_type == UNLOCK_LOCK) {
status = do_unlock(fsp,
lock_pid,
@@ -4439,22 +4712,25 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
const char *fname,
const SMB_STRUCT_STAT *psbuf)
{
- struct utimbuf tvs;
+ struct timespec ts[2];
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
/* access time */
- tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
+ ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
/* write time */
- tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+
+ DEBUG(10,("smb_set_info_standard: file %s\n",
+ fname ? fname : fsp->fsp_name ));
return smb_set_file_time(conn,
fsp,
fname,
psbuf,
- tvs);
+ ts);
}
/****************************************************************************
@@ -4469,10 +4745,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
SMB_STRUCT_STAT *psbuf)
{
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
- time_t write_time;
- time_t changed_time;
+ struct timespec write_time;
+ struct timespec changed_time;
uint32 dosmode = 0;
- struct utimbuf tvs;
+ struct timespec ts[2];
NTSTATUS status = NT_STATUS_OK;
if (total_data < 36) {
@@ -4492,26 +4768,31 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
/* Ignore create time at offset pdata. */
/* access time */
- tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
+ ts[0] = interpret_long_date(pdata+8);
- write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
- changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
+ write_time = interpret_long_date(pdata+16);
+ changed_time = interpret_long_date(pdata+24);
- tvs.modtime = MIN(write_time, changed_time);
+ /* mtime */
+ ts[1] = timespec_min(&write_time, &changed_time);
- if (write_time > tvs.modtime && write_time != (time_t)-1) {
- tvs.modtime = write_time;
+ if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
+ ts[1] = write_time;
}
+
/* Prefer a defined time to an undefined one. */
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+ if (null_timespec(ts[1])) {
+ ts[1] = null_timespec(write_time) ? changed_time : write_time;
}
+ DEBUG(10,("smb_set_file_basic_info: file %s\n",
+ fname ? fname : fsp->fsp_name ));
+
return smb_set_file_time(conn,
fsp,
fname,
psbuf,
- tvs);
+ ts);
}
/****************************************************************************
@@ -4725,7 +5006,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct utimbuf tvs;
+ struct timespec ts[2];
uint32 raw_unixmode;
mode_t unixmode;
SMB_OFF_T size = 0;
@@ -4752,8 +5033,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
#endif /* LARGE_SMB_OFF_T */
}
- tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
- tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
+ ts[0] = interpret_long_date(pdata+24); /* access_time */
+ ts[1] = interpret_long_date(pdata+32); /* modification_time */
set_owner = (uid_t)IVAL(pdata,40);
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
@@ -4796,8 +5077,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
/* Ensure we don't try and change anything else. */
raw_unixmode = SMB_MODE_NO_CHANGE;
size = get_file_size(*psbuf);
- tvs.modtime = psbuf->st_mtime;
- tvs.actime = psbuf->st_atime;
+ ts[0] = get_atimespec(psbuf);
+ ts[1] = get_mtimespec(psbuf);
/*
* We continue here as we might want to change the
* owner uid/gid.
@@ -4876,7 +5157,68 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
fsp,
fname,
psbuf,
- tvs);
+ ts);
+}
+
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_INFO2.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ NTSTATUS status;
+ uint32 smb_fflags;
+ uint32 smb_fmask;
+
+ if (total_data < 116) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Start by setting all the fields that are common between UNIX_BASIC
+ * and UNIX_INFO2.
+ */
+ status = smb_set_file_unix_basic(conn, pdata, total_data,
+ fsp, fname, psbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ smb_fflags = IVAL(pdata, 108);
+ smb_fmask = IVAL(pdata, 112);
+
+ /* NB: We should only attempt to alter the file flags if the client
+ * sends a non-zero mask.
+ */
+ if (smb_fmask != 0) {
+ int stat_fflags = 0;
+
+ if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
+ &stat_fflags)) {
+ /* Client asked to alter a flag we don't understand. */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (fsp && fsp->fh->fd != -1) {
+ /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
+ return NT_STATUS_NOT_SUPPORTED;
+ } else {
+ if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+ }
+
+ /* XXX: need to add support for changing the create_time here. You
+ * can do this for paths on Darwin with setattrlist(2). The right way
+ * to hook this up is probably by extending the VFS utimes interface.
+ */
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -4896,13 +5238,16 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
mode_t unixmode = (mode_t)0;
files_struct *fsp = NULL;
uint16 info_level_return = 0;
+ int info;
char *pdata = *ppdata;
- if (total_data < 10) {
+ if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
}
raw_unixmode = IVAL(pdata,8);
+ /* Next 4 bytes are not yet defined. */
+
status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -4910,6 +5255,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
+ fname, (unsigned int)unixmode ));
+
status = open_directory(conn,
fname,
psbuf,
@@ -4918,19 +5266,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
FILE_CREATE,
0,
mod_unixmode,
- NULL,
+ &info,
&fsp);
if (NT_STATUS_IS_OK(status)) {
close_file(fsp, NORMAL_CLOSE);
}
- info_level_return = SVAL(pdata,12);
+ info_level_return = SVAL(pdata,16);
if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
+ *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
} else {
- *pdata_return_size = 8;
+ *pdata_return_size = 12;
}
/* Realloc the data size */
@@ -4941,15 +5291,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
}
SSVAL(pdata,0,NO_OPLOCK_RETURN);
- SSVAL(pdata,2,0);
-
- if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,6,0); /* Padding. */
- store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
- } else {
- SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,6,0); /* Padding. */
+ SSVAL(pdata,2,0); /* No fnum. */
+ SIVAL(pdata,4,info); /* Was directory created. */
+
+ switch (info_level_return) {
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* Padding. */
}
return status;
@@ -4982,7 +5338,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
int info = 0;
uint16 info_level_return = 0;
- if (total_data < 14) {
+ if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -5034,6 +5390,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
}
raw_unixmode = IVAL(pdata,8);
+ /* Next 4 bytes are not yet defined. */
+
status = unix_perms_from_wire(conn,
psbuf,
raw_unixmode,
@@ -5056,6 +5414,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
mod_unixmode |= FILE_FLAG_NO_BUFFERING;
}
+ DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
+ fname,
+ (unsigned int)wire_open_mode,
+ (unsigned int)unixmode ));
+
status = open_file_ntcreate(conn,
fname,
psbuf,
@@ -5080,12 +5443,16 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
extended_oplock_granted = True;
}
- info_level_return = SVAL(pdata,12);
+ info_level_return = SVAL(pdata,16);
+ /* Allocate the correct return size. */
+
if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
+ *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
} else {
- *pdata_return_size = 8;
+ *pdata_return_size = 12;
}
/* Realloc the data size */
@@ -5109,13 +5476,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
}
SSVAL(pdata,2,fsp->fnum);
- if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,6,0); /* padding. */
- store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
- } else {
- SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,6,0); /* padding. */
+ SIVAL(pdata,4,info); /* Was file created etc. */
+
+ switch (info_level_return) {
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* padding. */
}
return NT_STATUS_OK;
}
@@ -5132,12 +5506,28 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
{
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
+ uint16 flags = 0;
int info = 0;
+ if (total_data < 2) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ flags = SVAL(pdata,0);
+
if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
+ !VALID_STAT_OF_DIR(*psbuf)) {
+ return NT_STATUS_NOT_A_DIRECTORY;
+ }
+
+ DEBUG(10,("smb_posix_unlink: %s %s\n",
+ (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
+ fname));
+
if (VALID_STAT_OF_DIR(*psbuf)) {
status = open_directory(conn,
fname,
@@ -5150,17 +5540,34 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
&info,
&fsp);
} else {
+ char del = 1;
+
status = open_file_ntcreate(conn,
fname,
psbuf,
DELETE_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
- FILE_DELETE_ON_CLOSE,
+ 0,
FILE_FLAG_POSIX_SEMANTICS|0777,
- INTERNAL_OPEN_ONLY,
+ 0, /* No oplock, but break existing ones. */
&info,
&fsp);
+ /*
+ * For file opens we must set the delete on close
+ * after the open.
+ */
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = smb_set_file_disposition_info(conn,
+ &del,
+ 1,
+ fsp,
+ fname,
+ psbuf);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -5251,13 +5658,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
/*
* For CIFS UNIX extensions the target name may not exist.
*/
@@ -5266,12 +5684,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
return UNIXERROR(ERRDOS,ERRbadpath);
}
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
-
}
if (!CAN_WRITE(conn)) {
@@ -5294,9 +5706,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
SSVAL(params,0,0);
- if (fsp && fsp->pending_modtime) {
+ if (fsp && !null_timespec(fsp->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp->pending_modtime;
+ set_mtimespec(&sbuf, fsp->pending_modtime);
}
switch (info_level) {
@@ -5417,6 +5829,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
break;
}
+ case SMB_SET_FILE_UNIX_INFO2:
+ {
+ status = smb_set_file_unix_info2(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
+
case SMB_SET_FILE_UNIX_LINK:
{
if (tran_call != TRANSACT2_SETPATHINFO) {
@@ -5576,6 +5999,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(status);
}
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+ return ERROR_NT(status);
+ }
+
/* Any data in this call is an EA list. */
if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
@@ -5607,12 +6036,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- status = check_name(conn, directory);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
- return ERROR_NT(status);
- }
-
status = create_directory(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source/tdb/common/open.c b/source/tdb/common/open.c
index 3f0c35331b2..c7fd3f66564 100644
--- a/source/tdb/common/open.c
+++ b/source/tdb/common/open.c
@@ -263,6 +263,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
tdb->map_size = st.st_size;
tdb->device = st.st_dev;
tdb->inode = st.st_ino;
+ tdb->max_dead_records = 0;
tdb_mmap(tdb);
if (locked) {
if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
@@ -321,6 +322,15 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
}
}
+/*
+ * Set the maximum number of dead records per hash chain
+ */
+
+void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
+{
+ tdb->max_dead_records = max_dead;
+}
+
/**
* Close a database.
*
diff --git a/source/tdb/common/tdb.c b/source/tdb/common/tdb.c
index bf4c01d1b3a..bf43701d2ed 100644
--- a/source/tdb/common/tdb.c
+++ b/source/tdb/common/tdb.c
@@ -258,6 +258,66 @@ int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct
return 0;
}
+static int tdb_count_dead(struct tdb_context *tdb, u32 hash)
+{
+ int res = 0;
+ tdb_off_t rec_ptr;
+ struct list_struct rec;
+
+ /* read in the hash top */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+ return 0;
+
+ while (rec_ptr) {
+ if (tdb_rec_read(tdb, rec_ptr, &rec) == -1)
+ return 0;
+
+ if (rec.magic == TDB_DEAD_MAGIC) {
+ res += 1;
+ }
+ rec_ptr = rec.next;
+ }
+ return res;
+}
+
+/*
+ * Purge all DEAD records from a hash chain
+ */
+static int tdb_purge_dead(struct tdb_context *tdb, u32 hash)
+{
+ int res = -1;
+ struct list_struct rec;
+ tdb_off_t rec_ptr;
+
+ if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+ return -1;
+ }
+
+ /* read in the hash top */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+ goto fail;
+
+ while (rec_ptr) {
+ tdb_off_t next;
+
+ if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) {
+ goto fail;
+ }
+
+ next = rec.next;
+
+ if (rec.magic == TDB_DEAD_MAGIC
+ && tdb_do_delete(tdb, rec_ptr, &rec) == -1) {
+ goto fail;
+ }
+ rec_ptr = next;
+ }
+ res = 0;
+ fail:
+ tdb_unlock(tdb, -1, F_WRLCK);
+ return res;
+}
+
/* delete an entry in the database given a key */
static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
{
@@ -265,9 +325,42 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
struct list_struct rec;
int ret;
- if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
- return -1;
- ret = tdb_do_delete(tdb, rec_ptr, &rec);
+ if (tdb->max_dead_records != 0) {
+
+ /*
+ * Allow for some dead records per hash chain, mainly for
+ * tdb's with a very high create/delete rate like locking.tdb.
+ */
+
+ if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+ return -1;
+
+ if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) {
+ /*
+ * Don't let the per-chain freelist grow too large,
+ * delete all existing dead records
+ */
+ tdb_purge_dead(tdb, hash);
+ }
+
+ if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
+ tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+ return -1;
+ }
+
+ /*
+ * Just mark the record as dead.
+ */
+ rec.magic = TDB_DEAD_MAGIC;
+ ret = tdb_rec_write(tdb, rec_ptr, &rec);
+ }
+ else {
+ if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK,
+ &rec)))
+ return -1;
+
+ ret = tdb_do_delete(tdb, rec_ptr, &rec);
+ }
if (ret == 0) {
tdb_increment_seqnum(tdb);
@@ -284,6 +377,35 @@ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
return tdb_delete_hash(tdb, key, hash);
}
+/*
+ * See if we have a dead record around with enough space
+ */
+static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
+ struct list_struct *r, tdb_len_t length)
+{
+ tdb_off_t rec_ptr;
+
+ /* read in the hash top */
+ if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+ return 0;
+
+ /* keep looking until we find the right record */
+ while (rec_ptr) {
+ if (tdb_rec_read(tdb, rec_ptr, r) == -1)
+ return 0;
+
+ if (TDB_DEAD(r) && r->rec_len >= length) {
+ /*
+ * First fit for simple coding, TODO: change to best
+ * fit
+ */
+ return rec_ptr;
+ }
+ rec_ptr = r->next;
+ }
+ return 0;
+}
+
/* store an element in the database, replacing any existing element
with the same key
@@ -316,8 +438,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
} else {
/* first try in-place update, on modify or replace. */
if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
- ret = 0;
- goto fail; /* Well, not really failed */
+ goto done;
}
if (tdb->ecode == TDB_ERR_NOEXIST &&
flag == TDB_MODIFY) {
@@ -347,9 +468,56 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
if (dbuf.dsize)
memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
+ if (tdb->max_dead_records != 0) {
+ /*
+ * Allow for some dead records per hash chain, look if we can
+ * find one that can hold the new record. We need enough space
+ * for key, data and tailer. If we find one, we don't have to
+ * consult the central freelist.
+ */
+ rec_ptr = tdb_find_dead(
+ tdb, hash, &rec,
+ key.dsize + dbuf.dsize + sizeof(tdb_off_t));
+
+ if (rec_ptr != 0) {
+ rec.key_len = key.dsize;
+ rec.data_len = dbuf.dsize;
+ rec.full_hash = hash;
+ rec.magic = TDB_MAGIC;
+ if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
+ || tdb->methods->tdb_write(
+ tdb, rec_ptr + sizeof(rec),
+ p, key.dsize + dbuf.dsize) == -1) {
+ goto fail;
+ }
+ goto done;
+ }
+ }
+
+ /*
+ * We have to allocate some space from the freelist, so this means we
+ * have to lock it. Use the chance to purge all the DEAD records from
+ * the hash chain under the freelist lock.
+ */
+
+ if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+ goto fail;
+ }
+
+ if ((tdb->max_dead_records != 0)
+ && (tdb_purge_dead(tdb, hash) == -1)) {
+ tdb_unlock(tdb, -1, F_WRLCK);
+ goto fail;
+ }
+
/* we have to allocate some space */
- if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
+ rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec);
+
+ tdb_unlock(tdb, -1, F_WRLCK);
+
+ if (rec_ptr == 0) {
goto fail;
+ }
/* Read hash top into next ptr */
if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
@@ -368,6 +536,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
goto fail;
}
+ done:
ret = 0;
fail:
if (ret == 0) {
diff --git a/source/tdb/common/tdb_private.h b/source/tdb/common/tdb_private.h
index 7fc136c6a70..10bc6dacdcf 100644
--- a/source/tdb/common/tdb_private.h
+++ b/source/tdb/common/tdb_private.h
@@ -169,6 +169,7 @@ struct tdb_context {
const struct tdb_methods *methods;
struct tdb_transaction *transaction;
int page_size;
+ int max_dead_records;
};
diff --git a/source/tdb/include/tdb.h b/source/tdb/include/tdb.h
index a0f6f983824..51bf709f442 100644
--- a/source/tdb/include/tdb.h
+++ b/source/tdb/include/tdb.h
@@ -94,6 +94,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
const struct tdb_logging_context *log_ctx,
tdb_hash_func hash_fn);
+void tdb_set_max_dead(struct tdb_context *tdb, int max_dead);
int tdb_reopen(struct tdb_context *tdb);
int tdb_reopen_all(int parent_longlived);
diff --git a/source/torture/cmd_vfs.c b/source/torture/cmd_vfs.c
index 6cecd693f83..455ca1c82c7 100644
--- a/source/torture/cmd_vfs.c
+++ b/source/torture/cmd_vfs.c
@@ -783,14 +783,14 @@ static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
- struct utimbuf times;
+ struct timespec ts[2];
if (argc != 4) {
printf("Usage: utime <path> <access> <modify>\n");
return NT_STATUS_OK;
}
- times.actime = atoi(argv[2]);
- times.modtime = atoi(argv[3]);
- if (SMB_VFS_UTIME(vfs->conn, argv[1], &times) != 0) {
+ ts[0] = convert_time_t_to_timespec(atoi(argv[2]));
+ ts[1] = convert_time_t_to_timespec(atoi(argv[3]));
+ if (SMB_VFS_NTIMES(vfs->conn, argv[1], ts) != 0) {
printf("utime: error=%d (%s)\n", errno, strerror(errno));
return NT_STATUS_UNSUCCESSFUL;
}
diff --git a/source/torture/nsstest.c b/source/torture/nsstest.c
index 4b894fbfc34..121679ed8cc 100644
--- a/source/torture/nsstest.c
+++ b/source/torture/nsstest.c
@@ -229,12 +229,15 @@ again:
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
return NULL;
}
if (status != NSS_STATUS_SUCCESS) {
report_nss_error("getgrnam", status);
+ SAFE_FREE(buf);
return NULL;
}
+ SAFE_FREE(buf);
return &grp;
}
@@ -266,12 +269,15 @@ again:
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
+ SAFE_FREE(buf);
return NULL;
}
if (status != NSS_STATUS_SUCCESS) {
report_nss_error("getgrgid", status);
+ SAFE_FREE(buf);
return NULL;
}
+ SAFE_FREE(buf);
return &grp;
}
diff --git a/source/torture/torture.c b/source/torture/torture.c
index 79444946122..5ab28438f21 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -4479,6 +4479,7 @@ static BOOL run_eatest(int dummy)
printf("starting eatest\n");
if (!torture_open_connection(&cli, 0)) {
+ talloc_destroy(mem_ctx);
return False;
}
@@ -4490,6 +4491,7 @@ static BOOL run_eatest(int dummy)
if (fnum == -1) {
printf("open failed - %s\n", cli_errstr(cli));
+ talloc_destroy(mem_ctx);
return False;
}
@@ -4500,6 +4502,7 @@ static BOOL run_eatest(int dummy)
memset(ea_val, (char)i+1, i+1);
if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ talloc_destroy(mem_ctx);
return False;
}
}
@@ -4512,6 +4515,7 @@ static BOOL run_eatest(int dummy)
memset(ea_val, (char)i+1, i+1);
if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ talloc_destroy(mem_ctx);
return False;
}
}
@@ -4545,6 +4549,7 @@ static BOOL run_eatest(int dummy)
slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ talloc_destroy(mem_ctx);
return False;
}
}
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 02a0b68932c..52af6e68d77 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -1118,6 +1118,72 @@ done:
}
/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+
+static ADS_STATUS net_set_os_attributes(TALLOC_CTX *ctx, ADS_STRUCT *ads_s,
+ const char *os_name, const char *os_version )
+{
+ ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *new_dn;
+ ADS_MODLIST mods;
+ LDAPMessage *res = NULL;
+ char *dn_string = NULL;
+ const char *machine_name = global_myname();
+ int count;
+ char *os_sp = NULL;
+
+ if ( !os_name || !os_version ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = ads_find_machine_acct(ads_s, &res, machine_name);
+ if (!ADS_ERR_OK(status))
+ return status;
+
+ if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+ DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+ DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+ goto done;
+ }
+
+ new_dn = talloc_strdup(ctx, dn_string);
+ ads_memfree(ads_s, dn_string);
+ if (!new_dn) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* now do the mods */
+
+ if (!(mods = ads_init_mods(ctx))) {
+ goto done;
+ }
+
+ os_sp = talloc_asprintf( ctx, "Samba %s", SAMBA_VERSION_STRING );
+
+ /* fields of primary importance */
+
+ ads_mod_str(ctx, &mods, "operatingSystem", os_name);
+ ads_mod_str(ctx, &mods, "operatingSystemVersion", os_version);
+ if ( os_sp )
+ ads_mod_str(ctx, &mods, "operatingSystemServicePack", os_sp);
+
+ status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+ ads_msgfree(ads_s, res);
+ TALLOC_FREE( os_sp );
+
+ return status;
+}
+
+/*******************************************************************
join a domain using ADS (LDAP mods)
********************************************************************/
@@ -1386,6 +1452,8 @@ int net_ads_join(int argc, const char **argv)
int i;
fstring dc_name;
struct in_addr dcip;
+ const char *os_name = NULL;
+ const char *os_version = NULL;
nt_status = check_ads_config();
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1427,7 +1495,21 @@ int net_ads_join(int argc, const char **argv)
}
else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
- d_fprintf(stderr, "Please supply a valid OU path\n");
+ d_fprintf(stderr, "Please supply a valid OU path.\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ }
+ else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
+ if ( (os_name = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a operating system name.\n");
+ nt_status = NT_STATUS_INVALID_PARAMETER;
+ goto fail;
+ }
+ }
+ else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
+ if ( (os_version = get_string_param(argv[i])) == NULL ) {
+ d_fprintf(stderr, "Please supply a valid operating system version.\n");
nt_status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
@@ -1546,7 +1628,18 @@ int net_ads_join(int argc, const char **argv)
}
}
+ /* Try to set the operatingSystem attributes if asked */
+
+ if ( os_name && os_version ) {
+ status = net_set_os_attributes( ctx, ads, os_name, os_version );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf(stderr, "Failed to set operatingSystem attributes. "
+ "Are you a Domain Admin?\n");
+ }
+ }
+
/* Now build the keytab, using the same ADS connection */
+
if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
DEBUG(1,("Error creating host keytab!\n"));
}
@@ -1819,13 +1912,16 @@ static int net_ads_printer_publish(int argc, const char **argv)
TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
ADS_MODLIST mods = ads_init_mods(mem_ctx);
char *prt_dn, *srv_dn, **srv_cn;
+ char *srv_cn_escaped = NULL, *printername_escaped = NULL;
LDAPMessage *res = NULL;
if (!ADS_ERR_OK(ads_startup(True, &ads))) {
+ talloc_destroy(mem_ctx);
return -1;
}
if (argc < 1) {
+ talloc_destroy(mem_ctx);
return net_ads_printer_usage(argc, argv);
}
@@ -1853,6 +1949,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
"for %s\n", servername, printername);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
@@ -1864,37 +1961,60 @@ static int net_ads_printer_publish(int argc, const char **argv)
d_fprintf(stderr, "Could not find machine account for server %s\n",
servername);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
srv_cn = ldap_explode_dn(srv_dn, 1);
- asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
+ srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
+ printername_escaped = escape_rdn_val_string_alloc(printername);
+ if (!srv_cn_escaped || !printername_escaped) {
+ SAFE_FREE(srv_cn_escaped);
+ SAFE_FREE(printername_escaped);
+ d_fprintf(stderr, "Internal error, out of memory!");
+ ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
+ return -1;
+ }
+
+ asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn);
+
+ SAFE_FREE(srv_cn_escaped);
+ SAFE_FREE(printername_escaped);
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
if (!pipe_hnd) {
d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
servername);
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
printername))) {
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
if (!ADS_ERR_OK(rc)) {
d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return -1;
}
d_printf("published printer\n");
+ SAFE_FREE(prt_dn);
ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
return 0;
}
@@ -2158,6 +2278,7 @@ static int net_ads_dn_usage(int argc, const char **argv)
"The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
"to show in the results\n\n"\
"Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
+ "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
);
net_common_flags_usage(argc, argv);
return -1;
diff --git a/source/utils/net_ads_gpo.c b/source/utils/net_ads_gpo.c
index 1865aee3d41..83cc2fe8fcf 100644
--- a/source/utils/net_ads_gpo.c
+++ b/source/utils/net_ads_gpo.c
@@ -351,6 +351,7 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
if (argc < 2) {
printf("usage: net ads gpo addlink <linkdn> <gpodn> [options]\n");
+ printf("note: DNs must be provided properly escaped.\n See RFC 4514 for details\n");
return -1;
}
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 34e87ddbd21..56aee3be91a 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -3585,15 +3585,23 @@ static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state
**/
BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
{
+ struct cli_state *targetcli;
+ pstring targetpath;
DEBUG(3,("calling cli_list with mask: %s\n", mask));
- if (cli_list(cp_clistate->cli_share_src, mask, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
- d_fprintf(stderr, "listing %s failed with error: %s\n",
+ if ( !cli_resolve_path( "", cp_clistate->cli_share_src, mask, &targetcli, targetpath ) ) {
+ d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n",
mask, cli_errstr(cp_clistate->cli_share_src));
return False;
}
+ if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
+ d_fprintf(stderr, "listing %s failed with error: %s\n",
+ mask, cli_errstr(targetcli));
+ return False;
+ }
+
return True;
}
@@ -4934,12 +4942,12 @@ static int rpc_file_close(int argc, const char **argv)
* @param str3 strings for FILE_INFO_3
**/
-static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
+static void display_file_info_3( FILE_INFO_3 *info3 )
{
fstring user = "", path = "";
- rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
- rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
+ rpcstr_pull_unistr2_fstring(user, info3->user);
+ rpcstr_pull_unistr2_fstring(path, info3->path);
d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
info3->id, user, info3->perms, info3->num_locks, path);
@@ -4994,8 +5002,7 @@ static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
"\nFileId Opened by Perms Locks Path"\
"\n------ --------- ----- ----- ---- \n");
for (i = 0; i < ctr.num_entries; i++)
- display_file_info_3(&ctr.file.info3[i].info_3,
- &ctr.file.info3[i].info_3_str);
+ display_file_info_3(&ctr.file.info3[i]);
done:
return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
@@ -6072,6 +6079,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (!pipe_hnd) {
DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
nt_errstr(nt_status) ));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6081,6 +6089,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6093,6 +6102,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
}
@@ -6112,6 +6122,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6133,6 +6144,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6151,6 +6163,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
if (!pipe_hnd) {
DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6161,6 +6174,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6173,6 +6187,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Couldn't open domain object. Error was %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
@@ -6191,6 +6206,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
if (NT_STATUS_IS_ERR(nt_status)) {
DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
nt_errstr(nt_status)));
+ cli_shutdown(cli);
talloc_destroy(mem_ctx);
return -1;
};
diff --git a/source/utils/net_sam.c b/source/utils/net_sam.c
index 8800cb36060..bf397803bc5 100644
--- a/source/utils/net_sam.c
+++ b/source/utils/net_sam.c
@@ -1043,6 +1043,7 @@ static int net_sam_provision(int argc, const char **argv)
d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
}
} else {
+ domusers_gid = gmap.gid;
d_printf("found!\n");
}
@@ -1096,6 +1097,7 @@ domu_done:
d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
}
} else {
+ domadmins_gid = gmap.gid;
d_printf("found!\n");
}
@@ -1124,7 +1126,7 @@ doma_done:
d_printf("Adding the Administrator user.\n");
if (domadmins_gid == -1) {
- d_fprintf(stderr, "Can't create Administrtor user, Domain Admins group not available!\n");
+ d_fprintf(stderr, "Can't create Administrator user, Domain Admins group not available!\n");
goto done;
}
if (!winbind_allocate_uid(&uid)) {
@@ -1238,8 +1240,12 @@ doma_done:
smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+ if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
+ }
+ if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+ }
smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
@@ -1261,7 +1267,7 @@ doma_done:
pwd = getpwnam_alloc(NULL, lp_guestaccount());
if (!pwd) {
d_fprintf(stderr, "Failed to find just created Guest account!\n"
- " Is nssswitch properly configured?!\n");
+ " Is nss properly configured?!\n");
goto failed;
}
diff --git a/source/utils/net_status.c b/source/utils/net_status.c
index c68c9f6e2fb..bfc30eac78a 100644
--- a/source/utils/net_status.c
+++ b/source/utils/net_status.c
@@ -104,7 +104,7 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
d_printf("%-10.10s %s %-12s %s",
crec.name,procid_str_static(&crec.pid),
crec.machine,
- time_to_asc(&crec.start));
+ time_to_asc(crec.start));
return 0;
}
@@ -173,7 +173,7 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
guest ? "" : gidtoname(ids->entries[i].gid),
crec.machine,
guest ? "" : ids->entries[i].hostname,
- time_to_asc(&crec.start));
+ time_to_asc(crec.start));
return 0;
}
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index 1e7b361e860..1f0a915574d 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -2303,7 +2303,8 @@ enum {
}
}
- if (opt_domain == NULL || !*opt_domain) {
+ /* Note: if opt_domain is "" then send no domain */
+ if (opt_domain == NULL) {
opt_domain = get_winbind_domain();
}
diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c
index d79ab187a3b..d1a87260fa9 100644
--- a/source/utils/pdbedit.c
+++ b/source/utils/pdbedit.c
@@ -573,6 +573,7 @@ static int new_user (struct pdb_methods *in, const char *username,
if (sscanf(user_sid, "%d", &u_rid) != 1) {
fprintf(stderr, "Error passed string is not a complete user SID or RID!\n");
+ TALLOC_FREE(sam_pwent);
return -1;
}
sid_copy(&u_sid, get_global_sam_sid());
diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c
index ec1e101e061..060079a5735 100644
--- a/source/utils/smbcontrol.c
+++ b/source/utils/smbcontrol.c
@@ -1145,22 +1145,12 @@ int main(int argc, const char **argv)
poptContext pc;
int opt;
- static struct poptOption wbinfo_options[] = {
+ static struct poptOption long_options[] = {
+ POPT_AUTOHELP
{ "timeout", 't', POPT_ARG_INT, &timeout, 't',
"Set timeout value in seconds", "TIMEOUT" },
- { "configfile", 's', POPT_ARG_STRING, NULL, 's',
- "Use alternative configuration file", "CONFIGFILE" },
-
- POPT_TABLEEND
- };
-
- struct poptOption options[] = {
- { NULL, 0, POPT_ARG_INCLUDE_TABLE, wbinfo_options, 0,
- "Options" },
-
- POPT_AUTOHELP
- POPT_COMMON_VERSION
+ POPT_COMMON_SAMBA
POPT_TABLEEND
};
@@ -1171,7 +1161,7 @@ int main(int argc, const char **argv)
/* Parse command line arguments using popt */
pc = poptGetContext(
- "smbcontrol", argc, (const char **)argv, options, 0);
+ "smbcontrol", argc, (const char **)argv, long_options, 0);
poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
"<parameters>");
@@ -1182,11 +1172,6 @@ int main(int argc, const char **argv)
while ((opt = poptGetNextOpt(pc)) != -1) {
switch(opt) {
case 't': /* --timeout */
- argc -= 2;
- break;
- case 's': /* --configfile */
- pstrcpy(dyn_CONFIGFILE, poptGetOptArg(pc));
- argc -= 2;
break;
default:
fprintf(stderr, "Invalid option\n");
@@ -1200,7 +1185,10 @@ int main(int argc, const char **argv)
correct value in the above switch statement. */
argv = (const char **)poptGetArgs(pc);
- argc--; /* Don't forget about argv[0] */
+ argc = 0;
+ while (argv[argc] != NULL) {
+ argc++;
+ }
if (argc == 1)
usage(&pc);
diff --git a/source/utils/status.c b/source/utils/status.c
index 4f66501511b..deba6a9523b 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -162,7 +162,7 @@ static void print_share_mode(const struct share_mode_entry *e,
d_printf("NONE ");
}
- d_printf(" %s %s %s",sharepath, fname, time_to_asc((time_t *)&e->time.tv_sec));
+ d_printf(" %s %s %s",sharepath, fname, time_to_asc((time_t)e->time.tv_sec));
}
}
@@ -207,7 +207,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
d_printf("%-10s %s %-12s %s",
crec.name,procid_str_static(&crec.pid),
crec.machine,
- time_to_asc(&crec.start));
+ time_to_asc(crec.start));
return 0;
}
diff --git a/source/utils/status_profile.c b/source/utils/status_profile.c
index 9224fc176cb..b4c4940f3fd 100644
--- a/source/utils/status_profile.c
+++ b/source/utils/status_profile.c
@@ -113,8 +113,8 @@ BOOL status_profile_dump(BOOL verbose)
d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time);
d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count);
d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time);
- d_printf("utime_count: %u\n", profile_p->syscall_utime_count);
- d_printf("utime_time: %u\n", profile_p->syscall_utime_time);
+ d_printf("ntimes_count: %u\n", profile_p->syscall_ntimes_count);
+ d_printf("ntimes_time: %u\n", profile_p->syscall_ntimes_time);
d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count);
d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time);
d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count);
diff --git a/source/web/statuspage.c b/source/web/statuspage.c
index 459b679d817..a88e5debd0e 100644
--- a/source/web/statuspage.c
+++ b/source/web/statuspage.c
@@ -101,7 +101,7 @@ static char *mapPid2Machine (struct process_id pid)
static char *tstring(time_t t)
{
static pstring buf;
- pstrcpy(buf, time_to_asc(&t));
+ pstrcpy(buf, time_to_asc(t));
all_string_sub(buf," ","&nbsp;",sizeof(buf));
return buf;
}