r653: Ok, so tridge convinced me. Allow full UNIX path symlinks
authorJeremy Allison <jra@samba.org>
Wed, 12 May 2004 00:35:43 +0000 (00:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:51:32 +0000 (10:51 -0500)
to anywhere on the server filesystem so long as widelinks
is set to true.... :-).
Jeremy.
(This used to be commit ba9809fcd493a53b33c3a24c9f91b0c1d9bd9726)

source3/include/trans2.h
source3/smbd/trans2.c

index 98a4fc09768fbc1e01990d7c43f62f6baedd4329..3106cd092ab018505031d2c429cecb371218b92b 100644 (file)
@@ -450,7 +450,6 @@ Offset Size         Name
 #define CIFS_UNIX_FCNTL_LOCKS_CAP           0x1
 #define CIFS_UNIX_POSIX_ACLS_CAP            0x2
 
-#define CIFS_CLIENT_SYMLINK_STRING     "smbln:"
 /* ... more as we think of them :-). */
 
 #endif
index 825bae86bb953dfa6e34eea251d3155dce6d96b7..a0e00cfcfe0471a8d17f1ec6f4aebd38f256985b 100644 (file)
@@ -2762,7 +2762,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
                                pstring buffer;
-                               char *bufp = buffer;
 
                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
 #ifdef S_ISLNK
@@ -2775,11 +2774,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                                if (len == -1)
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                                buffer[len] = 0;
-                               if (strncmp(buffer, CIFS_CLIENT_SYMLINK_STRING, strlen(CIFS_CLIENT_SYMLINK_STRING)) == 0) {
-                                       bufp += strlen(CIFS_CLIENT_SYMLINK_STRING);
-                               }
-
-                               len = srvstr_push(outbuf, pdata, bufp, -1, STR_TERMINATE);
+                               len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
                                pdata += len;
                                data_size = PTR_DIFF(pdata,(*ppdata));
 
@@ -2929,6 +2924,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in
                errno = EACCES;
                return -1;
        }
+
        return 0;
 }
 
@@ -2972,6 +2968,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if (!check_name(oldname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
        if (!rcdest && bad_path_newname) {
                return NT_STATUS_OBJECT_PATH_NOT_FOUND;
@@ -2989,6 +2989,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
+       if (!check_name(newname,conn)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -3492,9 +3496,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
 
                case SMB_SET_FILE_UNIX_LINK:
                {
-                       pstring oldname;
+                       pstring link_target;
                        char *newname = fname;
-                       BOOL cifs_client_link = False;
 
                        /* Set a symbolic link. */
                        /* Don't allow this if follow links is false. */
@@ -3502,16 +3505,15 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                        if (!lp_symlinks(SNUM(conn)))
                                return(ERROR_DOS(ERRDOS,ERRnoaccess));
 
-                       srvstr_pull(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE);
-                       unix_format(oldname);
+                       srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
 
-                       if (*oldname == '/') {
-                               /* Absolute paths are automatically a client resolved link. */
-                               cifs_client_link = True;
-                       } else {
+                       /* !widelinks forces the target path to be within the share. */
+                       if (!lp_widelinks(SNUM(conn))) {
                                pstring rel_name;
                                char *last_dirp = NULL;
 
+                               unix_format(link_target);
+
                                pstrcpy(rel_name, newname);
                                last_dirp = strrchr_m(rel_name, '/');
                                if (last_dirp) {
@@ -3519,23 +3521,20 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                } else {
                                        pstrcpy(rel_name, "./");
                                }
-                               pstrcat(rel_name, oldname);
-                               if (ensure_link_is_safe(conn, rel_name, rel_name) != 0)
-                                       cifs_client_link = True;
-
-                       }
+                               pstrcat(rel_name, link_target);
+                               if (ensure_link_is_safe(conn, rel_name, rel_name) != 0) {
+                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               }
 
-                       if (cifs_client_link) {
-                               pstring tmp_name;
-                               pstrcpy(tmp_name, CIFS_CLIENT_SYMLINK_STRING);
-                               pstrcat(tmp_name, oldname);
-                               pstrcpy(oldname, tmp_name);
+                               if (check_name(link_target, conn)) {
+                                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+                               }
                        }
 
                        DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
-                               fname, oldname ));
+                               fname, link_target ));
 
-                       if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0)
+                       if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
                                return(UNIXERROR(ERRDOS,ERRnoaccess));
                        SSVAL(params,0,0);
                        send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);