responsible for 3rd party projects that work with Samba
(e.g. vfs modules).
-Note that this list is for you benefit, but please do not
+Note that this list is for your benefit, but please do not
abuse it by constantly emailing a stream of help questions
to the maintainers. Some are more open to direct
communication than others and some struggle with enormous
libsmbclient Derrell Lipman <derrell@samba.org>
-pdb_*sql <samba-pdbsql@samba.org>
- Peter Rindfuss: pdb_mysql
- Darrell McGuire: pdb_mysql
- Ulrich Meis: pdb_pgsql
- Filip Jirsák: pdb_pgsql
+pdb_*sql Wilco Baan Hofman <synnack@users.sf.net>
+ Florian Effenberger <floeff@users.sf.net>
+
+ http://pdbsql.sourceforge.net/
printing Gerald (Jerry) Carter <jerry@samba.org>
idmap expire time New 900
idmap negative time New 120
kernel change notify Per share Yes
- max stat cache size Modified 1024MB
+ max stat cache size Modified 1024KB
printjob username New %U
winbind normalize names New no
o Jiri Sasek <Jiri.Sasek@Sun.COM>
- I Fix possible NULL dereference in adt_tree.c
+ * Fix possible NULL dereference in adt_tree.c
o Karolin Seeger <ks@sernet.de>
- * Improvements to 'net sam policy'
+ * Add 'net sam policy' commands.
* Fixes for "net usershare" and "guest_ok=y"
rm -f core *~ *% *.bak *.o *.$(SHLIBEXT)
distclean: clean
- rm config.* Makefile
+ rm -f config.status config.cache Makefile
PICSUFFIX="po"
SHLIBEXT="so"
+# Since we are not embedded in the Samba tree, building shared modules is
+# really the only option.
+enable_shared=yes
+
if test "$enable_shared" = "yes"; then
# this bit needs to be modified for each OS that is suported by
# smbwrapper. You need to specify how to created a shared library and
* --metze
*/
+/* NOTE: As of approximately Samba 3.0.24, the vfswrap_* functions are not
+ * global symbols. They are included here only as an pointer that opaque
+ * operations should not call further into the VFS.
+ */
+
static int skel_connect(vfs_handle_struct *handle, const char *service, const char *user)
{
return 0;
return vfswrap_getwd(NULL, buf);
}
-static int skel_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+static int skel_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
{
- return vfswrap_utime(NULL, path, times);
+ return vfswrap_ntimes(NULL, path, ts);
}
static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
return vfswrap_symlink(NULL, oldpath, newpath);
}
+
static int skel_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
{
return vfswrap_readlink(NULL, path, buf, bufsiz);
return vfswrap_realpath(NULL, path, resolved_path);
}
-static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+static NTSTATUS skel_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)
+{
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static int skel_chflags(vfs_handle_struct *handle, const char *path, uint flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, uint32 security_info, SEC_DESC **ppdesc)
{
errno = ENOSYS;
return 0;
}
-static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ const char *name, uint32 security_info, SEC_DESC **ppdesc)
{
errno = ENOSYS;
return 0;
}
-static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int
+ fd, uint32 security_info_sent, SEC_DESC *psd)
{
errno = ENOSYS;
return False;
}
-static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const
+ char *name, uint32 security_info_sent, SEC_DESC *psd)
{
errno = ENOSYS;
return False;
{SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_OPAQUE},
- {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_notify_watch), SMB_VFS_OP_NOTIFY_WATCH, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_chflags), SMB_VFS_OP_CHFLAGS, SMB_VFS_LAYER_OPAQUE},
+
+
/* NT File ACL operations */
return SMB_VFS_NEXT_GETWD(handle, buf);
}
-static int skel_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+static int skel_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 int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
}
-static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+static NTSTATUS skel_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)
+{
+ return SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, e, callback,
+ private_data, handle_p);
+}
+
+static int skel_chflags(vfs_handle_struct *handle, const char *path, uint flags)
+{
+ return SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, uint32 security_info, SEC_DESC **ppdesc)
{
return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc);
}
-static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ const char *name, uint32 security_info, SEC_DESC **ppdesc)
{
return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info, ppdesc);
}
-static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ int fd, uint32 security_info_sent, SEC_DESC *psd)
{
return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, fd, security_info_sent, psd);
}
-static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+ const char *name, uint32 security_info_sent, SEC_DESC *psd)
{
return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd);
}
{SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_TRANSPARENT},
- {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_notify_watch), SMB_VFS_OP_NOTIFY_WATCH, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_chflags), SMB_VFS_OP_CHFLAGS, SMB_VFS_LAYER_TRANSPARENT},
/* NT File ACL operations */
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@ \
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
$(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) \
@$(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
# 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 #
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 */
/* 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 ) {
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));
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..... */
}
} 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));
finfo->name,
attrib_string(finfo->mode),
(double)finfo->size,
- time_to_asc(&t));
+ time_to_asc(t));
dir_total += finfo->size;
} else {
pstring afname;
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);
}
return;
p[1] = 0;
pstrcat(mask2, f->name);
- pstrcat(mask2,"\\*");
+ pstrcat(mask2,CLI_DIRSEP_STR);
+ pstrcat(mask2,"*");
add_to_do_list_queue(mask2);
}
return;
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();
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) {
return 1;
}
pstrcpy(lname,p);
- dos_clean_name(rname);
+ clean_name(rname);
next_token_nr(NULL,lname,NULL,sizeof(lname));
unlink(lname);
return 1;
}
- dos_clean_name(rname);
+ clean_name(rname);
rc = do_get(rname, lname, False);
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);
else
pstrcat(rname,lname);
- dos_clean_name(rname);
+ clean_name(rname);
{
SMB_STRUCT_STAT st;
{
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);
}
}
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");
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;
}
-
/****************************************************************************
****************************************************************************/
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;
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';
{
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");
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;
}
return 1;
}
-
if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
d_printf("%s getfacl doing a stat on file %s\n",
cli_errstr(targetcli), src);
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");
}
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");
}
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");
}
return 1;
}
-
if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
d_printf("Server doesn't support UNIX CIFS calls.\n");
return 1;
{
pstring src,dest;
pstring buf,buf2;
+ struct cli_state *targetcli;
+ pstring targetname;
pstrcpy(src,cur_dir);
pstrcpy(dest,cur_dir);
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;
}
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;
}
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));
else
pstrcat(remote_name, local_name);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
return do_put(remote_name, local_name, True);
}
{"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}},
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",
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 {
#define MS_MOVE 8192
#endif
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
+
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
const char *thisprogram;
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);
finfo->name,
attrib_string(finfo->mode),
(double)finfo->size,
- time_to_asc(&t));
+ time_to_asc(t));
dir_total += finfo->size;
}
}
{
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);
unlink(lname);
return 1;
}
- dos_clean_name(rname);
+ clean_name(rname);
rc = do_get(rname, lname, False);
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;
}
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));
else
pstrcat(remote_name, local_name);
- dos_clean_name(remote_name);
+ clean_name(remote_name);
return do_put(remote_name, local_name, True);
}
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)
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,[
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
[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
*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!)
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
NSSSONAMEVERSIONSUFFIX=""
+SMB_KRB5_LOCATOR="bin/smb_krb5_locator.$SHLIBEXT"
+
case "$host_os" in
*linux*)
NSSSONAMEVERSIONSUFFIX=".2"
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
AC_SUBST(NSSSONAMEVERSIONSUFFIX)
+AC_SUBST(SMB_KRB5_LOCATOR)
+
# Check the setting of --with-winbind
AC_ARG_WITH(winbind,
* 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;
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
#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)
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 */
};
struct junction_map {
- pstring service_name;
+ fstring service_name;
pstring volume_name;
pstring comment;
int referral_count;
};
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", \
#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
/* 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 \
#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
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
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
{
} 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
{
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 */
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;
#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)
/*
Unix SMB/CIFS implementation.
SMB transaction2 handling
+
+ Copyright (C) James Peach 2007
Copyright (C) Jeremy Allison 1994-2002.
Extensively modified by Andrew Tridgell, 1995
#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" */
#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
#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
*/
+#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
#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)
#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.
*/
#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
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 */
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,
SMB_VFS_OP_MKNOD,
SMB_VFS_OP_REALPATH,
SMB_VFS_OP_NOTIFY_WATCH,
+ SMB_VFS_OP_CHFLAGS,
/* NT ACL operations. */
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);
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. */
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;
struct vfs_handle_struct *mknod;
struct vfs_handle_struct *realpath;
struct vfs_handle_struct *notify_watch;
+ struct vfs_handle_struct *chflags;
/* NT ACL operations. */
#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)))
#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)))
#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)))
#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)))
#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)))
#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)))
/* 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';
}
/* 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;
}
+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
****************************************************************************/
*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;
+}
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);
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++) {
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);
/* 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);
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));
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
}
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
#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
#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)
*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 ||
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
********************************************************************/
}
/*******************************************************************
-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);
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);
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;
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);
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;
#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;
#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;
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
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;
if (t == (time_t)-1) {
/* that's what NT uses for infinite */
- *nt = 0x8000000000000000LL;
+ *nt = NTTIME_INFINITY;
return;
}
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";
if (nttime==0)
return "Now";
- if (nttime==0x8000000000000000LL)
+ if (nttime==NTTIME_INFINITY)
return "Never";
high = 65536;
return False;
}
- if (*nt == 0x8000000000000000LL) {
+ if (*nt == NTTIME_INFINITY) {
return False;
}
return True;
}
-
gfree_debugsyms();
gfree_charcnv();
gfree_messages();
+ gfree_interfaces();
/* release the talloc null_context memory last */
talloc_disable_null_tracking();
/* 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;
}
trim_string(s,NULL,"\\..");
-
all_string_sub(s, "\\.\\", "\\", 0);
}
}
trim_string(s,NULL,"/..");
+ all_string_sub(s, "/./", "/", 0);
+}
+
+void clean_name(char *s)
+{
+ dos_clean_name(s);
+ unix_clean_name(s);
}
/*******************************************************************
#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
}
-/****************************************************************************
- 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.
****************************************************************************/
return NULL;
}
-#if defined(PARANOID_MALLOC_CHECKER)
- return memalign_(align, el_size*count);
-#else
return sys_memalign(align, el_size*count);
-#endif
}
/****************************************************************************
/* check for loopback */
+ if (strequal(servername, "127.0.0.1"))
+ return True;
+
if (strequal(servername, "localhost"))
return True;
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 );
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 );
{
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);
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;
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;
}
#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));
}
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;
}
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;
}
}
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;
}
}
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;
}
}
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
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;
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
}
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);
* 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 {
if (keytab) {
krb5_kt_close(context, keytab);
}
+ *perr = ret;
return auth_ok;
}
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;
}
/* 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;
}
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",
/* 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;
}
out:
SAFE_FREE(password_s);
-
+ *perr = ret;
return auth_ok;
}
***********************************************************************************/
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)
{
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);
}
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) {
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;
}
}
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();
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;
}
}
*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);
{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}
};
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};
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 ) {
ret = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(machine_escaped);
ads_msgfree(ads, res);
talloc_destroy(ctx);
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};
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))))
status = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(name_escaped);
talloc_destroy(ctx);
return status;
}
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")))
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)))
status = ads_gen_add(ads, new_dn, mods);
done:
+ SAFE_FREE(name_escaped);
talloc_destroy(ctx);
return status;
}
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
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);
}
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) {
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;
--- /dev/null
+/*
+ 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
} \
} 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)) { \
/*
- 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;
}
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);
}
}
}
+ data_blob_free(&msg1);
}
if (!blob.length) {
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,
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
#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;
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;
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;
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;
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;
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;
}
}
connections = NULL;
-
return;
}
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);
}
/********************************************************************
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;
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;
p += ref_size;
}
-
}
*num_refs = num_referrals;
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;
}
pstring fullpath;
BOOL res;
uint16 cnum;
+ pstring newextrapath;
if ( !cli || !sharename )
return False;
/* 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 */
}
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 */
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 = ¶m[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, ¶m_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 = ¶m[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, ¶m_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);
+}
krb5_error_code ret;
char *utf8_name;
+ *principal = NULL;
if (push_utf8_allocate(&utf8_name, name) == (size_t)-1) {
return ENOMEM;
}
krb5_error_code ret;
char *utf8_name;
+ *unix_name = NULL;
ret = krb5_unparse_name(context, principal, &utf8_name);
if (ret) {
return ret;
}
#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,
*p_resume_key = 0;
}
memcpy(finfo,&def_finfo,sizeof(*finfo));
+ finfo->cli = cli;
switch (level) {
case 1: /* OS/2 understands this */
/* 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++;
*finfo = def_finfo;
+ finfo->cli = cli;
finfo->mode = CVAL(p,21);
/* this date is converted to GMT by make_unix_date */
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);
}
#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,
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 */
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;
}
/****************************************************************************
-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;
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)
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,
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,
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,
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)
{
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,
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 )
{
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);
}
/****************************************************************************
-send a qfileinfo call
+ Send a qfileinfo call.
****************************************************************************/
BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
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;
{ "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 },
};
/*****************************************************************************
- 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;
{ 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 },
#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
}
/*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) {
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,
lock_path("brlock.tdb")));
return;
}
+
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
}
/****************************************************************************
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;
}
return NT_STATUS_RANGE_NOT_LOCKED;
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
+ SMB_ASSERT(fsp->current_lock_count > 0);
+ fsp->current_lock_count--;
+
return NT_STATUS_OK;
}
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) {
return False;
}
+ /* Activate the per-hashchain freelist */
+ tdb_set_max_dead(tdb, 5);
+
if (!posix_locking_init(read_only))
return False;
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;
}
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 */
}
}
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);
}
{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},
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,
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},
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
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;
}
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);
return -1;
result = linux_setlease(fd, leasetype);
-
+#else
+ errno = ENOSYS;
#endif
END_PROFILE(syscall_linux_setlease);
return result;
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;
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},
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. */
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,
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);
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},
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. */
{ 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" },
{ 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" },
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;
}
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)
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));
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));
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));
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));
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;
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)));
}
}
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;
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
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 ) {
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;
}
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 */
backend_init_status = NT_STATUS_OK;
- return NT_STATUS_OK;
+ return ret;
done:
DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
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;
}
/* 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;
dictionary *d = NULL;
char *username_ret = NULL;
char *new_authtok_required = NULL;
- char *combined_member = NULL;
const char *real_username = NULL;
/* parse arguments */
/* 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 */
/* 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;
close_sock();
our_pid = getpid();
}
+
+ if ((need_priv != 0) && (is_privileged == 0)) {
+ close_sock();
+ }
if (winbindd_fd != -1) {
return winbindd_fd;
return -1;
}
+ is_privileged = 0;
+
/* version-check the socket */
request.flags = WBFLAG_RECURSE;
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;
/* 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;
restart:
- if (winbind_open_pipe_sock(recursing) == -1) {
+ if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
return -1;
}
* 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;
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;
}
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);
#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);
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) {
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 */
/* 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);
#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
{
ADS_STRUCT *ads;
ADS_STATUS status;
+ fstring dc_name;
+ struct in_addr dc_ip;
DEBUG(10,("ads_cached_connection\n"));
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",
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"));
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)));
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);
}
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();
* 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)) )
/* 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)) {
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)) {
/* 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);
/* 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) {
{
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));
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;
}
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;
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 ));
*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;
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];
}
}
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);
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;
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;
}
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",
int winbind_cache_time;
int winbind_max_idle_children;
char **szWinbindNssInfo;
- int iLockSpinCount;
int iLockSpinTime;
char *szLdapMachineSuffix;
char *szLdapUserSuffix;
BOOL bClientNTLMv2Auth;
BOOL bClientPlaintextAuth;
BOOL bClientUseSpnego;
+ BOOL bDebugPrefixTimestamp;
BOOL bDebugHiresTimestamp;
BOOL bDebugPid;
BOOL bDebugUid;
{"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},
{"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},
{"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},
Globals.bSyslogOnly = False;
Globals.bTimestampLogs = True;
string_set(&Globals.szLogLevel, "0");
+ Globals.bDebugPrefixTimestamp = False;
Globals.bDebugHiresTimestamp = False;
Globals.bDebugPid = False;
Globals.bDebugUid = False;
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;
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)
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)
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
*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;
*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;
*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;
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;
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,
}
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, "))");
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 */
}
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;
}
if (num_result == 0) {
+ char *escape_name;
+
DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
is_new_entry = True;
}
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"));
uint32 num_result;
LDAPMod **mods = NULL;
char *filter;
+ char *escape_username;
char *gidstr;
const char *dn = NULL;
gid_t gid;
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;
}
dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
if (!dn) {
+ ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
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,
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));
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 */
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;
}
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));
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));
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));
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));
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",
{
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;
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");
****************************************************************************/
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",
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 */
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);
/*
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);
"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 */
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
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);
+ }
}
* 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
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 );
+ }
}
/*******************************************************************
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;
}
return True;
}
-/*******************************************************************
- 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;
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.
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;
}
return True;
}
-/*******************************************************************
- 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");
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;
return True;
}
-/*******************************************************************
- 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;
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;
}
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;
}
/*******************************************************************
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;
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;
}
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;
}
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;
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");
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;
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;
}
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.
********************************************************************/
return True;
}
-/*******************************************************************
- 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.
********************************************************************/
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))
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;
+}
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;
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;
{
struct current_user user;
struct junction_map jn;
+ BOOL self_ref = False;
+ int consumedcnt = 0;
BOOL found = False;
pstring dfspath, servername, sharename;
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;
}
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);
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;
}
/* FIXME: Implement your code here */
return WERR_NOT_SUPPORTED;
}
-
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);
init_samr_r_query_aliasmem(r_u, num_sids, sid, NT_STATUS_OK);
- SAFE_FREE(sids);
+ TALLOC_FREE(sids);
return NT_STATUS_OK;
}
* 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
return True;
}
+/*******************************************************************
+*******************************************************************/
+
+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
********************************************************************/
{ "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 )
* 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
#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.
********************************************************************/
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:");
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);
}
r_n->status = status;
}
-/*******************************************************************
- 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.
********************************************************************/
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++;
}
}
/*******************************************************************
- 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;
}
/*******************************************************************
{
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);
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;
}
/*******************************************************************
return r_u->status;
}
-/*******************************************************************
-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
********************************************************************/
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;
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;
+}
+
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;
}
* 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);
}
}
if (hide_unreadable || hide_unwriteable || hide_special) {
+ pstring link_target;
char *entry = NULL;
if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
/* 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;
}
}
/* 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. */
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. */
}
/*******************************************************************
- 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;
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
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();
}
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, ×)) {
+ if (file_ntimes(conn, fname, ts)) {
DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
return False;
}
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
- return(True);
-}
+ return True;
+}
* 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();
}
}
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;
}
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;
}
}
/*
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
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;
}
/********************************************************
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;
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)) {
/**********************************************************************
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;
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];
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;
}
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
* 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;
}
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 */
}
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;
}
*/
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;
}
ref->proximity = 0;
ref->ttl = REFERRAL_TTL;
jucn->referral_list = ref;
- if (consumedcntp) {
- *consumedcntp = strlen(pathname);
- }
+ *consumedcntp = strlen(dfs_path);
ret = True;
goto out;
}
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:
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;
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);
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;
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;
}
/******************************************************************
- 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"))) {
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;
**********************************************************************/
/*********************************************************************
- 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;
}
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;
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;
}
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) {
}
}
- 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) {
ret = True;
-
+
out:
conn_free_internal(conn);
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;
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;
}
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 */
}
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++;
+ }
}
}
}
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;
+}
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
#ifdef HAVE_INOTIFY
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
#include <linux/inotify.h>
#include <asm/unistd.h>
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));
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;
(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()) {
return(ERROR_DOS(ERRDOS,ERRnoaccess));
}
}
-
+
if (create_options & FILE_OPEN_BY_FILE_ID) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
if(!dir_fsp) {
END_PROFILE(SMBntcreateX);
- return(ERROR_DOS(ERRDOS,ERRbadfid));
+ return ERROR_DOS(ERRDOS,ERRbadfid);
}
if(!dir_fsp->is_directory) {
return ERROR_NT(status);
}
- /*
+ /*
* Check to see if this is a mac fork of some kind.
*/
* 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++;
}
return ERROR_NT(status);
}
- /*
+ /*
* Check to see if this is a mac fork of some kind.
*/
* 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) {
}
}
- /*
+ /*
* 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,
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
+
} else {
+
/*
* Ordinary file case.
*/
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,
return ERROR_NT(status);
}
} else {
-
restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
}
restore_case_semantics(conn, file_attributes);
-
+
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
if(fattr == 0) {
* 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;
}
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);
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;
}
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)) {
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
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,
* 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;
}
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)) {
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;
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);
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);
}
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 {
}
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 {
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) {
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))) {
uint32 file_attributes,
SMB_STRUCT_STAT *psbuf)
{
- int ret= -1;
mode_t mode;
char *parent_dir;
const char *dirname;
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);
}
return ERROR_DOS(ERRDOS,ERRbadfid);
}
- /* TODO: REMOVE PIPE FROM DB */
-
return(outsize);
}
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;
/* 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);
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
{
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;
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;
*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')) {
}
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" ! */
/*
/* 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;
}
if (!(*s & 0x80)) {
- if (windows_path) {
+ if (!posix_path) {
if (*s <= 0x1f) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
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);
}
/****************************************************************************
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);
}
/****************************************************************************
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);
}
/****************************************************************************
*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 {
} 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 {
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)));
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! */
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)) {
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
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);
}
}
- if (!set_filetime(conn,fname,mtime)) {
+ if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
END_PROFILE(SMBsetatr);
return UNIXERROR(ERRDOS, ERRnoaccess);
}
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);
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)) {
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);
}
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;
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)) {
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);
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)) {
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,
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;
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)) {
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)) {
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));
}
return ERROR_NT(status);
}
- times.actime = sbuf.st_atime;
- file_utime(conn, fname, ×);
+ ts[0] = get_atimespec(&sbuf); /* atime. */
+ file_ntimes(conn, fname, ts);
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
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) {
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;
}
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;
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));
{
NTSTATUS status = NT_STATUS_OK;
int outsize = 0;
- time_t mtime;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
* 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
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);
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)) {
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.
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)) {
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)));
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)) {
char *p,*p2, *pname1, *pname2;
int available_space, actual_space;
-
pname1 = strrchr_m(name1,'/');
pname2 = strrchr_m(name2,'/');
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;
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;
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;
}
* 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.
*/
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,
}
}
- 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.
*/
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);
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))) {
* 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;
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
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);
*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);
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);
* 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;
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);
}
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)) {
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);
* 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);
}
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);
#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;
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);
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));
}
/****************************************************************************
- 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 --
#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
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.
****************************************************************************/
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
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 */
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);
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
#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.
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;
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 {
/* 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;
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);
}
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)) {
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);
}
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;
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;
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(¤t_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(¤t_user.nt_user_token->user_sids[i]);
+
+ sid_linearize(pdata + data_len, sid_len,
+ ¤t_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
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));
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).
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
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, ¶ms[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)) {
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);
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;
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;
}
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;
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
}
/* 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) {
* 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) {
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)) {
pstring rel_name;
char *last_dirp = NULL;
- unix_format(link_target);
if (*link_target == '/') {
/* No absolute paths allowed. */
return NT_STATUS_ACCESS_DENIED;
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));
uint32 len;
pstring newname;
pstring base_name;
+ BOOL dest_has_wcard = False;
NTSTATUS status = NT_STATUS_OK;
char *p;
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, '/')) {
} 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;
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);
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,
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);
}
/****************************************************************************
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) {
/* 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);
}
/****************************************************************************
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;
#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);
/* 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.
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;
}
/****************************************************************************
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;
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,
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 */
}
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;
int info = 0;
uint16 info_level_return = 0;
- if (total_data < 14) {
+ 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,
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,
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 */
}
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;
}
{
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,
&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)) {
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.
*/
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)) {
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) {
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) {
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);
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)) {
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) {
}
}
+/*
+ * 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.
*
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)
{
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);
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
} 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) {
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)
goto fail;
}
+ done:
ret = 0;
fail:
if (ret == 0) {
const struct tdb_methods *methods;
struct tdb_transaction *transaction;
int page_size;
+ int max_dead_records;
};
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);
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], ×) != 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;
}
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;
}
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;
}
printf("starting eatest\n");
if (!torture_open_connection(&cli, 0)) {
+ talloc_destroy(mem_ctx);
return False;
}
if (fnum == -1) {
printf("open failed - %s\n", cli_errstr(cli));
+ talloc_destroy(mem_ctx);
return False;
}
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;
}
}
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;
}
}
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;
}
}
return status;
}
+/*******************************************************************
+ 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)
********************************************************************/
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)) {
}
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;
}
}
}
+ /* 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"));
}
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);
}
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;
}
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;
}
"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;
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;
}
**/
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;
}
* @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);
"\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;
}
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;
};
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;
};
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;
}
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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
}
} else {
+ domusers_gid = gmap.gid;
d_printf("found!\n");
}
d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
}
} else {
+ domadmins_gid = gmap.gid;
d_printf("found!\n");
}
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)) {
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,
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;
}
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;
}
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;
}
}
}
- if (opt_domain == NULL || !*opt_domain) {
+ /* Note: if opt_domain is "" then send no domain */
+ if (opt_domain == NULL) {
opt_domain = get_winbind_domain();
}
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());
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
};
/* 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>");
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");
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);
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));
}
}
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;
}
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);
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," "," ",sizeof(buf));
return buf;
}