I just discovered an issue in one of my apps with El Capitan’s System Integrity Protection feature. I basically use the following code to temporarily replace the default TFTPD plist file with one of my own:
[code]
Dim s as new shell
Dim f as FolderItem = App.ExecutableFile.Parent.Parent.Child("Resources")
If f <> Nil and f.Exists Then
// Set up plistFile
SetUpOSXPlist
Dim ftmp as FolderItem = SpecialFolder.Temporary.child("tftp.plist")
If ftmp = Nil or Not ftmp.Exists Then Return
Dim MyScript as String
Dim MyParams as String =""
Dim filepath as FolderItem = SpecialFolder.SharedDocuments
MyScript = "#! /bin/sh"+endofline.unix+endofline.unix+"chmod 777 "+f.shellpath+EndOfLine.UNIX+ _
"launchctl unload -F /System/Library/LaunchDaemons/tftp.plist"+endofline.unix+ _
"mv -f /System/Library/LaunchDaemons/tftp.plist /System/Library/LaunchDaemons/tftp.bak"+EndOfLine.UNIX+_
"cp "+ftmp.nativepath+" /System/Library/LaunchDaemons/tftp.plist"+EndOfLine.UNIX
If RunAuthShellOSX(MyScript,MyParams) Then
MyScript = "#! /bin/sh"+endofline.unix+endofline.unix+f.ShellPath+"/TFTPStartHelper True"
MyParams = ""
If RunAuthShellOSX(MyScript,MyParams) Then
'System.DebugLog("TFTP Server Started")
Return
End IF
End If
End If
[/code]
The SetupOSXPlist method looks like:
Sub SetUpOSXPlist()
#If TargetMacOS Then
Dim f as FolderItem = App.ExecutableFile.Parent.Parent.Child("Resources")
If f = Nil Then Return
Dim path as string = f.NativePath
Dim TempPath as FolderItem = SpecialFolder.Temporary
Dim f1 as FolderItem = SpecialFolder.Temporary.Child("tftp.plist")
Dim filepath as FolderItem = SpecialFolder.SharedDocuments
If f1 = Nil Then Return
Dim bs as BinaryStream = BinaryStream.Create(f1,true)
bs.write("<?xml version=""1.0"" encoding=""UTF-8""?>"+EndOfLine.Unix)
bs.Write("<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">"+EndOfLine.Unix)
bs.write("<plist version=""1.0"">"+EndOfLine.Unix)
bs.write("<dict>"+EndOfLine.Unix)
bs.write("<key>Disabled</key>"+EndOfLine.Unix)
bs.write("<true/>"+EndOfLine.Unix)
bs.write("<key>InitGroups</key>"+EndOfLine.Unix)
bs.write("<true/>"+EndOfLine.Unix)
bs.write("<key>Label</key>"+EndOfLine.Unix)
bs.write("<string>com.apple.tftpd</string>"+EndOfLine.Unix)
bs.write("<key>ProgramArguments</key>"+EndOfLine.Unix)
bs.write("<array>"+EndOfLine.Unix)
bs.write("<string>/usr/libexec/tftpd</string>"+EndOfLine.Unix)
bs.write("<string>-d</string>"+EndOfLine.Unix)
bs.write("<string>-i</string>"+EndOfLine.Unix)
bs.write("<string>-s</string>"+EndOfLine.Unix)
'bs.write("<string>"+path+"</string>"+EndOfLine.Unix)
// Here's the all important line to change the path with TFTPD serves the files...
bs.write("<string>"+f.nativepath+"</string>"+EndOfLine.Unix)
bs.Write("<string>-u</string>"+EndOfLine.Unix)
bs.Write("<string>root</string>"+EndOfLine.Unix)
bs.write("</array>"+EndOfLine.Unix)
bs.write("<key>Sockets</key>"+EndOfLine.Unix)
bs.write("<dict>"+EndOfLine.Unix)
bs.write("<key>Listeners</key>"+EndOfLine.Unix)
bs.write("<dict>"+EndOfLine.Unix)
bs.write("<key>SockServiceName</key>"+EndOfLine.Unix)
bs.write("<string>tftp</string>"+EndOfLine.Unix)
bs.write("<key>SockType</key>"+EndOfLine.Unix)
bs.write("<string>dgram</string>"+EndOfLine.Unix)
bs.write("</dict>"+EndOfLine.Unix)
bs.write("</dict>"+EndOfLine.Unix)
bs.write("<key>inetdCompatibility</key>"+EndOfLine.Unix)
bs.write("<dict>"+EndOfLine.Unix)
bs.write("<key>Wait</key>"+EndOfLine.Unix)
bs.write("<true/>"+EndOfLine.Unix)
bs.write("</dict>"+EndOfLine.Unix)
bs.write("</dict>"+EndOfLine.Unix)
bs.write("</plist>"+EndOfLine.Unix)
#Endif
End Sub
Well, El Capitan does not like me doing this one bit. Throws errors saying the copying into the system files is not allowed.
So, how do I do this now days? I also found that the following code in the run event of a helper app is not appearing to work either. The setuid function is always returning -1. I’m afraid this is another limitation of El Capitan.
Dim s as new shell
soft declare function setuid lib "/usr/lib/libc.dylib" (uid as Integer) as Integer
dim setuid_result as Integer = setuid(0)
if setuid_result = -1 then
system.debuglog "Couldn't raise root setuid"
return 1
end if
Try
If args(1) = "True" Then
s.Execute("launchctl load -F /System/Library/LaunchDaemons/tftp.plist")
s.Execute("launchctl start com.apple.tftpd")
else
s.Execute("launchctl stop com.apple.tftpd")
s.Execute("launchctl unload -F /System/Library/LaunchDaemons/tftp.plist")
End If
Catch
s.Execute("launchctl stop com.apple.tftpd")
s.Execute(" launchctl unload -F /System/Library/LaunchDaemons/tftp.plist")
End Try
So I want to use OS X’s built in TFTP server, but what’s the way you can do that in El Capitan. I hate how Apple changes things that breaks code. ARGH!
As far as I know you have to avoid writing/changing stuff in the apps content from within your app. It breakes code sign and will introduce issues with SIP
dim setuid_result as Integer = setuid(0)
if setuid_result = -1 then
system.debuglog "Couldn't raise root setuid"
return 1
end if[/quote]
This will always return -1 unless the current user is root. From the OS X man pages:
[quote]The setuid() function sets the real and effective user IDs and the saved set-user-ID of the current
process to the specified value. The setuid() function is permitted if the effective user ID is that of
the super user, or if the specified user ID is the same as the effective user ID. If not, but the
specified user ID is the same as the real user ID, setuid() will set the effective user ID to the real
user ID.[/quote]
Until 10.11 unprotects certain files in /System/Library or allows you to do it yourself, the only way without disabling SIP would be to make a different service by coping the file somewhere else, like
And then instead of using the Sharing panel in System Preferences, you would manage the service yourself… Be sure to change the filename and the Label key inside the file, in order to avoid conflicts with the original launchd item
Best solution to change the plist file is too move in another folder and launch it from there like. copy the plist in a user’s home folder and launch tftpd like:
Thank you for your response. I will try that. I don’t need to manage anything from the sharing pane. This is a completely temporary operation used just within the app. So your idea just may work.
I wouldn’t call it “breaking code”. It increases security, which is important for common users I think. But as a developer you might turn SIP off on your own machines.
Thank you for your response. I will try that. I don’t need to manage anything from the sharing pane. This is a completely temporary operation used just within the app. So your idea just may work.[/quote]
You don’t need to mess with sharing pane,my previous post was just example…
Because of the SIP you don’t have rights to modify the original Plist file,so just copy the plist file to your preferred folder and there make the changes.
and run the demon again with the new Plist file sudo launchctl load -F /Users/userhomefolder/MyNewFolder/tftp.plist
Remember you need to include in your plist this two new
Without knowing too much about the service, I would imagine that it needs to be in a folder that your application can read & write from by default, such as it’s own application support folder.
Or within the application bundle, /Contents/Library/LaunchDaemons/
But of course having it within the application bundle, means it cannot be adjusted at run time, only launched.
So I’m getting a Path had bad ownership/permissions error. I’ve made it read/write for everyone…What am I doing wrong?[/quote]
Have you stop the server and relaunch ?
Stopped and unloaded tftpd
root# sudo launchctl stop com.apple.tftpd
root# sudo launchctl unload -F /System/Library/LaunchDaemons/com.apple.syslogd.plist
Loaded and started tftpd:
Check the folder and the file for permissions /JustAddSoftware/tftp.plist
JustAddSoftware <folder permissions
Jon(me) = Read&Write
staff =Read Only
everyone=Read Only
the same as above for the file…
Tip
go to the folder >Library/Application\ Support/JustAddSoftware/ < and on terminal put “ls -la” to see the owner and permissions
then
change the ownership
sudo chown -Rv username directory
to fix permissions in el capitan i use the Onyx,for me is the best utility Onyx
OK. It still isn’t working. Here is the output of the file from ls -la:
-rw-r--r--@ 1 Jon staff 1105 Mar 25 23:19 jastftp.plist
I have done the chown command and tried everything possible. Staff was not originally the group the file was under (it was under the admin group) so I changed that to staff, but I still get the same error.
Is it something in the plist file perhaps? I’m stuck and really need to get this working…
[quote=255939:@Norman Palardy]have you set it up manually using these steps ?
I’d start there on a 10.11 machine and see what errors / issues you encounter[/quote]
That’s what I am trying to do. I’m trying to get it started in terminal but am not having any luck.
So to re-cap I want to start OS X’s TFTP daemon but with a different plist file than the default. But I can’t get it to load. Keeps giving me bad ownership errors…
Most folders i have in application Support is…
Owner: my Name Group :Staff
Folder is RWX - R-X R-X
For my files is 644 like yours.
BUT the folder is 755 ?
[quote=255942:@Loannis Kolliageorgas]Most folders i have in application Support is…
Owner: my Name Group :Staff
Folder is RWX - R-X R-X
For my files is 644 like yours.
BUT the folder is 755 ?[/quote]
drwxrwxrwx 15 Jon staff 510 Mar 28 11:38 JustAddSoftware