Cyberduck Mountain Duck CLI

#5669 closed defect (thirdparty)

third-part addInternetKeyChain for cyberduck

Reported by: likun Owned by: dkocher
Priority: normal Milestone:
Component: ftp Version: 3.8.1
Severity: normal Keywords:
Cc: Architecture:
Platform:

Description (last modified by likun)

I code an app to write many ftp address, port, accounts and passwords to keychain using api: SecTrustedApplicationCreateFromPath SecAccessCreate SecKeychainItemCreateFromContent

I hope cyberduck could use them, but even I update the keychain fields the same as cyberduck saved, cyberduck couldn't use them. when connecting to an ftp, the password dialog pop up.

Is it because cyberduck save the ftp info with X509Certificate?

If I want to add keychains for cyberduck, how to do?

I create a ticket here, cause the forum above can't be reached in my country.

thank you!

Change History (6)

comment:1 Changed on Jan 26, 2011 at 2:34:33 PM by likun

  • Description modified (diff)

comment:2 Changed on Jan 26, 2011 at 2:51:50 PM by dkocher

  • Resolution set to thirdparty
  • Status changed from new to closed

Make sure the item you add with SecKeychainAddInternetPassword has the properties kSecProtocolTypeFTP and a service name matching the hostname plus a matching username.

comment:3 Changed on Jan 27, 2011 at 2:08:46 PM by likun

This is my code and the item i add. but it can't work.

#import <Cocoa/Cocoa.h>
#include <Security/SecKeychain.h>
#include <Security/SecKeychainItem.h>
#include <Security/SecAccess.h>
#include <Security/SecTrustedApplication.h>
#include <Security/SecACL.h>

SecAccessRef createAccess(NSString *accessLabel)
{
    OSStatus err;
    SecAccessRef access=nil;
    NSArray *trustedApplications=nil;
	
    //Make an exception list of trusted applications; that is,
    // applications that are allowed to access the item without
    // requiring user confirmation:
    SecTrustedApplicationRef myself, someOther;
	//Create trusted application references; see SecTrustedApplications.h:
    err = SecTrustedApplicationCreateFromPath(NULL, &myself);
    err = SecTrustedApplicationCreateFromPath("/Applications/web/Cyberduck.app", &someOther);
    trustedApplications = [NSArray arrayWithObjects:(id)myself, (id)someOther, nil];
	//Create an access object:
    err = SecAccessCreate((CFStringRef)accessLabel,
						  (CFArrayRef)trustedApplications, &access);
    if (err) return nil;
	
    return access;
}


void addInternetPassword(NSString *itemLabel, NSString *account, NSString *password, 
						 SecProtocolType protocol, NSString *server, int port, NSString *path)
{
    OSStatus err;
    SecKeychainItemRef item = nil;
    const char *itemLabelUTF8 = [itemLabel UTF8String];
    const char *accountUTF8 = [account UTF8String];
    const char *passwordUTF8 = [password UTF8String];
	const char *serverUTF8 = [server UTF8String];
	const char *pathUTF8 = [path UTF8String];
	
    //Create initial access control settings for the item:
    SecAccessRef access = createAccess(itemLabel);
	
    //Following is the lower-level equivalent to the
    // SecKeychainAddInternetPassword function:
	
    //Set up the attribute vector (each attribute consists
    // of {tag, length, pointer}):
    SecKeychainAttribute attrs[] = {
        { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 },
        { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 },
        { kSecServerItemAttr, strlen(serverUTF8), (char *)serverUTF8 },
        { kSecPortItemAttr, sizeof(int), (int *)&port },
        { kSecProtocolItemAttr, sizeof(SecProtocolType), (SecProtocolType *)&protocol },
        { kSecPathItemAttr, strlen(pathUTF8), (char *)pathUTF8 }
    };
    SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
	
    err = SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass,
										   &attributes,
										   strlen(passwordUTF8),
										   passwordUTF8,
										   NULL, // use the default keychain
										   access,
										   &item);
	//NSLog(@"%@", item);
	
    if (access) CFRelease(access);
    if (item) CFRelease(item);
}


int main(int argc, const char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
    addInternetPassword(@"222.132.26.196", @"username", @"password", kSecProtocolTypeFTP, @"222.132.26.196", 4321, @"");
	
    [pool release];
	
    return 0;
}
Last edited on Jan 27, 2011 at 2:12:29 PM by dkocher (previous) (diff)

comment:4 follow-up: Changed on Jan 27, 2011 at 2:13:30 PM by dkocher

Use the hostname instead of the IP address for the service name.

comment:5 in reply to: ↑ 4 ; follow-up: Changed on Jan 28, 2011 at 12:30:51 PM by likun

Replying to dkocher:

Use the hostname instead of the IP address for the service name.

Using ip for server name is ok, That is not the point, I changed this line like this:

addInternetPassword(@"myftp", @"username", @"password", kSecProtocolTypeFTP, @"ftp.servername.com", 21, @"");

It still can't work.

And I hope that you get a ftp server and test the code above.

Last edited on Jan 28, 2011 at 12:53:05 PM by dkocher (previous) (diff)

comment:6 in reply to: ↑ 5 Changed on Jan 28, 2011 at 12:54:08 PM by dkocher

Replying to likun:

Replying to dkocher:

Use the hostname instead of the IP address for the service name.

Using ip for server name is ok, That is not the point, I changed this line like this:

addInternetPassword(@"myftp", @"username", @"password", kSecProtocolTypeFTP, @"ftp.servername.com", 21, @"");

It still can't work.

And I hope that you get a ftp server and test the code above.

Refer to the API. Make sure the serverName parameter equals the hostname.

Note: See TracTickets for help on using tickets.
swiss made software