Swift Cocoa - Process() doesn't allow sudo - swift

I have made a cocoa swift application, in which there is a NSTextField. The textfield returns a password, which is then loaded in a Process(), that brings it into a bash command script.
The command is: Echo ${1} | sudo -S echo works
To the process I pass the argument of the password, so it goes instead of the ${1}. When I run the command, the console says that usr/bin/sudo: Operation not permitted.
Is there a way I can use sudo in my bash scripts?
Help would really be appreciated. Thanks.

This is not the correct way to escalate privileges on OS X, particularly because it's terrible security; your passing around the password in cleartext like this is a generally bad practice.
Let me illustrate why this is a problem. Suppose I have this bash script:
#!/bin/bash
sleep 10
echo ${1}
Then, I execute my script, using Process:
import Foundation
let process = Process()
process.launchPath = "/bin/bash"
process.arguments = ["/path/to/foo.sh", "This is a parameter"]
process.launch()
process.waitUntilExit()
Run the script, it outputs "This is a parameter", all seems well. But, while the script is running, in a separate Terminal window, I run this command:
$ ps -ajxww | grep foo.sh
And get the output:
username 85281 85276 85281 0 1 S s006 0:00.00 /bin/bash /path/to/foo.sh This is a parameter
As you can see, the parameter is plainly visible in the process list. If the parameter to that script had been my admin password, I would have just broadcast that password to every interested process on the system.
Anyway, instead of doing things like this, you should create a privileged launchd helper tool, which you can bless using SMJobBless(). The OS will prompt for the password in a secure way, and install your helper tool in a secure location. You can then communicate with your tool via XPC to have it do things as root. See Apple's EvenBetterAuthorizationSample for an idea of how to do this.

Related

How to use Process Class to execute commands need to enter password in MacOS

I want to execute commands below by Process Class:
let uninstallTask = Process()
uninstallTask.launchPath = "/bin/bash"
//MarkerPro is an app in launchpad
uninstallTask.arguments = ["-c","sudo rm -rf "+"/Applications/MarkerPro.app"]
uninstallTask.launch()
But get errors below:
sudo: no tty present and no askpass program specified
So probably need to enter password before i execute delete command.
I found the solution by using "STPrivilegedTask" which is a tool to get authorization by users.
Using FileManager API I think also a good idea

Adapt perl script to run from cgi

I have a perl script which works fine from shell but doesn't work from web (lighttpd + mod_cgi). I found out that problem is with the following string
my $lastupdate = `/opt/mongo/bin/mongo 127.0.0.1:27117/getVersion -u test -p test --eval 'db.polling.find({},{"_id":0,"host":0,"ports":0}).sort({"date":-1}).limit(1).forEach(function(x){printjson(x)})' | awk -F'"' '/date/{print \$4}' |sed 's/T/,/;s/Z//'`;
As i understood, when running from cgi, string is not being splitted. So i have done this by my own
my $lastupdate = system('/opt/mongo/bin/mongo', '127.0.0.1:27117/getVersion', '-u', 'test', '-p', 'test', '--eval', 'db.polling.find({},{"_id":0,"host":0,"ports":0}).sort({"date":-1}).limit(1).forEach(function(x){printjson(x)})', '|', 'awk', '-F', '"', '/date/{print', '\$4}', '|sed', 's/T/,/;s/Z//');
Script works now but gives me unexpected value (differs from shell's run value).
What did i miss?
P.S. I know that there are smarter ways to interact mongoDB from perl, but my env is totally firewalled. I have access neither to CPAN, nor to rh repos and perl mongoDB driver has too much deps to install it manually.
The environment that you run a program under from a shell is completely different to the environment that the same program gets when run from a web server. Most obviously, it will be run as a different user - one who will have far more restricted filesystem permissions that the average user.
You can (partly) simulate this by working out which user your web server runs as (perhaps apache, www or nobody) and using sudo to run your program as that user. This might well reveal what the problem is.
You can't just switch from backticks to system(). Backticks return the output from running the command line and system() returns a value which requires some interpretation. That'll be why you're seeing a different result.

Substitute user with long command doesn't work

I'm having trouble to start a service as a specific user (under Ubuntu 14.4) and I'm unsure what the problem is. I use the following command to autostart a jar-file on startup:
nohup ${JAVA_EXEC} -jar ${MICROSERVICE_HOME}/bin/${MICROSERVICE_JAR} server ${MICROSERVICE_CONF} 2>> /dev/null &
That works perfectly, therefore there is no problem with the variables and so on. Well, this script get's executed by the actual user, which is in this case, the root. Since I don't want to take any risks, I do want to execute it as a specific (already existing) user. Normally my approach would be to change the to command to:
nohup su some_user -c "${JAVA_EXEC} -jar ${MICROSERVICE_HOME}/bin/${MICROSERVICE_JAR} server ${MICROSERVICE_CONF}"
But this doesn't work. I don't get any error messages (of course I left out the redirection of stderr for test purposes) and the nohup.out is empty.
I already have tried different versions, e.g. replacing the double quotes with single quotes and masking the "$" inside the command. According to this thread it should work with the syntax.
None of the solutions in that thread do work. E.g.
su some_user -c "nohup ${JAVA_EXEC} -jar ${MICROSERVICE_HOME}/bin/${MICROSERVICE_JAR} server ${MICROSERVICE_CONF}" -> doesn't work
nohup runuser some_user c "nohup ${JAVA_EXEC} -jar ${MICROSERVICE_HOME}/bin/${MICROSERVICE_JAR} server ${MICROSERVICE_CONF}"-> doesn't work (the runuser commands doesn't exist).
What do I miss?
Any help is very appreciated!

Terminal prompt disappears when a named pipe is used

I'm trying to use named pipes in a project. I have two terminals open, Terminal A and Terminal B.
In terminal A, I issued this command:
mkfifo myFifo && tail -f myFifo | csh -s
It seems as if standard out is being redirected somewhere else, though, because my prompt disappears and some commands aren't reflected in terminal A.
For example, if in terminal B I begin a python session via issuing echo "python" > myFifo, then echo "print 'Hello, World'" > myFifo, I don't see Hello, World in terminal A.
However, if I issue echo ls > myFifo within terminal B, I see the correct output from ls in terminal A.
Does anyone know why sometimes the output appears and sometime it doesn't?
I'm running on CentOS 6.6
Thanks,
erip
You read from the FIFO with csh, if you start an interactive Python shell in csh, then it won't be reading from the FIFO because it's busy running python.
Python doesn't somehow automagically do a REPL on the FIFO. How should it even know about the FIFO? It has no knowledge of it.
You could, perhaps, tell Python to read commands from the FIFO with something like:
>>> import os, sys, time
>>> fifo = open(os.open('myFifo', os.O_NONBLOCK), 'r')
And then:
$ echo 'print(42+5)' > ! myFifo
Will give you:
>>> eval(fifo.read())
47
Perhaps there's also a way to tell Python to read commands from myFifo by overwriting sys.stdin, but I can't get that working in my testing.
It's a bit unclear to me what exactly you're trying to achieve here, though. I suspect there might be another solution which is much more appropriate to the problem you're having.

SSH connectivity using Swift

Recently, I've been trying to make a (very) simple program with Swift that lets you connect to a server through SSH and execute some files. Unfortunately, I could not figure out how to start an SSH session completely within the Swift app. Here is some code that I have written:
var sshConnectCommand = ["-c", "spawn ssh "+sshUsername+"#"+sshHost+"; expect assword:; send "+sshPassword+"\r"]
func sshIn() {
//starting ssh session
let sshConnect = NSTask()
sshConnect.arguments = [testCmd]
//rerouting output through a pipe
sshConnect.standardOutput = logAppend
//launch!
sshConnect.launch();
}
As you can see, I have used NSTask to try and run the 'expect' command to enter the password and everything. I would like to try and avoid using SSH-keygen as much as possible as this is intended to be used a server that the user does not have any access to.
So, to sum up:
How would you connect to SSH without SSH-keygen while remaining completely within the application code?
edit: I should also add, when trying to compile, I get this error:
[Swift._SwiftDeferredNSArray fileSystemRepresentation]: unrecognized selector sent to instance 0x600000032500. I'm not sure what this means.
I've been using something similar to this to ssh into my Raspberry Pi:
func sshIn() {
let task = CommandLine()
task.launchPath = "/usr/bin/ssh"
task.arguments = ["USERNAME#IPADDRESS", "-t", "sudo systemctl stop mediacenter; /opt/vc/bin/tvservice -o"]
task.launch()
}
-t closes the connection when the commands are finished running, and you can pass in all your commands like so command1; command 2 like where I've got sudo systemctl stop mediacenter; /opt/vc/bin/tvservice -o
As for the keygen thing, I don't think you have much of a choice. You can look into locking it down a bit though. Here's a good place to start looking.