mirror of https://github.com/macssh/macssh.git
added keychain support
This commit is contained in:
parent
04c93b8840
commit
653cd31ec4
|
@ -66,6 +66,7 @@ typedef struct lshcontext {
|
|||
char _kpassword[64];
|
||||
int _kindex;
|
||||
int _pindex;
|
||||
char _keychainprompt[256];
|
||||
|
||||
} lshcontext;
|
||||
|
||||
|
|
|
@ -255,8 +255,8 @@ typedef struct {
|
|||
|
||||
/* NONO */
|
||||
Boolean
|
||||
cachePassphrase, // Connection's windows remain open after connection close
|
||||
unused1, // free
|
||||
cachePassphrase, //
|
||||
useKeyChain, //
|
||||
unused2, // free
|
||||
unused3; // free
|
||||
long
|
||||
|
|
|
@ -152,6 +152,8 @@ PaletteHandle
|
|||
AnsiColors; //The Global ANSI Color palette
|
||||
Boolean
|
||||
haveColorQuickDraw;
|
||||
Boolean
|
||||
haveKeyChain;
|
||||
NewMacroInfo
|
||||
newMacros;
|
||||
};
|
||||
|
|
|
@ -156,6 +156,11 @@ void Cenviron( void)
|
|||
} else {
|
||||
cachePass = TRUE;
|
||||
}
|
||||
if ( !TelInfo->haveKeyChain ) {
|
||||
HideDialogItem(dptr, 41);
|
||||
} else {
|
||||
SetCntrl(dptr, 41, gApplicationPrefs->useKeyChain);
|
||||
}
|
||||
/* NONO */
|
||||
|
||||
scratchPstring[0] = 4;
|
||||
|
@ -199,6 +204,7 @@ void Cenviron( void)
|
|||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
case 41:
|
||||
FlipCheckBox( dptr, ditem);
|
||||
break;
|
||||
case PrefStag:
|
||||
|
@ -312,6 +318,7 @@ void Cenviron( void)
|
|||
GetTEText(dptr,24, scratchPstring);
|
||||
StringToNum(scratchPstring, &scratchlong);
|
||||
gApplicationPrefs->cacheDelay = scratchlong;
|
||||
gApplicationPrefs->useKeyChain = GetCntlVal(dptr, 41);
|
||||
/* NONO */
|
||||
|
||||
gApplicationPrefs->CommandKeys = GetCntlVal(dptr, PrefCMDkey);
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "memory.proto.h"
|
||||
#include "AddressXLation.h"
|
||||
|
||||
#include <KeyChain.h>
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -253,6 +255,11 @@ void InquireEnvironment( void)
|
|||
}
|
||||
|
||||
TelInfo->haveColorQuickDraw = theWorld.hasColorQD;
|
||||
#if GENERATINGCFM
|
||||
TelInfo->haveKeyChain = KeychainManagerAvailable();
|
||||
#else
|
||||
TelInfo->haveKeyChain = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define kURLEventClass 'GURL'
|
||||
|
|
|
@ -24,14 +24,22 @@
|
|||
#include <Notification.h>
|
||||
#include <Dialogs.h>
|
||||
#include <TextEdit.h>
|
||||
#include <Keychain.h>
|
||||
|
||||
#include "PasswordDialog.h"
|
||||
#include "movableModal.h"
|
||||
#include "event.proto.h"
|
||||
#include "netevent.proto.h"
|
||||
#include "DlogUtils.proto.h"
|
||||
#include "wind.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
extern void ssh2_sched();
|
||||
extern WindRec *ssh2_window();
|
||||
|
||||
extern void setctxprompt(const char *prompt);
|
||||
extern char *getctxprompt();
|
||||
|
||||
extern TelInfoRec *TelInfo;
|
||||
extern Boolean gAEavail;
|
||||
|
@ -368,11 +376,144 @@ Boolean SSH2LoginDialog(StringPtr host, StringPtr login, StringPtr password)
|
|||
return item == 1;
|
||||
}
|
||||
|
||||
Boolean SSH2PasswordDialog(StringPtr prompt, StringPtr password)
|
||||
#if GENERATINGCFM
|
||||
|
||||
/*
|
||||
* GetPassFromKeychain
|
||||
*/
|
||||
|
||||
static void GetLabelFromPrompt(const char *prompt, StringPtr host, StringPtr user)
|
||||
{
|
||||
WindRec *wind = ssh2_window();
|
||||
if ( wind && strstr(prompt, "assword for") ) {
|
||||
StringPtr p = wind->sshdata.host;
|
||||
memcpy( host, p, *p + 1 );
|
||||
p = wind->sshdata.login;
|
||||
memcpy( user, p, *p + 1 );
|
||||
} else {
|
||||
/* use key label as both host name and user name */
|
||||
int l = strlen(prompt);
|
||||
*host = 4 + l;
|
||||
memcpy(host + 1, "Key ", 4);
|
||||
memcpy(host + 5, prompt, l);
|
||||
*user = l;
|
||||
memcpy(user + 1, prompt, l);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GetPassFromKeychain
|
||||
*/
|
||||
|
||||
static Boolean GetPassFromKeychain(const char *prompt, StringPtr password)
|
||||
{
|
||||
OSStatus theStatus;
|
||||
UInt32 theLength;
|
||||
KCItemRef theItem;
|
||||
|
||||
if ( TelInfo->haveKeyChain && gApplicationPrefs->useKeyChain ) {
|
||||
Str255 phost;
|
||||
Str255 puser;
|
||||
GetLabelFromPrompt(prompt, phost, puser);
|
||||
theStatus = KCFindGenericPassword(phost, puser, 255,
|
||||
password + 1, &theLength, &theItem);
|
||||
if ( theStatus == noErr ) {
|
||||
password[0] = theLength;
|
||||
if (theItem != NULL)
|
||||
KCReleaseItem( &theItem );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* AddPassToKeychain
|
||||
*/
|
||||
|
||||
static void AddPassToKeychain(const char *prompt, StringPtr password)
|
||||
{
|
||||
OSStatus theStatus;
|
||||
UInt32 theLength;
|
||||
KCItemRef theItem = NULL;
|
||||
Str255 phost;
|
||||
Str255 puser;
|
||||
Str255 ppass;
|
||||
KCAttribute theAttribute;
|
||||
OSType theTypeCreator;
|
||||
|
||||
if ( !TelInfo->haveKeyChain || !gApplicationPrefs->useKeyChain )
|
||||
return;
|
||||
|
||||
GetLabelFromPrompt(prompt, phost, puser);
|
||||
theStatus = KCFindGenericPassword(phost, puser, 255,
|
||||
ppass + 1, &theLength, &theItem);
|
||||
if ( theStatus == noErr && theItem != NULL) {
|
||||
ppass[0] = theLength;
|
||||
if ( memcmp(ppass, password, *ppass + 1) ) {
|
||||
theStatus = KCSetData(theItem, *password, password + 1);
|
||||
if (theStatus == noErr)
|
||||
theStatus = KCUpdateItem(theItem);
|
||||
}
|
||||
} else {
|
||||
theStatus = KCAddGenericPassword(phost, puser,
|
||||
*password, password + 1, &theItem);
|
||||
if (theStatus == noErr) {
|
||||
unsigned char *theDescriptionText = "\pMacSSH password";
|
||||
theAttribute.tag = kDescriptionKCItemAttr;
|
||||
theAttribute.length = *theDescriptionText;
|
||||
theAttribute.data = theDescriptionText + 1;
|
||||
theStatus = KCSetAttribute(theItem, &theAttribute);
|
||||
}
|
||||
if (theStatus == noErr) {
|
||||
theTypeCreator = 'Ssh2';
|
||||
theAttribute.tag = kCreatorKCItemAttr;
|
||||
theAttribute.length = sizeof(theTypeCreator);
|
||||
theAttribute.data = &theTypeCreator;
|
||||
theStatus = KCSetAttribute(theItem, &theAttribute);
|
||||
}
|
||||
if (theStatus == noErr) {
|
||||
theTypeCreator = 'APPL';
|
||||
theAttribute.tag = kTypeKCItemAttr;
|
||||
theStatus = KCSetAttribute(theItem, &theAttribute);
|
||||
}
|
||||
if (theStatus == noErr) {
|
||||
Boolean theCustomIcon = true;
|
||||
theAttribute.tag = kCustomIconKCItemAttr;
|
||||
theAttribute.length = sizeof(theCustomIcon);
|
||||
theAttribute.data = &theCustomIcon;
|
||||
theStatus = KCSetAttribute(theItem, &theAttribute);
|
||||
}
|
||||
if (theStatus == noErr)
|
||||
theStatus = KCUpdateItem(theItem);
|
||||
}
|
||||
if (theItem != NULL)
|
||||
KCReleaseItem(&theItem);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* SSH2PasswordDialog
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Boolean SSH2PasswordDialog(const char *prompt, StringPtr password)
|
||||
{
|
||||
DialogPtr dlog;
|
||||
short item = 0;
|
||||
Boolean addKey = false;
|
||||
ModalFilterUPP internalBufferFilterUPP;
|
||||
ConstStringPtr keyPrompt = "\pEnter passphrase for private key ";
|
||||
WindRec *wind;
|
||||
|
||||
#if GENERATINGCFM
|
||||
if ( strcmp(prompt, getctxprompt()) && GetPassFromKeychain(prompt, password) ) {
|
||||
setctxprompt(prompt);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
InteractWithUser( true, 128, 128 );
|
||||
|
||||
|
@ -381,12 +522,29 @@ Boolean SSH2PasswordDialog(StringPtr prompt, StringPtr password)
|
|||
*password = '\0';
|
||||
dlog = GetNewMyDialog(rSSH2PasswordDialog, 0L, (WindowPtr)-1L, NULL);
|
||||
if ( dlog ) {
|
||||
Str255 pprompt;
|
||||
SInt16 itemType;
|
||||
Handle itemHandle;
|
||||
Rect itemRect;
|
||||
ControlHandle cntlHandle;
|
||||
WindRec *wind = ssh2_window();
|
||||
// set prompt
|
||||
if ( wind && strstr(prompt, "assword for") ) {
|
||||
pprompt[0] = strlen(prompt);
|
||||
memcpy(pprompt + 1, prompt, pprompt[0]);
|
||||
} else {
|
||||
memcpy(pprompt, keyPrompt, keyPrompt[0] + 1);
|
||||
memcpy(pprompt + pprompt[0] + 1, prompt, strlen(prompt));
|
||||
pprompt[0] += strlen(prompt);
|
||||
}
|
||||
GetDialogItem(dlog, 5, &itemType, &itemHandle, &itemRect);
|
||||
SetDialogItemText(itemHandle, prompt);
|
||||
SetDialogItemText(itemHandle, pprompt);
|
||||
if ( TelInfo->haveKeyChain && gApplicationPrefs->useKeyChain ) {
|
||||
GetDialogItem(dlog, 6, &itemType, (Handle *)&cntlHandle, &itemRect);
|
||||
SetControlValue(cntlHandle, addKey = true);
|
||||
} else {
|
||||
HideDialogItem(dlog, 6);
|
||||
}
|
||||
SetDialogDefaultItem(dlog, 1);
|
||||
SetDialogCancelItem(dlog, 2);
|
||||
SetDialogTracksCursor(dlog, 1);
|
||||
|
@ -394,16 +552,25 @@ Boolean SSH2PasswordDialog(StringPtr prompt, StringPtr password)
|
|||
SetWRefCon(dlog, (long)password); // Stash the buffer's address
|
||||
do {
|
||||
movableModalDialog(internalBufferFilterUPP, &item);
|
||||
if (item == 6) {
|
||||
SetControlValue(cntlHandle, !GetControlValue(cntlHandle));
|
||||
}
|
||||
} while (item != 1 && item != 2); // Until the OK button is hit
|
||||
addKey = GetControlValue(cntlHandle);
|
||||
DisposeDialog(dlog);
|
||||
}
|
||||
DisposeRoutineDescriptor(internalBufferFilterUPP);
|
||||
ResetMenus();
|
||||
#if GENERATINGCFM
|
||||
if ( item == 1 && addKey ) {
|
||||
AddPassToKeychain( prompt, password );
|
||||
}
|
||||
#endif
|
||||
return item == 1;
|
||||
}
|
||||
|
||||
|
||||
static short SSH2SOCDialog(char *fingerprint, int id)
|
||||
static short SSH2SOCDialog(const char *fingerprint, int id)
|
||||
{
|
||||
DialogPtr dlog;
|
||||
short item = 3; /* cancel */
|
||||
|
@ -442,12 +609,12 @@ static short SSH2SOCDialog(char *fingerprint, int id)
|
|||
return item;
|
||||
}
|
||||
|
||||
short SSH2SOC1Dialog(char *fingerprint)
|
||||
short SSH2SOC1Dialog(const char *fingerprint)
|
||||
{
|
||||
return SSH2SOCDialog(fingerprint, rSSH2SOC1Dialog);
|
||||
}
|
||||
|
||||
short SSH2SOC2Dialog(char *fingerprint)
|
||||
short SSH2SOC2Dialog(const char *fingerprint)
|
||||
{
|
||||
return SSH2SOCDialog(fingerprint, rSSH2SOC2Dialog);
|
||||
}
|
||||
|
|
|
@ -38,9 +38,9 @@ Boolean SSH2RandomizeDialog( long *type, long *level, long *encrypt, Str255 labe
|
|||
void SSH2ErrorDialog(char *mess1);
|
||||
|
||||
Boolean SSH2LoginDialog(StringPtr inhost, StringPtr iologin, StringPtr outpassword);
|
||||
Boolean SSH2PasswordDialog (StringPtr inprompt, StringPtr outpassword);
|
||||
short SSH2SOC1Dialog(char *fingerprint);
|
||||
short SSH2SOC2Dialog(char *fingerprint);
|
||||
Boolean SSH2PasswordDialog (const char *inprompt, StringPtr outpassword);
|
||||
short SSH2SOC1Dialog(const char *fingerprint);
|
||||
short SSH2SOC2Dialog(const char *fingerprint);
|
||||
|
||||
void InternalBufferDialog (StringPtr inprompt, StringPtr outpassword);
|
||||
Boolean YesNoDialog (StringPtr inprompt);
|
||||
|
|
|
@ -781,11 +781,9 @@ char *getpass( const char *prompt )
|
|||
wind->sshdata.password[0] = '\0';
|
||||
valid = 1;
|
||||
} else {
|
||||
pprompt[0] = strlen(prompt);
|
||||
memcpy(pprompt + 1, prompt, pprompt[0]);
|
||||
ppassword[0] = 0;
|
||||
pthread_mutex_lock( &dialock );
|
||||
valid = SSH2PasswordDialog(pprompt, ppassword);
|
||||
valid = SSH2PasswordDialog(prompt, ppassword);
|
||||
pthread_mutex_unlock( &dialock );
|
||||
if (valid) {
|
||||
memcpy(password, ppassword + 1, ppassword[0]);
|
||||
|
@ -805,12 +803,9 @@ char *getpass( const char *prompt )
|
|||
&& getnextcachedpassphrase(prompt, context->_kpassword, &context->_kindex) ) {
|
||||
return context->_kpassword;
|
||||
}
|
||||
PLstrcpy(pprompt, "\pEnter passphrase for private key ");
|
||||
memcpy(pprompt + pprompt[0] + 1, prompt, strlen(prompt));
|
||||
pprompt[0] += strlen(prompt);
|
||||
context->_kpassword[0] = 0;
|
||||
pthread_mutex_lock( &dialock );
|
||||
valid = SSH2PasswordDialog(pprompt, (StringPtr)context->_kpassword);
|
||||
valid = SSH2PasswordDialog(prompt, (StringPtr)context->_kpassword);
|
||||
pthread_mutex_unlock( &dialock );
|
||||
if (valid) {
|
||||
plen = context->_kpassword[0];
|
||||
|
@ -825,6 +820,23 @@ char *getpass( const char *prompt )
|
|||
return (valid) ? password : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* setctxprompt
|
||||
*/
|
||||
void setctxprompt(const char *prompt)
|
||||
{
|
||||
strcpy(((lshcontext *)pthread_getspecific(ssh2threadkey))->_keychainprompt, prompt);
|
||||
}
|
||||
|
||||
/*
|
||||
* getctxprompt
|
||||
*/
|
||||
|
||||
char *getctxprompt()
|
||||
{
|
||||
return ((lshcontext *)pthread_getspecific(ssh2threadkey))->_keychainprompt;
|
||||
}
|
||||
|
||||
/*
|
||||
* save_once_cancel1
|
||||
*/
|
||||
|
@ -1110,6 +1122,7 @@ void init_context(lshcontext *context, short port)
|
|||
context->_kpassword[0] = 0;
|
||||
context->_kindex = 0;
|
||||
context->_pindex = 0;
|
||||
context->_keychainprompt[0] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue