rsync patch to add Apple keychain support

Dirk Theisen d.theisen at objectpark.org
Thu Aug 23 22:00:55 GMT 2007


Hi!

In a project I'm working on, I needed a way to run rsync in daemon mode  
as a regular user without having the passwords readable to everybody  
accessing the console. With this chance rsync falls back to Apples  
keychain access if no secrets file is given.

You need to put the passwords into the keychain like this (I do it  
programmatically bit it can be done manually as well):

Servicename: rsyncd
Account name: <modulename>-<username>

Enjoy!

It would be very cool to see this as an option for the Darwin target.

Greetings,
    Dirk

In the Makefile, I added:

--------------------------------------------------------------
LDFLAGS=-framework Security -framework CoreFoundation -framework  
CoreServices
--------------------------------------------------------------

In authenticate.c, I added the following function:

--------------------------------------------------------------
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>

OSStatus SecKeychainFindGenericPassword(CFTypeRef keychainOrArray,  
UInt32 serviceNameLength, const char *serviceName, UInt32  
accountNameLength, const char *accountName, UInt32 *passwordLength,  
void **passwordData, SecKeychainItemRef *itemRef);
OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList *attrList,  
void *data);

static int get_secret_from_keychain(int module, char *user, char  
*secret, unsigned secretmaxlen)
{
	char accountname[100] = "";
	char* modulename = lp_name(module);
	
	strcat(accountname, modulename);
	strcat(accountname, "-");
	strcat(accountname, user);
		
	OSStatus status = noErr;
	
	UInt32 passwordLength = 0;	
	void* passwordData = nil; // will be allocated and filled in by  
SecKeychainFindGenericPassword
	
	SecKeychainItemRef* itemRef = NULL;
	
	
	status = SecKeychainFindGenericPassword (
											 NULL,           // default keychain
											 strlen("rsyncd"),             // length of service name
											 "rsyncd",   // service name
											 strlen(accountname),             // length of account name
											 accountname,   // account name
											 &passwordLength,  // length of password
											 &passwordData,   // pointer to password data
											 itemRef         // the item reference
											 );

	if (status != noErr) return 0;
	
	passwordLength = MIN(passwordLength, secretmaxlen);
	strncpy(secret, (char*)passwordData, passwordLength);
	secret[passwordLength] = 0; // terminate.
	
	SecKeychainItemFreeContent(NULL, passwordData);
	return 1;	
}
-----------------------------------------------------------------

In In authenticate.c, I changed the following function to call  
get_secret_from_keychain as fallback:

-----------------------------------------------------------------
/* Return the secret for a user from the secret file, null terminated.
  * Maximum length is len (not counting the null). */
static int get_secret(int module, char *user, char *secret, int len)
{
	char *fname = lp_secrets_file(module);
	STRUCT_STAT st;
	int fd, ok = 1;
	char ch, *p;

	if (!fname || !*fname)
		return get_secret_from_keychain(module, user, secret, len);

----------------------------------------------------------------

Greetings,
    Dirk


--

A: No.
Q: Should I include e-mail quotations after my reply?


More information about the rsync mailing list