macOS Privileged Helper doesn't have access to a filesystem path? - swift

Halp! I am writing an internal macOS app for our IT staff to perform some org-specific tasks, and am also adding some shortcuts for simple, but common tasks that they do. One of those tasks is to rename a user when migrating between domains. This app has a Privileged Helper available (via SMjobBless) to perform most of the tasks. However, it appears that this helper tool, despite its privileged execution context, is unable to rename a user's home directory.
My first attempt at implementing this specific task in the helper was to run a short shell script via Process() (a technique used successfully for dozens of other tasks in this helper).
let script = """
set -e
mv '\(homeDirPath)' /Users/\(toUsername)
dscl . -change /Users/\(fromUsername) NFSHomeDirectory '\(homeDirPath)' '/Users/\(toUsername)'
dscl . -change /Users/\(fromUsername) RecordName \(fromUsername) \(toUsername)
"""
I get the following output on stderr (/Users/newname verified to not exist):
mv: rename /Users/oldname to /Users/newname: Operation not permitted
Trying this as a non-root user gives a different error: mv: rename /Users/oldname to /Users/newname: Permission denied
Okay, weird. Add whoami to the top of the script to double check the user context: root. Well... interesting. Wth, I can do this just fine via sudo in my user session.
Then I try using FileManager thinking there might be some SIP interference or sandboxing for child processes of a launchdaemon (despite not finding any docs that say this), but I still get an error - but more verbose this time:
Error: “oldname” couldn’t be moved because you don’t have permission to access “Users”.
I've tried searching for documentation for whatever restriction I am up against, but I'm at a loss. The directory doesn't appear to be under SIP's protection, and I can't find any docs for daemon sandboxing outside of the app store (the parent app does not have the App Sandbox capability enabled). Can anyone point me in the right direction?
Update: It doesn't appear to be affected by 10.14's Privacy Protection. Adding the helper to "Full Disk Access" doesn't resolve. Perhaps I am adding the helper incorrectly: had to change the build target to 10.14 (which will be a problem), then dragged the helper binary from within the App bundle into the list. I cannot add it from /Library/PrivilegedHelperTools/ - it is greyed out as an option to add.
Update 2: Correction, it does appear to be FDA related. iTerm was in the FDA list. Removing it causes it to throw Operation not permitted, then adding it back resolves. So I'm now chasing down how to properly add the helper to the FDA list.

Okay, it's confirmed - Mojave's Privacy Protections apply even to privileged tools. The solution was to make the helper binary executable by all so it can be allowed to be added to the Full Disk Access table.
Hopefully, this helps someone in the future who is initially puzzled by what they're seeing.
Here's to hoping that Apple adds a standardized, easier method for the user to grant this access to helpers.

Related

Could not locate login item in the caller's bundle error when using SMLoginItemSetEnabled

I'm trying to get my swift Mac app to launch at login using the method described in this page: https://theswiftdev.com/how-to-launch-a-macos-app-at-login/
However, I keep getting the following errors as soon as I call SMLoginItemSetEnabled:
Could not locate login item com.domain.LauncherApplication in the caller's bundle
Could not enable login item: com.domain.LauncherApplication: 3: No such process
I checked that the launcher app ID is correct multiple times, I tried changing it and changing its version number. I even tried cleaning the project and moving the base app to /Applications but I always get these error messages.
Any idea what the problem might be? (Notice the solution must not require me to disable App Sandboxing)
OK, I found the problem but it took a long time since it was so sneaky: In the Copy File Build Phase section I entered "Contents/Library/LoginItem" as the subpath instead of "Contents/Library/LoginItems" (notice the 's' in the end - can't believe I missed it). So thank you #vadian! You were absolutely right.

Clone rep:policy on AEM

I am currently working on with a solution that would be able to clone/copy/backup my existing rep:policy. 'Cause when we do some jobs it accidentally removed. I am trying to apply this kind of fix, but am failing to. It says it is an invalid path.
javax.jcr.security.AccessControlException: OakAccessControl0006: Isolated policy node. Parent is not of type [rep:AccessControllable]
final Workspace ws = session.getWorkspace();
ws.copy("/etc/commerce/products/abccompany/TvPackChannelMap/rep:policy","/tmp/nxt/TvPackChannelMap/rep:policy");
Are there other ways that I can be able to take the rep:policy thru code?
You need to make sure that your job does not touch the permissions or the rep:policy, this is the best way forward for you.
The exception could be because of /etc/commerce/products/abccompany/TvPackChannelMap/rep:policy does not exist or the user whose session you are using does not have read access to the node.
Make sure the path is correct, copy paste it to your CRX/DE to make sure it exists.
I have tried to use your code to copy a rep:policy from one node to another, works fine. But I would not* recommend copying permissions that way. The best practice is to use the Access Control Management API for all things permissions.
You can check, install and use the access control tool from netcentric. It offers a jmx interface for exporting AC entries and maybe also some APIs you could use to implement your custom solution.
The Other approach is to retrieve the ACL permissions through the query language.
For example, SELECT * FROM [rep:ACL] or SELECT * FROM [rep:ACE] where [rep:principalName] is not null should give you the results.
For more information, I would recommend you to check the ACS commons ACL Packager Implementation which is available on GitHub.
Reference Link - https://github.com/Adobe-Consulting-Services/acs-aem-commons/blob/master/bundle/src/main/java/com/adobe/acs/commons/packaging/impl/ACLPackagerServletImpl.java

gsutil setwebcfg weird sub folder behavior

It seems google cloud storage provides a different behavior whether a folder is access from a web client with or without a trailing /
A simple test shows a different behavior for the following link
http://gstest.tekartik.com/sub/dir (fail to load css - background is white)
http://gstest.tekartik.com/sub/dir/ (works ok - background is black)
Where the bucket has been configured using:
gsutil setwebcfg -m index.html -e 404.html gs://gstest.tekartik.com
For information it contains 3 simple files index.html/404.html/style.css where style.css only set the background to black.
They both correctly "redirect" to the url http://gstest.tekartik.com/sub/dir/index.html. However the relative path does not allow for style.css to be loaded properly in the first case.
What I would like is to have the 1st case to be redirected using a trailing / (which is what Amazon S3 does). What is needed for this to work propertly so that I can give a url to someone without worrying about whether the trailing / is entered?
as a side, this works fine as at the root level (http://gstest.tekartik.com/ got automatically renamed to http://gstest.tekartik.com as here the trailing / is not needed)
I've spoken with the engineering team and we agree this should work the way you expected. This will be fixed in the near term by adding a bucket configuration setting to enable the expected behavior (the extra config step is needed to avoid breaking any apps depending on the current behavior). We're also planning to make it easy to update the new config setting via gsutil. I can't say when exactly these changes will be available but tune into the gs-announce group to monitor these (and other) details about Google Cloud Storage. Thanks for bringing this to our attention.
Update (June 3, 2013): This has now been fixed in production.

Lost Microstrategy Administrator Password?

In researching this scenario, all I could find was a suggestion that you contact Microstrategy, send them your metadata DB and ask them for the password.
This CAN'T be the only way.
Is there no way to simply reset the password in some fashion? Looking at the DSSMDUSRACCT table in the metadata DB, this appears to hold (at first glance anyway) a hashed/encrypted password, but I don't believe this is correct, as every entry for every account is the same in the PASSWD field.
Can someone suggest an alternative beyond sending a database to Microstrategy?
There isn't any alternative. We ended up in similar scenario and had Microstrategy reset the password. Password is not easily recoverable from Medadata since it is secured.
I'm not sure how many projects you have in your metadata or if you have access to another user that may have all privileges; but another option would be to create a new database, use MSTR configuration wizard to populate metadata tables, then duplicate the project across project sources into the new metadata that was just created. The Administrator user in this new metadata will have a blank password. If this is not an option then I recommend to open a support ticket (as others have suggested).
One of the things which one can try is to see any command manager script or system manager workflow. Every MicroStrategy environment may have atleast one of the above two things running in their environment. If you check the file, you may see the password for the administrator user. But in case if there is none of these being used then contacting MicroStrategy support would be the right thing to do.
Thanks,
Nikhil.
Benedict's right, there's no way they would keep passwords in plaintext in the metadata. You'll have to send it to them in a support ticket. It can take quite a few days, but they get the job done.
as soon as you get it reset use object manager, create a configuration object package for the administrator account and anytime you forget it, just redeploy the package to reset it.
You could try using the MicroStrategy Object Manager to copy the Administrator user from another project source/server to this environment.
This should do the trick if you have at least one other user with the right administrative privileges.
The other day I wanted to login to one of our applications. However, I forgot my username and password. I tried using the forgot password wizard but had no luck.
The steps I am about to walkthrough will work with most web applications with average logon security measures. It may not work with MicroStrategy, but should work if the input password is not externally verified.
So this is how I got access:
First I logged into my database manager -If you don't have access to
this... run a scan for 'password' on your server root. For Linux I
write sudo grep 'password' -roni or try: db_pass, dbpass,
database_password, etc as other search terms... The -roni will apply various filtering and
options to the search... aka line number, file name and etc. After
getting some results... find a likely file and open it to see if you
have your database details in there.
Login to your database manager. Find the table associated with your account. (This will usually have the name X_users If the password isn't hashed, just take it and login with it... if it is hashed... copy the hashed value to your clipboard.
Change the directory to your chosen applications root.
Run the scan with the search term 'password' or 'md5(' ...this will hopefully bring up a login controller file.
Edit the line within the function that takes your login input. Change the value 'md5($#####)' with '$#####', (aka removing the md5hashing of your input).
Reload the login page. Now, enter your username and hashed password copied from the database and login.
If done correctly you should now be logged into your web app.
Change the password of the account. Now go back to the login controller file and undo the chnages.
This might not be applicable with your app in question, but it's worth a shot! ....and if it isn't appropriate for your scenario... it could still be very helpful for someone else with a similar problem and different application. I just thought there's a small chance it may help someone who's locked out of one of their web applications. Rather than having to reinstall and lose data.
I'd be happy for you to improve on this or give some feedback.

How to run my program on before logout on windows XP?

I am looking for an inverse version of "RunOnceEx".
RunOnceEx does run some program, before the user's shell(desktop&taskbar) start. The login progress will not continue before the runonceex complete.
I want to do exact the same but on user logout.
When she/he logout, all running program shutdown, leaving shell(desktop&taskbar), then ""I wish my program will be execute this moment"", finally logout.
I think it is possible because the "mobsync.exe" is doing that. But I cannot find where and how to do it.
Warning, as said here, gpedit.msc will allow you to configure a logoff script for all users.
If you need that script only for one user, you need to declare it directly in the registry, both in HKCU and HKLM.
To run this only for the current user, you can use WMI to get an information when a shutdown/logout occurs.
Either you write a small C# (or any other language that can use WMI) application or vbs script to listen on the Win32_ComputerShutdownEvent WMI event.
An example C# app can be found here in this question: Get Log off event from system
found in the first result on google for me
To execute a program you can create a script to run it and use group policy to enforce it.
In Group Policy Editor navigate to User Configuration-->Windows Settings-->Scripts (Logon/Logoff)
more information here
If you want a running program to execute code on logoff, then you should hook the WM_QUERYENDSESSION message and look for an lParam value of ENDSESSION_LOGOFF (0x80000000).
It's important to test for this lParam value because the other ones indicate a "forced close" - i.e. your process may be killed before your code is even allowed to run. In fact, most shutdown/session-end messages are only intended to give you an opportunity to run last-minute cleanup code and aren't that safe to respond to with long-running actions; but this particular combination should be OK.
Note: I've never tried to actually run a separate process in response to the WM_QUERYENDSESSION message. It's possible that the window manager will disallow this, like it does during shutdown. Try it and see, I guess.
If you're in a .NET environment (you didn't specify), a quicker way is to add an event handler to the Microsoft.Win32.SystemEvents.SessionEnding event.
What you need is an implementation of GINA. You can run your custom commands in WlxIsLogoffOk function, which gets called when the user initiates a logoff
Once you create the proper GINA dll you can register it here: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\#GinaDLL
Here is an implementation which may fit your needs (it provides a Logoff registry key where you could specify your command):
http://wwwthep.physik.uni-mainz.de/~frink/newgina_pre09/readme.html
As VonC and TFD already mentioned, the Group Policy Editor is just another way to manipulate the registry.
Just make with gpedit the changes (in Userconfig - Windows Settings - Scripts) you like and afterwards take a look in the registry at [HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\Scripts]
to find out how you can do that directly.
Also on my PC (hanging in a domain) is a hidden folder C:\WINDOWS\System32\GroupPolicy with subfolders for user and machine. Both having additional subfolders called Shutdown and Startup. Maybe you can also use these ones.
If you need something simple and working for a single (or any) user you can make a simple application in C++ or C# for example.
The simplest is having a C# in tray (by simply adding the tray component to the form) and register and event handler for the FormClosing event. It'd look like this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason != CloseReason.UserClosing)
{
// It's not the user closing the application,
// Let's do whatever you want here, for example starting a process
Process notePad = new Process();
notePad.StartInfo.FileName = "notepad.exe";
notePad.StartInfo.Arguments = "ProcessStart.cs";
notePad.Start();
}
}
So your application will be started with Windows or with the user. It'll wait (using a little bit of memory) and will do something when the system shuts down, or the user log off, etc (by checking "CloseReason" above).