Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!




Share:
Notifications
Clear all

Lazarus - macOS - Request Admin Authentication

37 Posts
2 Users
14 Likes
1,403 Views
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  

Sometimes one needs to verify if the user is admin and has the appropriate right to access a certain function.
there are under macOS several ways to do this, but to use the proper API call in Lazarus Pascal, you can try this function I created.
It triggers a Admin authentication request and returns either TRUE or FALSE.

Uses ... MacOSAll ...

...
{$linkframework Security}
...
function TfmMain.VerifyAdminLogin:boolean;
var
  status:OSStatus;
  authRef: AuthorizationRef;
  authFlags: AuthorizationFlags;
  authRights: AuthorizationRights;
  authItem: AuthorizationItem;
begin
  authItem.flags := 0;
  authItem.name := kAuthorizationRightExecute;
  authItem.value := nil;
  authItem.valueLength:= 0;
  authRights.count := 1;
  authRights.items := @authItem;
  authRef := nil;
  authFlags := kAuthorizationFlagInteractionAllowed or kAuthorizationFlagExtendRights or kAuthorizationFlagPreAuthorize;
  status := AuthorizationCreate(@authRights, kAuthorizationEmptyEnvironment, authFlags, authRef);
  Result := status=errAuthorizationSuccess;
end;        

   
johngaver reacted
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

@hans This runs great and raises the needful dialog but then doesn't do anything.

Is there a way to retrieve the credential supplied in this dialog?

Or how can I run an app with elevated privileges after having done this step?

What sort of data is expected in the authItem.Value field - a PChar probably wouldn't cut it here?

Thanks again for the great start here, would be even more awesome to have it fleshed out a little more.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  

It basically confirms admin credentials, if your application would like to validate those.
However, username and password cannot be retrieved like that. This would be a big security issue of course.

An app on itself cannot run with elevated privileges (Apple's security feature)... you'd need a helper tool for that.
Apple has a SMJobLess example for Obj.C and Swift for that, but even with that It took me a lot of research and testing to figure that one out for Lazarus. 
So based on my findings I made a description: SMJobBless or Elevated Privileges

Hint: Where things often will go wrong is with the plist files.

It is a quite a bit of info to process, but it is do-able with Lazarus. Especially once you get it - but 3 months later I have to read my own article again 🤣 

As for your AuthorizationItem question: I'm not an expert either, but I did a lot of digging in the Apple documentation.
As far as I can guess this could point to a tool you'd like to use, but I highly doubt it will run the tool with elevated privileges.

Just as an example: for one of my tools I would need full access to a disk to read or write a full disk.
Well, giving the application "rights" for full disk access is not going to cut it - macOS will simply not allow it, UNLESS you're running a helper tool.

Hope this helps a little bit - feel free to ask questions 😊 


   
johngaver reacted
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

Thanks for the super quick reply!

Yes, I have already come across your amazing work RE: SMJobBless and have even printed out the full article for offline reading.

Have you seen VMware InstallBuilder for macOS? You can build an "always elevate" package with it for macOS. How do they do it?

Just like a Windows binary which requests elevation at start, the package they build can also request elevation upon start.

I would post an attachment, but the forum says "no more attachments are allowed today."

The package can then write to protected folders such as /Library/Application Support/My Custom Folder. It fails without the initial elevation.

There have also been some references to a now deprecated, but viable elevation path in my recent travels: AuthorizationExecuteWithPrivileges.

Do you think you might be able to share an example of how to get that working using Lazarus?

I even tried a Lazarus sample which uses TProcess and pipes input into sudo to elevate that way. But even that has a problem:

- If I create a folder using the Finder inside /Library/Application Support/, after the requested elevation, the folder is writable by user apps.

- If I create a folder inside /Library/Application Support/ using the sudo elevation approach, the resulting folder is not writable by user apps.

What would be the best way to achieve the objective of creating a folder inside /Library/Application Support/, and making it writable too?

(I didn't test what happens with VMware InstallBuilder for this scenario, but shall chime in with my results as soon as I've had a chance).

Last but not least...consider an app which may need to write to a random number of potentially privileged folders.

I think the VMware InstallBuilder approach makes the most sense in this scenario - to elevate at start - rather than repeated helper invokes.

Anyways, this is just my lay of the land based on what I've seen and learned so far.

Eagerly awaiting your reply, in gratitude!


   
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

Just to let you know that I was just able to test the situation with VMware InstallBuilder - no joy. Either using sudo or VMware InstallBuilder both fails to assign the created folder the appropriate rights for the current user. Both an elevated VMware InstallBuilder and sudo grant system rights to the folder object, which is not good because then my user-land app cannot access the folder.

So how exactly can we mimick what Finder does here? It creates the folder properly, and:

- Grants it rights for the current user

- Permits a rename of the folder without an additional password prompt

How do they achieve this programmatically?

And still, I am very interested in elevation from the start via AuthorizationExecuteWithPrivileges, as I suppose I could always pre-elevate and then grant rights to the current user manually after that fact.

Would really love to hear your thoughts! To summarize my requests:

1. A Lazarus sample for AuthorizationExecuteWithPrivileges to elevate the current app (or any app) with one user prompt would be fascinating.

2. Any suggestions on a "proper" implementation would also be great.

Once again, very grateful for any and all assistance.


   
ReplyQuote


 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  
Posted by: @johngaver

You can build an "always elevate" package with it for macOS

If I recall correctly, there is this one "officially supported" exception (an installer) where elevated privileges can be used. Well, up to a point anyway.
I found this to be a mixed bag as well.

Posted by: @johngaver

no more attachments are allowed today

Yeah, the forum has been setup that I need to approve 5 of your posts before you can add attachments. Sorry about the inconvenience - too many annoying people out there spamming 😞 

Posted by: @johngaver

AuthorizationExecuteWithPrivileges

I do not have an example for AuthorizationExecuteWithPrivileges and I doubt it will work. It's been deprecated quite a while now and for security reasons I'm sure Apple removed it. 

Sounds like you're running in circles now as well - I know the feeling, done that, been there and to be honest I'm not thrilled with what Apple has done there.

If I understand this right, you're trying to write in "/Library/Application Support/" which should be accessible, even with SIP enabled.
However, just like you, I ran into the "Access Denied" issue. I even tried signing and notarizing the test app - no luck.
So it looks like you will have to consider using a Helper tool (I really don't like that).

Now having said that and not being 100% sure why you want the info to be shared, but I have the impression that Apple wants us to use this path for sharing configs:

/Users/Shared/Library/Application Support/

 

I did a test and I do have full access there. For example (Pascal):

MkDir('/Users/Shared/Library/Application Support/TestDir');

 

I usually use this function to determine preferences path and such, but it doesn't cover the "/Users/Shared/Library" I just mentioned.
Which is odd, since it is using the proper API calls to get the paths ...

// add to uses: MacOSAll
function GetPreferencesFolder(AllUsers:boolean; ApplicationSupport:boolean; CreateDir:boolean): String;
var
  theError     : OSErr;
  theRef       : FSRef;
  myFolderType : UInt32;
  pathBuffer   : PChar;
const
  kMaxPath = 1024;
begin
  Result := '';

  try
    pathBuffer := Allocmem(kMaxPath);
    try
      Fillchar(pathBuffer^, kMaxPath, #0);
      Fillchar(theRef, Sizeof(theRef), #0);

      if ApplicationSupport then
        myFolderType:=kApplicationSupportFolderType
      else
        myFolderType:=kPreferencesFolderType;

      if AllUsers then
        theError := FSFindFolder(kLocalDomain, myFolderType, kDontCreateFolder, theRef)
      else
        theError := FSFindFolder(kUserDomain , myFolderType, kDontCreateFolder, theRef);

      if (pathBuffer <> nil) and (theError = noErr) then
        begin
          theError := FSRefMakePath(theRef, pathBuffer, kMaxPath);
          if theError = noErr then
            Result := UTF8ToAnsi(StrPas(pathBuffer)) + DirectorySeparator + Application.Title + DirectorySeparator;
        end;

      Freemem(pathBuffer);
    except
      Result := '';
    end;
  except
    Result := '';
  end;

  if Result='' then
    // Sloppy method in case the official method fails
    Result:= BoolToStr(AllUsers,'/Library/',ExpandFileName('~/Library/'))+
             BoolToStr(ApplicationSupport,'Application Support/','Preferences/')+
             Application.Title + DirectorySeparator;

  if CreateDir and not(DirectoryExists(Result)) then
    mkDir(Result);
end; 

 

Maybe this helps 😊 


   
johngaver reacted
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  

Just seeing that FSFindFolder is deprecated as well (still working though - Monterey 12.4): FsFindFolder documentation.
(seems part of the Carbon core - which of course has been replaced by Cocoa)

Did find this Lazarus Wiki post (source) but this does not produce any of the /Users/Shared directories either. Odd.
Good info though, so I'm posting it here anyway 😁 

{$mode objfpc}{H+}
{$modeswitch objectivec1} 

interface

Uses
  ...
  CocoaUtils,   // for NStringToString
  CocoaAll;     // for NSArray      
...

function GetSignificantDir(DirLocation: qword; DomainMask: qword; count: byte): string;
var
  paths : NSArray;
begin
  paths := NSSearchPathForDirectoriesInDomains(DirLocation, DomainMask, True);
  if(count < paths.count) then
    Result := NSString(paths.objectAtIndex(0)).UTF8String
  else
    Result := '';  
end;

 

To keep the info complete:

Don't forget to add "CocoaUtils" and "CocoaAll" to the uses clause, and to switch mode with  {$modeswitch objectivec1} .

 

DirLocation

  NSApplicationDirectory = 1;
  NSDemoApplicationDirectory = 2;
  NSDeveloperApplicationDirectory = 3;
  NSAdminApplicationDirectory = 4;
  NSLibraryDirectory = 5;
  NSDeveloperDirectory = 6;
  NSUserDirectory = 7;
  NSDocumentationDirectory = 8;
  NSDocumentDirectory = 9;
  NSCoreServiceDirectory = 10;
  NSAutosavedInformationDirectory = 11 { available in 10_6, 4_0 };
  NSDesktopDirectory = 12;
  NSCachesDirectory = 13;
  NSApplicationSupportDirectory = 14;
  NSDownloadsDirectory = 15 { available in 10_5, 2_0 };
  NSInputMethodsDirectory = 16 { available in 10_6, 4_0 };
  NSMoviesDirectory = 17 { available in 10_6, 4_0 };
  NSMusicDirectory = 18 { available in 10_6, 4_0 };
  NSPicturesDirectory = 19 { available in 10_6, 4_0 };
  NSPrinterDescriptionDirectory = 20 { available in 10_6, 4_0 };
  NSSharedPublicDirectory = 21 { available in 10_6, 4_0 };
  NSPreferencePanesDirectory = 22 { available in 10_6, 4_0 };
  NSApplicationScriptsDirectory = 23 { available in 10_8, NA };
  NSItemReplacementDirectory = 99 { available in 10_6, 4_0 };
  NSAllApplicationsDirectory = 100;
  NSAllLibrariesDirectory = 101;
  NSTrashDirectory = 102 { available in 10_8, NA }; 

 

DomainMasks

  NSUserDomainMask = 1;
  NSLocalDomainMask = 2;
  NSNetworkDomainMask = 4;
  NSSystemDomainMask = 8;
  NSAllDomainsMask = $0ffff; 

 

To get an idea what kind of paths these generate:

--NSUserDomainMask
NSApplicationDirectory = /Users/username/Applications
NSDemoApplicationDirectory = /Users/username/Applications/Demos
NSDeveloperApplicationDirectory = /Users/username/Developer/Applications
NSAdminApplicationDirectory = /Users/username/Applications/Utilities
NSLibraryDirectory = /Users/username/Library
NSDeveloperDirectory = /Users/username/Developer
NSUserDirectory = 
NSDocumentationDirectory = /Users/username/Library/Documentation
NSDocumentDirectory = /Users/username/Documents
NSCoreServiceDirectory = 
NSAutosavedInformationDirectory = /Users/username/Library/Autosave Information
NSDesktopDirectory = /Users/username/Desktop
NSCachesDirectory = /Users/username/Library/Caches
NSApplicationSupportDirectory = /Users/username/Library/Application Support
NSDownloadsDirectory = /Users/username/Downloads
NSInputMethodsDirectory = /Users/username/Library/Input Methods
NSMoviesDirectory = /Users/username/Movies
NSMusicDirectory = /Users/username/Music
NSPicturesDirectory = /Users/username/Pictures
NSPrinterDescriptionDirectory = 
NSSharedPublicDirectory = /Users/username/Public
NSPreferencePanesDirectory = /Users/username/Library/PreferencePanes
NSApplicationScriptsDirectory = 
NSItemReplacementDirectory = 
NSAllApplicationsDirectory = /Users/username/Applications
NSAllLibrariesDirectory = /Users/username/Library
NSTrashDirectory = /Users/username/.Trash

--NSLocalDomainMask
NSApplicationDirectory = /Applications
NSDemoApplicationDirectory = /Applications/Demos
NSDeveloperApplicationDirectory = /Developer/Applications
NSAdminApplicationDirectory = /Applications/Utilities
NSLibraryDirectory = /Library
NSDeveloperDirectory = /Developer
NSUserDirectory = /Users
NSDocumentationDirectory = /Library/Documentation
NSDocumentDirectory = 
NSCoreServiceDirectory = 
NSAutosavedInformationDirectory = 
NSDesktopDirectory = 
NSCachesDirectory = /Library/Caches
NSApplicationSupportDirectory = /Library/Application Support
NSDownloadsDirectory = 
NSInputMethodsDirectory = /Library/Input Methods
NSMoviesDirectory = 
NSMusicDirectory = 
NSPicturesDirectory = 
NSPrinterDescriptionDirectory = 
NSSharedPublicDirectory = 
NSPreferencePanesDirectory = /Library/PreferencePanes
NSApplicationScriptsDirectory = 
NSItemReplacementDirectory = 
NSAllApplicationsDirectory = /Applications
NSAllLibrariesDirectory = /Library
NSTrashDirectory = /Users/username/.Trash

--NSNetworkDomainMask
NSApplicationDirectory = /Network/Applications
NSDemoApplicationDirectory = /Network/Applications/Demos
NSDeveloperApplicationDirectory = /Network/Developer/Applications
NSAdminApplicationDirectory = /Network/Applications/Utilities
NSLibraryDirectory = /Network/Library
NSDeveloperDirectory = /Network/Developer
NSUserDirectory = /Network/Users
NSDocumentationDirectory = /Network/Library/Documentation
NSDocumentDirectory = 
NSCoreServiceDirectory = 
NSAutosavedInformationDirectory = 
NSDesktopDirectory = 
NSCachesDirectory = 
NSApplicationSupportDirectory = /Network/Library/Application Support
NSDownloadsDirectory = 
NSInputMethodsDirectory = /Network/Library/Input Methods
NSMoviesDirectory = 
NSMusicDirectory = 
NSPicturesDirectory = 
NSPrinterDescriptionDirectory = 
NSSharedPublicDirectory = 
NSPreferencePanesDirectory = 
NSApplicationScriptsDirectory = 
NSItemReplacementDirectory = 
NSAllApplicationsDirectory = /Network/Applications
NSAllLibrariesDirectory = /Network/Library
NSTrashDirectory = 

--NSSystemDomainMask
NSApplicationDirectory = /System/Applications
NSDemoApplicationDirectory = /Applications/Demos
NSDeveloperApplicationDirectory = /Developer/Applications
NSAdminApplicationDirectory = /System/Applications/Utilities
NSLibraryDirectory = /System/Library
NSDeveloperDirectory = /Developer
NSUserDirectory = 
NSDocumentationDirectory = /System/Library/Documentation
NSDocumentDirectory = 
NSCoreServiceDirectory = /System/Library/CoreServices
NSAutosavedInformationDirectory = 
NSDesktopDirectory = 
NSCachesDirectory = /System/Library/Caches
NSApplicationSupportDirectory = /Library/Application Support
NSDownloadsDirectory = 
NSInputMethodsDirectory = /System/Library/Input Methods
NSMoviesDirectory = 
NSMusicDirectory = 
NSPicturesDirectory = 
NSPrinterDescriptionDirectory = /System/Library/Printers/PPDs
NSSharedPublicDirectory = 
NSPreferencePanesDirectory = /System/Library/PreferencePanes
NSApplicationScriptsDirectory = 
NSItemReplacementDirectory = 
NSAllApplicationsDirectory = /System/Applications
NSAllLibrariesDirectory = /System/Library
NSTrashDirectory = 

--NSAllDomainsMask
NSApplicationDirectory = /Users/username/Applications
NSDemoApplicationDirectory = /Users/username/Applications/Demos
NSDeveloperApplicationDirectory = /Users/username/Developer/Applications
NSAdminApplicationDirectory = /Users/username/Applications/Utilities
NSLibraryDirectory = /Users/username/Library
NSDeveloperDirectory = /Users/username/Developer
NSUserDirectory = /Users
NSDocumentationDirectory = /Users/username/Library/Documentation
NSDocumentDirectory = /Users/username/Documents
NSCoreServiceDirectory = /System/Library/CoreServices
NSAutosavedInformationDirectory = /Users/username/Library/Autosave Information
NSDesktopDirectory = /Users/username/Desktop
NSCachesDirectory = /Users/username/Library/Caches
NSApplicationSupportDirectory = /Users/username/Library/Application Support
NSDownloadsDirectory = /Users/username/Downloads
NSInputMethodsDirectory = /Users/username/Library/Input Methods
NSMoviesDirectory = /Users/username/Movies
NSMusicDirectory = /Users/username/Music
NSPicturesDirectory = /Users/username/Pictures
NSPrinterDescriptionDirectory = /System/Library/Printers/PPDs
NSSharedPublicDirectory = /Users/username/Public
NSPreferencePanesDirectory = /Users/username/Library/PreferencePanes
NSApplicationScriptsDirectory = 
NSItemReplacementDirectory = 
NSAllApplicationsDirectory = /Users/username/Applications
NSAllLibrariesDirectory = /Users/username/Library
NSTrashDirectory = /Users/username/.Trash

 

 


   
johngaver reacted
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

Thanks for the great posts! Yes, the biggest harm spammers often do is to bury the efforts of legitimate people in a pile of junk, isn't it?

Is there any chance to see an example of the installer exception implemented in Lazarus?

I agree what Apple has done here is terrible, but other platform hosts are hardly better these days - you can look at Microsoft and their terrific disrespect of all Windows desktop developers, year over year...I have actually found Apple to be slightly refreshing in some ways.

The documentation for AuthorizationExecuteWithPrivileges says "You should use this function only to allow installers to run as root" which is almost exactly what I am looking for. Can I use it with the authorization reference generated above in the first post on this thread? Do you think it might be possible to put together a very simple demo which just shows how to self-elevate a Lazarus app accordingly? I am just unfamiliar with how strings should be prepared/formatted for calling macOS API's from Lazarus. We used to be a Windows-only shop here until recently :)

The striking thing about the VMware InstallBuilder example is that it doesn't require code signing, it doesn't require notarization - it just works, out of the box! I understand the API may be deprecated but there's probably a ton of installers out there using this API already, so even with the deprecation stuff, I can see how Apple may not have already retired the API (testing on 12.4 locally).

My hunch is that VMware InstallBuilder itself is using this legacy AuthorizationExecuteWithPrivileges API - based on all our research thus far, this is the only scenario that explains how they can get things working with neither notarization nor code signing.

Would really love a quick and dirty demo of that!


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  
Posted by: @johngaver

Is there any chance to see an example of the installer exception implemented in Lazarus?

 

I do not have such an example - sorry. I've been looking for this as well, but haven't been successful at getting something to run ...
I also suspect that this may cause issues with signing and notarizing. Here an ancient post of me trying to get that to work.

Note: in one of my older programs, I did simply use "sudo" in the background.
This still works, but probably is frowned upon heavily as it potential reveals the sudo password.

Just read the Apple Docs quickly on this topic and they recommend the helper tool approach.
VMWare is not using a helper tool otherwise you'd see a password request to install the launchd helper tool.

 

Oh I agree with you on the sh*t Microsoft has been pulling these last decades ... 
I have seen too many around me getting fond of MS tool, to then see MS drop support completely.
Not to mention the poor copying of Apple like solutions 😉 
I try to avoid using anything Microsoft, but Windows is still hard to avoid completely. 

 

Is there anything you can look at? Like the plist files that come with the files you created with VMWare InstallBuilder?
May that reveals the trick?

I have to admit that I haven't used InstallBuilder at all. I assume it creates packages?
Personally I prefer using DMGs.

 

 

In case this is useful ...

I waste most of today by migrating my signing tool from "altool" to "notarytool".
I've created my own tool to deal with all this stuff (creates DMG's as well, and cleans up stuff, etc) - I haven't published this tool though.

Anyhoo ... we used to use "xcrun altool" to notarize (signing and stapling didn't change), but for notarizing we now need to use 

xcrun notarytool submit <yourfile.dmg> --apple-id <your email address> --password <your app specific password> --team-id <cert team id> --wait

 

Here "--wait" is optional and waits for notarizing to complete (still need to staple afterwards). Team ID is not mandatory, part of your signing certificate and looks something like this: X6E86N7JH7

 


   
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

Can I upload their installer somewhere? I did take a peek at their property lists, and there was hardly anything of import there. Practically nothing pertaining to elevation. I am really curious now to see how VMware InstallBuilder makes this work! I already have a binary (.app bundle) and a project file ready to share.

I can see the attachments are now enabled for my account - but there's an 8 MB file size limit. The built package is 10 MB even with their best compression, and I could not attach the XML sources (a file type issue which persisted even after zipping); but here's the raw XML source for their project - you can just download their free trial to build this empty package:

<project>
    <shortName>mysample</shortName>
    <fullName>my product</fullName>
    <version>1.0</version>
    <componentList>
        <component>
            <name>default</name>
            <description>Default Component</description>
            <canBeEdited>1</canBeEdited>
            <selected>1</selected>
            <show>1</show>
            <folderList>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfiles</name>
                    <platforms>all</platforms>
                    <shortcutList>
                        <shortcut>
                            <comment>Uninstall</comment>
                            <exec>${installdir}/${uninstallerName}</exec>
                            <icon></icon>
                            <name>Uninstall ${product_fullname}</name>
                            <path>${installdir}</path>
                            <platforms>all</platforms>
                            <runAsAdmin>0</runAsAdmin>
                            <runInTerminal>0</runInTerminal>
                            <windowsExec>${installdir}/${uninstallerName}.exe</windowsExec>
                            <windowsExecArgs></windowsExecArgs>
                            <windowsIcon></windowsIcon>
                            <windowsPath>${installdir}</windowsPath>
                        </shortcut>
                    </shortcutList>
                </folder>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfileslinux</name>
                    <platforms>linux</platforms>
                </folder>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfileslinux64</name>
                    <platforms>linux-x64</platforms>
                </folder>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfileswindows</name>
                    <platforms>windows</platforms>
                </folder>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfileswindows64</name>
                    <platforms>windows-x64</platforms>
                </folder>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfilesosx</name>
                    <platforms>osx</platforms>
                </folder>
            </folderList>
            <startMenuShortcutList>
                <startMenuShortcut>
                    <comment>Uninstall ${product_fullname}</comment>
                    <name>Uninstall ${product_fullname}</name>
                    <runAsAdmin>0</runAsAdmin>
                    <runInTerminal>0</runInTerminal>
                    <windowsExec>${installdir}/${uninstallerName}.exe</windowsExec>
                    <windowsExecArgs></windowsExecArgs>
                    <windowsIcon></windowsIcon>
                    <windowsPath>${installdir}/</windowsPath>
                </startMenuShortcut>
            </startMenuShortcutList>
        </component>
    </componentList>
    <readyToInstallActionList>
        <createDirectory>
            <path>/Library/Application Support/{77BB117C-086B-4059-A0ED-840FE684173E}</path>
        </createDirectory>
    </readyToInstallActionList>
    <compressionAlgorithm>lzma-ultra</compressionAlgorithm>
    <enableRollback>1</enableRollback>
    <enableTimestamp>1</enableTimestamp>
    <requireInstallationByRootUser>1</requireInstallationByRootUser>
    <vendor>my vendor</vendor>
    <parameterList>
        <directoryParameter>
            <name>installdir</name>
            <description>Installer.Parameter.installdir.description</description>
            <explanation>Installer.Parameter.installdir.explanation</explanation>
            <value></value>
            <default>${platform_install_prefix}/${product_shortname}-${product_version}</default>
            <allowEmptyValue>0</allowEmptyValue>
            <ask>yes</ask>
            <cliOptionName>prefix</cliOptionName>
            <mustBeWritable>yes</mustBeWritable>
            <mustExist>0</mustExist>
            <width>30</width>
        </directoryParameter>
    </parameterList>
</project>

 

Subsequently you would see this dialog for launch upon elevation:

Quite the conundrum, isn't it?


   
ReplyQuote


 Anonymous
Joined: 53 years ago
Posts: 0
 

BTW forgot to respond to the MSFT vs AAPL argument.

I am 100% with you there in that MSFT are trying to copy Mac and doing a bad job at it - instead of doing real work on reinforcing the actual  strengths of their own platforms. Probably all the bad karma playing out from their dealings (and burial) of Nokia.

Fortunately I was never bit by the MSFT tendency to obsolete their "latest and greatest" technologies a year or two after release - having used Delphi there, I was able to weather most of the storm unharmed. Now it is even that same choice of development tool which is enabling as seamless as possible a transition to Lazarus (which, in some ways, exceeds the conveniences of Delphi even).


   
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

Ah, now that I can attach files - please find enclosed this screenshot; summarizing pretty well what I would like to achieve with Lazarus:

Here's three folders as you can see, shown with their permissions - and named by their creator.

Actually even VMware InstallBuilder gets this one wrong - because they are fully elevated, their folder has the wrong permissions, along with the folder that was created using sudo itself.

How do you think Finder does this magic? I figure the only way that makes sense is if they manually adjust permissions after creating with sudo. That is sort of the end-goal here - being able to do this with a Lazarus app.

The elevation prompt shown here BTW is coming from the VMware InstallBuilder app. Finder shows a different kind of prompt, which I again include for completeness:

Since Finder is a "first party" app, there's no way to be certain Apple isn't cutting corners (wouldn't surprise me). The prompt is highly custom. Achieving something with that degree of customizability would be truly amazing.

Anyways, thanks again for all the information you've shared - and I am crossing my fingers we'll have this figured out sooner than later.

Wishing you a great week! 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 9 years ago
Posts: 2282
Topic starter  
Posted by: @johngaver

Can I upload their installer somewhere?

I doubt we'd get any smarter from the installer - we'd need to be able to read it's source.
My initial guess would be the plist, but we already excluded that one.

The admin password request could potentially mean it's installing a helper tool - which it leaves there or removes once its task has been completed.
Keep an eye on this directory "/Library/PrivilegedHelperTools" - In mine I see a few "installer" helper tools listed there.
So my best guess this would be the case with the VMWare Install builder as well.

Maybe it utilizes AppleScript - I'm not sure if this trick still works though, and it looks something like this (if I recall correctly):

do shell script "open /path/to/my/executable" with administrator privileges

 

Yeah the MSFT discussion is an endless one ... I never got burned by it either, as I avoided it as the plague hahaha ...
I always used 3rd party tool to develop apps. Ended up with Lazarus since I really loved Turbo Pascal and Delphi.
Unfortunately, Embarcadero moved away from VCL and tries to get you to use FireMonkey.
I did see I'm not alone in preferring VLC, as some developed VCL packages for Linux and macOS as well - for example CrossVCL which is too expensive for my purposes ($399).


   
johngaver reacted
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 
Posted by: @hans
Posted by: @johngaver

Can I upload their installer somewhere?

I doubt we'd get any smarter from the installer - we'd need to be able to read it's source.
My initial guess would be the plist, but we already excluded that one.

The admin password request could potentially mean it's installing a helper tool - which it leaves there or removes once its task has been completed.
Keep an eye on this directory "/Library/PrivilegedHelperTools" - In mine I see a few "installer" helper tools listed there.
So my best guess this would be the case with the VMWare Install builder as well.

Maybe it utilizes AppleScript - I'm not sure if this trick still works though, and it looks something like this (if I recall correctly):

do shell script "open /path/to/my/executable" with administrator privileges

 

Yeah the MSFT discussion is an endless one ... I never got burned by it either, as I avoided it as the plague hahaha ...
I always used 3rd party tool to develop apps. Ended up with Lazarus since I really loved Turbo Pascal and Delphi.
Unfortunately, Embarcadero moved away from VCL and tries to get you to use FireMonkey.
I did see I'm not alone in preferring VLC, as some developed VCL packages for Linux and macOS as well - for example CrossVCL which is too expensive for my purposes ($399).

Great thought, I will check that folder (maybe on a clean VM too) to see if a helper is being installed. So if that were indeed the case, would the helper then be re-launching its actual invoker as admin?

Regarding Apple Script, while I don't have the URLs with me right now, a few StackOverflow pages suggested just doing that instead. Might you be able to share a Lazarus example with Apple Script that does this kind of elevation?

I'll also check out CrossVCL. Your posts are truly full of rich resources - as is the forum at large - thank you so much :)


   
ReplyQuote
 Anonymous
Joined: 53 years ago
Posts: 0
 

(BTW yes, same here - I never liked FireMonkey as it just looks bad IMHO - I've been all for the VCL from the get-go.)


   
ReplyQuote


Page 1 / 3

Like what you see and you'd like to help out? 

The best way to help is of course by assisting others with their questions here in the forum, but you can also help us out in other ways:

- Do your shopping at Amazon, it will not cost you anything extra but may generate a small commission for us,
- send a cup of coffee through PayPal ($5, $10, $20, or custom amount),
- become a Patreon,
- donate BitCoin (BTC), or BitCoinCash (BCH).

Share: