This discussion is locked
-
All replies
-
Helpful answers
-
Mar 12, 2008 4:20 PM in response to Adam Wenocurby Adam Wenocur,I found a workaround for this by writing a program that uses the Security framework to grab the password from the keychain, calls /sbin/mount_afp via execve, and pipes the password to the stdin of the mount_afp process. This isn't as good a solution as having mount_afp use the keychain directly, as it foregoes the checksum of the process image, and hence would not detect a malicious program substituted for mount_afp.
If this functionality were present in mount_afp for Leopard, I'd still find it useful. -
Mar 17, 2008 1:43 PM in response to Adam Wenocurby LuigiG,Hi,
Would it be too intrusive too ask for the source code?
I'm exactly in the same boat!
Cheers,
L -
Mar 24, 2008 2:28 PM in response to LuigiGby Adam Wenocur,Sure, let me clean it up a bit, and I'll post it. -
Mar 24, 2008 9:29 PM in response to Adam Wenocurby Adam Wenocur,The following C program should be compiled with the Security framework as follows:
cc -framework Security -o mountwrapper mountwrapper.c
This program works only under Leopard, and requires that you have an AFP Internet password in your keychain with the exact hostname, username, and port number you specify on the command line. It does not look for approximate or ambiguous matches.
#include <unistd.h>
#include <stdio.h>
#include <Security/SecKeychain.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
int main(int argc, char **argv)
{
UInt32 passwordLength = 0;
void *passwordData;
OSStatus keychainStatus = 0;
UInt16 serverPort = 0;
if(argc < 6)
{
fprintf(stderr, "Usage: mountwrapper <hostname> <username> <share> <port> <mountpoint>\n");
return 1;
}
sscanf(argv[4], "%hu", &serverPort);
keychainStatus = SecKeychainFindInternetPassword(0, strlen(argv[1]), argv[1], 0, 0, strlen(argv[2]), argv[2], strlen(argv[3]), argv[3], serverPort, kSecProtocolTypeAFP, kSecAuthenticationTypeDefault, &passwordLength, &passwordData, 0);
if(keychainStatus || !passwordLength)
{
fprintf(stderr, "Keychain error: %i\n", keychainStatus);
return 1;
}
int pipein = 0, pipeout = 0, forkValue;
{
int myPipes1[2], myPipes2[2];
pipe(myPipes1);
pipe(myPipes2);
forkValue = fork();
if(forkValue)
{
pipein=myPipes1[0];
pipeout=myPipes2[1];
close(myPipes2[0]);
close(myPipes1[1]);
}
else
{
pipein = myPipes2[0];
pipeout = myPipes1[1];
close(myPipes1[0]);
close(myPipes2[1]);
}
}
if(!forkValue)
{
setsid();
int URLLength;
char *URL = malloc((URLLength = strlen(argv[1]) + strlen(argv[2]) + strlen(argv[3]) + strlen(argv[4]) + 12) + 1);
char *newArgv[] = {"mount_afp", "-i", "-o", "nobrowse", URL, argv[5], 0};
char *newEnv[] = {0};
snprintf(URL, URLLength, "afp://%s@%s:%hu%s", argv[2], argv[1], serverPort, argv[3]);
while(pipein < 3)
{
int oldpipein;
pipein = dup2(oldpipein = pipein, 8);
close(oldpipein);
}
while(pipeout < 3)
{
int oldpipeout;
pipein = dup2(oldpipeout = pipeout, 9);
close(oldpipeout);
}
dup2(pipein, 0);
dup2(pipeout, 1);
dup2(pipeout, 2);
execve("/sbin/mount_afp", newArgv, environ);
}
else
{
char buffer\[1024\];
int returnParams = 0;
write(pipeout, passwordData, passwordLength);
write(pipeout, "\n", 1);
size_t bytesRead = read(pipein, buffer, 1024);
size_t bufferOffset = 0;
if(bytesRead > 10)
if(!strncmp(buffer, "Password:", 9))
bufferOffset += 11;
fwrite(buffer + bufferOffset, 1, bytesRead, stderr);
wait(&returnParams);
}
return 0;
} -
Mar 25, 2008 12:14 AM in response to Adam Wenocurby Adam Wenocur,oops; I put a potential buffer overrun in there; that line toward the end should be:
fwrite(buffer + bufferOffset, 1, bytesRead - bufferOffset, stderr);
not:
fwrite(buffer + bufferOffset, 1, bytesRead, stderr); -