11#include "osxkeychain_darwin.h"
2+ #include <CoreFoundation/CoreFoundation.h>
3+ #include <stdio.h>
4+ #include <string.h>
25
36char * get_error (OSStatus status ) {
47 char * buf = malloc (128 );
@@ -96,3 +99,77 @@ char *keychain_delete(struct Server *server) {
9699 }
97100 return NULL ;
98101}
102+
103+ char * CFStringToCharArr (CFStringRef aString ) {
104+ if (aString == NULL ) {
105+ return NULL ;
106+ }
107+ CFIndex length = CFStringGetLength (aString );
108+ CFIndex maxSize =
109+ CFStringGetMaximumSizeForEncoding (length , kCFStringEncodingUTF8 ) + 1 ;
110+ char * buffer = (char * )malloc (maxSize );
111+ if (CFStringGetCString (aString , buffer , maxSize ,
112+ kCFStringEncodingUTF8 )) {
113+ return buffer ;
114+ }
115+ return NULL ;
116+ }
117+
118+ char * keychain_list (char * * * paths , char * * * accts , unsigned int * list_l ) {
119+ CFMutableDictionaryRef query = CFDictionaryCreateMutable (NULL , 1 , NULL , NULL );
120+ CFDictionaryAddValue (query , kSecClass , kSecClassInternetPassword );
121+ CFDictionaryAddValue (query , kSecReturnAttributes , kCFBooleanTrue );
122+ CFDictionaryAddValue (query , kSecMatchLimit , kSecMatchLimitAll );
123+ //Use this query dictionary
124+ CFTypeRef result = NULL ;
125+ OSStatus status = SecItemCopyMatching (
126+ query ,
127+ & result );
128+ //Ran a search and store the results in result
129+ if (status ) {
130+ return get_error (status );
131+ }
132+ int numKeys = CFArrayGetCount (result );
133+ * paths = (char * * ) malloc ((int )sizeof (char * )* numKeys );
134+ * accts = (char * * ) malloc ((int )sizeof (char * )* numKeys );
135+ //result is of type CFArray
136+ for (int i = 0 ; i < numKeys ; i ++ ) {
137+ CFDictionaryRef currKey = CFArrayGetValueAtIndex (result ,i );
138+ if (CFDictionaryContainsKey (currKey , CFSTR ("path" ))) {
139+ //Even if a key is stored without an account, Apple defaults it to null so these arrays will be of the same length
140+ CFStringRef pathTmp = CFDictionaryGetValue (currKey , CFSTR ("path" ));
141+ CFStringRef acctTmp = CFDictionaryGetValue (currKey , CFSTR ("acct" ));
142+ if (acctTmp == NULL ) {
143+ acctTmp = CFSTR ("<unknown>" );
144+ }
145+ char * path = (char * ) malloc (CFStringGetLength (pathTmp )+ 1 );
146+ path = CFStringToCharArr (pathTmp );
147+ path [strlen (path )] = '\0' ;
148+ char * acct = (char * ) malloc (CFStringGetLength (acctTmp )+ 1 ); //<- problem line in 38th iteration
149+ acct = CFStringToCharArr (acctTmp );
150+ acct [strlen (acct )] = '\0' ;
151+ //We now have all we need, username and servername. Now export this to .go
152+ (* paths )[i ] = (char * ) malloc (sizeof (char )* (strlen (path )+ 1 ));
153+ memcpy ((* paths )[i ], path , sizeof (char )* (strlen (path )+ 1 ));
154+ (* accts )[i ] = (char * ) malloc (sizeof (char )* (strlen (acct )+ 1 ));
155+ memcpy ((* accts )[i ], acct , sizeof (char )* (strlen (acct )+ 1 ));
156+ }
157+ else {
158+ char * path = "0" ;
159+ char * acct = "0" ;
160+ (* paths )[i ] = (char * ) malloc (sizeof (char )* (strlen (path )));
161+ memcpy ((* paths )[i ], path , sizeof (char )* (strlen (path )));
162+ (* accts )[i ] = (char * ) malloc (sizeof (char )* (strlen (acct )));
163+ memcpy ((* accts )[i ], acct , sizeof (char )* (strlen (acct )));
164+ }
165+ }
166+ * list_l = numKeys ;
167+ return NULL ;
168+ }
169+
170+ void freeListData (char * * * data , unsigned int length ) {
171+ for (int i = 0 ; i < length ; i ++ ) {
172+ free ((* data )[i ]);
173+ }
174+ free (* data );
175+ }
0 commit comments