github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/dockerfile/copy_windows.go (about)

     1  package dockerfile // import "github.com/Prakhar-Agarwal-byte/moby/builder/dockerfile"
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	winio "github.com/Microsoft/go-winio"
    10  	"github.com/Prakhar-Agarwal-byte/moby/pkg/idtools"
    11  	"github.com/Prakhar-Agarwal-byte/moby/pkg/reexec"
    12  	"github.com/Prakhar-Agarwal-byte/moby/pkg/system"
    13  	"github.com/pkg/errors"
    14  	"golang.org/x/sys/windows"
    15  )
    16  
    17  var pathDenyList = map[string]bool{
    18  	`c:\`:        true,
    19  	`c:\windows`: true,
    20  }
    21  
    22  func init() {
    23  	reexec.Register("windows-fix-permissions", fixPermissionsReexec)
    24  }
    25  
    26  func fixPermissions(source, destination string, identity idtools.Identity, _ bool) error {
    27  	if identity.SID == "" {
    28  		return nil
    29  	}
    30  
    31  	cmd := reexec.Command("windows-fix-permissions", source, destination, identity.SID)
    32  	output, err := cmd.CombinedOutput()
    33  
    34  	return errors.Wrapf(err, "failed to exec windows-fix-permissions: %s", output)
    35  }
    36  
    37  func fixPermissionsReexec() {
    38  	err := fixPermissionsWindows(os.Args[1], os.Args[2], os.Args[3])
    39  	if err != nil {
    40  		fmt.Fprint(os.Stderr, err)
    41  		os.Exit(1)
    42  	}
    43  }
    44  
    45  func fixPermissionsWindows(source, destination, SID string) error {
    46  	privileges := []string{winio.SeRestorePrivilege, idtools.SeTakeOwnershipPrivilege}
    47  
    48  	err := winio.EnableProcessPrivileges(privileges)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	defer winio.DisableProcessPrivileges(privileges)
    54  
    55  	sid, err := windows.StringToSid(SID)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	// Owners on *nix have read/write/delete/read control and write DAC.
    61  	// Add an ACE that grants this to the user/group specified with the
    62  	// chown option. Currently Windows is not honoring the owner change,
    63  	// however, they are aware of this and it should be fixed at some
    64  	// point.
    65  
    66  	sddlString := system.SddlAdministratorsLocalSystem
    67  	sddlString += "(A;OICI;GRGWGXRCWDSD;;;" + SID + ")"
    68  
    69  	securityDescriptor, err := windows.SecurityDescriptorFromString(sddlString)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	dacl, _, err := securityDescriptor.DACL()
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	return windows.SetNamedSecurityInfo(destination, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION, sid, nil, dacl, nil)
    80  }
    81  
    82  // normalizeDest normalises the destination of a COPY/ADD command in a
    83  // platform semantically consistent way.
    84  func normalizeDest(workingDir, requested string) (string, error) {
    85  	dest := filepath.FromSlash(requested)
    86  	endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator))
    87  
    88  	// We are guaranteed that the working directory is already consistent,
    89  	// However, Windows also has, for now, the limitation that ADD/COPY can
    90  	// only be done to the system drive, not any drives that might be present
    91  	// as a result of a bind mount.
    92  	//
    93  	// So... if the path requested is Linux-style absolute (/foo or \\foo),
    94  	// we assume it is the system drive. If it is a Windows-style absolute
    95  	// (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we
    96  	// strip any configured working directories drive letter so that it
    97  	// can be subsequently legitimately converted to a Windows volume-style
    98  	// pathname.
    99  
   100  	// Not a typo - filepath.IsAbs, not system.IsAbs on this next check as
   101  	// we only want to validate where the DriveColon part has been supplied.
   102  	if filepath.IsAbs(dest) {
   103  		if strings.ToUpper(string(dest[0])) != "C" {
   104  			return "", fmt.Errorf("Windows does not support destinations not on the system drive (C:)")
   105  		}
   106  		dest = dest[2:] // Strip the drive letter
   107  	}
   108  
   109  	// Cannot handle relative where WorkingDir is not the system drive.
   110  	if len(workingDir) > 0 {
   111  		if ((len(workingDir) > 1) && !system.IsAbs(workingDir[2:])) || (len(workingDir) == 1) {
   112  			return "", fmt.Errorf("Current WorkingDir %s is not platform consistent", workingDir)
   113  		}
   114  		if !system.IsAbs(dest) {
   115  			if string(workingDir[0]) != "C" {
   116  				return "", fmt.Errorf("Windows does not support relative paths when WORKDIR is not the system drive")
   117  			}
   118  			dest = filepath.Join(string(os.PathSeparator), workingDir[2:], dest)
   119  			// Make sure we preserve any trailing slash
   120  			if endsInSlash {
   121  				dest += string(os.PathSeparator)
   122  			}
   123  		}
   124  	}
   125  	return dest, nil
   126  }
   127  
   128  func containsWildcards(name string) bool {
   129  	for i := 0; i < len(name); i++ {
   130  		ch := name[i]
   131  		if ch == '*' || ch == '?' || ch == '[' {
   132  			return true
   133  		}
   134  	}
   135  	return false
   136  }
   137  
   138  func validateCopySourcePath(imageSource *imageMount, origPath string) error {
   139  	if imageSource == nil {
   140  		return nil
   141  	}
   142  	origPath = filepath.FromSlash(origPath)
   143  	p := strings.ToLower(filepath.Clean(origPath))
   144  	if !filepath.IsAbs(p) {
   145  		if filepath.VolumeName(p) != "" {
   146  			if p[len(p)-2:] == ":." { // case where clean returns weird c:. paths
   147  				p = p[:len(p)-1]
   148  			}
   149  			p += `\`
   150  		} else {
   151  			p = filepath.Join(`c:\`, p)
   152  		}
   153  	}
   154  	if _, ok := pathDenyList[p]; ok {
   155  		return errors.New(`copy from c:\ or c:\windows is not allowed on windows`)
   156  	}
   157  	return nil
   158  }