Commit 327f9b96 authored by Jeremy Allison's avatar Jeremy Allison Committed by Gerald (Jerry) Carter
Browse files

r653: Ok, so tridge convinced me. Allow full UNIX path symlinks

to anywhere on the server filesystem so long as widelinks
is set to true.... :-).
Jeremy.
(This used to be commit ba9809fcd493a53b33c3a24c9f91b0c1d9bd9726)
parent 758e36a9
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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
+25 −26
Original line number Diff line number Diff line
@@ -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);