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];
|
char _kpassword[64];
|
||||||
int _kindex;
|
int _kindex;
|
||||||
int _pindex;
|
int _pindex;
|
||||||
|
char _keychainprompt[256];
|
||||||
|
|
||||||
} lshcontext;
|
} lshcontext;
|
||||||
|
|
||||||
|
|
|
@ -255,8 +255,8 @@ typedef struct {
|
||||||
|
|
||||||
/* NONO */
|
/* NONO */
|
||||||
Boolean
|
Boolean
|
||||||
cachePassphrase, // Connection's windows remain open after connection close
|
cachePassphrase, //
|
||||||
unused1, // free
|
useKeyChain, //
|
||||||
unused2, // free
|
unused2, // free
|
||||||
unused3; // free
|
unused3; // free
|
||||||
long
|
long
|
||||||
|
|
|
@ -152,6 +152,8 @@ PaletteHandle
|
||||||
AnsiColors; //The Global ANSI Color palette
|
AnsiColors; //The Global ANSI Color palette
|
||||||
Boolean
|
Boolean
|
||||||
haveColorQuickDraw;
|
haveColorQuickDraw;
|
||||||
|
Boolean
|
||||||
|
haveKeyChain;
|
||||||
NewMacroInfo
|
NewMacroInfo
|
||||||
newMacros;
|
newMacros;
|
||||||
};
|
};
|
||||||
|
|
|
@ -156,6 +156,11 @@ void Cenviron( void)
|
||||||
} else {
|
} else {
|
||||||
cachePass = TRUE;
|
cachePass = TRUE;
|
||||||
}
|
}
|
||||||
|
if ( !TelInfo->haveKeyChain ) {
|
||||||
|
HideDialogItem(dptr, 41);
|
||||||
|
} else {
|
||||||
|
SetCntrl(dptr, 41, gApplicationPrefs->useKeyChain);
|
||||||
|
}
|
||||||
/* NONO */
|
/* NONO */
|
||||||
|
|
||||||
scratchPstring[0] = 4;
|
scratchPstring[0] = 4;
|
||||||
|
@ -199,6 +204,7 @@ void Cenviron( void)
|
||||||
case 35:
|
case 35:
|
||||||
case 36:
|
case 36:
|
||||||
case 37:
|
case 37:
|
||||||
|
case 41:
|
||||||
FlipCheckBox( dptr, ditem);
|
FlipCheckBox( dptr, ditem);
|
||||||
break;
|
break;
|
||||||
case PrefStag:
|
case PrefStag:
|
||||||
|
@ -312,6 +318,7 @@ void Cenviron( void)
|
||||||
GetTEText(dptr,24, scratchPstring);
|
GetTEText(dptr,24, scratchPstring);
|
||||||
StringToNum(scratchPstring, &scratchlong);
|
StringToNum(scratchPstring, &scratchlong);
|
||||||
gApplicationPrefs->cacheDelay = scratchlong;
|
gApplicationPrefs->cacheDelay = scratchlong;
|
||||||
|
gApplicationPrefs->useKeyChain = GetCntlVal(dptr, 41);
|
||||||
/* NONO */
|
/* NONO */
|
||||||
|
|
||||||
gApplicationPrefs->CommandKeys = GetCntlVal(dptr, PrefCMDkey);
|
gApplicationPrefs->CommandKeys = GetCntlVal(dptr, PrefCMDkey);
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
#include "memory.proto.h"
|
#include "memory.proto.h"
|
||||||
#include "AddressXLation.h"
|
#include "AddressXLation.h"
|
||||||
|
|
||||||
|
#include <KeyChain.h>
|
||||||
|
|
||||||
#define _POSIX_SOURCE 1
|
#define _POSIX_SOURCE 1
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -253,6 +255,11 @@ void InquireEnvironment( void)
|
||||||
}
|
}
|
||||||
|
|
||||||
TelInfo->haveColorQuickDraw = theWorld.hasColorQD;
|
TelInfo->haveColorQuickDraw = theWorld.hasColorQD;
|
||||||
|
#if GENERATINGCFM
|
||||||
|
TelInfo->haveKeyChain = KeychainManagerAvailable();
|
||||||
|
#else
|
||||||
|
TelInfo->haveKeyChain = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define kURLEventClass 'GURL'
|
#define kURLEventClass 'GURL'
|
||||||
|
|
|
@ -24,14 +24,22 @@
|
||||||
#include <Notification.h>
|
#include <Notification.h>
|
||||||
#include <Dialogs.h>
|
#include <Dialogs.h>
|
||||||
#include <TextEdit.h>
|
#include <TextEdit.h>
|
||||||
|
#include <Keychain.h>
|
||||||
|
|
||||||
#include "PasswordDialog.h"
|
#include "PasswordDialog.h"
|
||||||
#include "movableModal.h"
|
#include "movableModal.h"
|
||||||
#include "event.proto.h"
|
#include "event.proto.h"
|
||||||
#include "netevent.proto.h"
|
#include "netevent.proto.h"
|
||||||
#include "DlogUtils.proto.h"
|
#include "DlogUtils.proto.h"
|
||||||
|
#include "wind.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
extern void ssh2_sched();
|
extern void ssh2_sched();
|
||||||
|
extern WindRec *ssh2_window();
|
||||||
|
|
||||||
|
extern void setctxprompt(const char *prompt);
|
||||||
|
extern char *getctxprompt();
|
||||||
|
|
||||||
extern TelInfoRec *TelInfo;
|
extern TelInfoRec *TelInfo;
|
||||||
extern Boolean gAEavail;
|
extern Boolean gAEavail;
|
||||||
|
@ -368,11 +376,144 @@ Boolean SSH2LoginDialog(StringPtr host, StringPtr login, StringPtr password)
|
||||||
return item == 1;
|
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;
|
DialogPtr dlog;
|
||||||
short item = 0;
|
short item = 0;
|
||||||
|
Boolean addKey = false;
|
||||||
ModalFilterUPP internalBufferFilterUPP;
|
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 );
|
InteractWithUser( true, 128, 128 );
|
||||||
|
|
||||||
|
@ -381,12 +522,29 @@ Boolean SSH2PasswordDialog(StringPtr prompt, StringPtr password)
|
||||||
*password = '\0';
|
*password = '\0';
|
||||||
dlog = GetNewMyDialog(rSSH2PasswordDialog, 0L, (WindowPtr)-1L, NULL);
|
dlog = GetNewMyDialog(rSSH2PasswordDialog, 0L, (WindowPtr)-1L, NULL);
|
||||||
if ( dlog ) {
|
if ( dlog ) {
|
||||||
|
Str255 pprompt;
|
||||||
SInt16 itemType;
|
SInt16 itemType;
|
||||||
Handle itemHandle;
|
Handle itemHandle;
|
||||||
Rect itemRect;
|
Rect itemRect;
|
||||||
|
ControlHandle cntlHandle;
|
||||||
|
WindRec *wind = ssh2_window();
|
||||||
// set prompt
|
// 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);
|
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);
|
SetDialogDefaultItem(dlog, 1);
|
||||||
SetDialogCancelItem(dlog, 2);
|
SetDialogCancelItem(dlog, 2);
|
||||||
SetDialogTracksCursor(dlog, 1);
|
SetDialogTracksCursor(dlog, 1);
|
||||||
|
@ -394,16 +552,25 @@ Boolean SSH2PasswordDialog(StringPtr prompt, StringPtr password)
|
||||||
SetWRefCon(dlog, (long)password); // Stash the buffer's address
|
SetWRefCon(dlog, (long)password); // Stash the buffer's address
|
||||||
do {
|
do {
|
||||||
movableModalDialog(internalBufferFilterUPP, &item);
|
movableModalDialog(internalBufferFilterUPP, &item);
|
||||||
|
if (item == 6) {
|
||||||
|
SetControlValue(cntlHandle, !GetControlValue(cntlHandle));
|
||||||
|
}
|
||||||
} while (item != 1 && item != 2); // Until the OK button is hit
|
} while (item != 1 && item != 2); // Until the OK button is hit
|
||||||
|
addKey = GetControlValue(cntlHandle);
|
||||||
DisposeDialog(dlog);
|
DisposeDialog(dlog);
|
||||||
}
|
}
|
||||||
DisposeRoutineDescriptor(internalBufferFilterUPP);
|
DisposeRoutineDescriptor(internalBufferFilterUPP);
|
||||||
ResetMenus();
|
ResetMenus();
|
||||||
|
#if GENERATINGCFM
|
||||||
|
if ( item == 1 && addKey ) {
|
||||||
|
AddPassToKeychain( prompt, password );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return item == 1;
|
return item == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static short SSH2SOCDialog(char *fingerprint, int id)
|
static short SSH2SOCDialog(const char *fingerprint, int id)
|
||||||
{
|
{
|
||||||
DialogPtr dlog;
|
DialogPtr dlog;
|
||||||
short item = 3; /* cancel */
|
short item = 3; /* cancel */
|
||||||
|
@ -442,12 +609,12 @@ static short SSH2SOCDialog(char *fingerprint, int id)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
short SSH2SOC1Dialog(char *fingerprint)
|
short SSH2SOC1Dialog(const char *fingerprint)
|
||||||
{
|
{
|
||||||
return SSH2SOCDialog(fingerprint, rSSH2SOC1Dialog);
|
return SSH2SOCDialog(fingerprint, rSSH2SOC1Dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
short SSH2SOC2Dialog(char *fingerprint)
|
short SSH2SOC2Dialog(const char *fingerprint)
|
||||||
{
|
{
|
||||||
return SSH2SOCDialog(fingerprint, rSSH2SOC2Dialog);
|
return SSH2SOCDialog(fingerprint, rSSH2SOC2Dialog);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,9 @@ Boolean SSH2RandomizeDialog( long *type, long *level, long *encrypt, Str255 labe
|
||||||
void SSH2ErrorDialog(char *mess1);
|
void SSH2ErrorDialog(char *mess1);
|
||||||
|
|
||||||
Boolean SSH2LoginDialog(StringPtr inhost, StringPtr iologin, StringPtr outpassword);
|
Boolean SSH2LoginDialog(StringPtr inhost, StringPtr iologin, StringPtr outpassword);
|
||||||
Boolean SSH2PasswordDialog (StringPtr inprompt, StringPtr outpassword);
|
Boolean SSH2PasswordDialog (const char *inprompt, StringPtr outpassword);
|
||||||
short SSH2SOC1Dialog(char *fingerprint);
|
short SSH2SOC1Dialog(const char *fingerprint);
|
||||||
short SSH2SOC2Dialog(char *fingerprint);
|
short SSH2SOC2Dialog(const char *fingerprint);
|
||||||
|
|
||||||
void InternalBufferDialog (StringPtr inprompt, StringPtr outpassword);
|
void InternalBufferDialog (StringPtr inprompt, StringPtr outpassword);
|
||||||
Boolean YesNoDialog (StringPtr inprompt);
|
Boolean YesNoDialog (StringPtr inprompt);
|
||||||
|
|
|
@ -781,11 +781,9 @@ char *getpass( const char *prompt )
|
||||||
wind->sshdata.password[0] = '\0';
|
wind->sshdata.password[0] = '\0';
|
||||||
valid = 1;
|
valid = 1;
|
||||||
} else {
|
} else {
|
||||||
pprompt[0] = strlen(prompt);
|
|
||||||
memcpy(pprompt + 1, prompt, pprompt[0]);
|
|
||||||
ppassword[0] = 0;
|
ppassword[0] = 0;
|
||||||
pthread_mutex_lock( &dialock );
|
pthread_mutex_lock( &dialock );
|
||||||
valid = SSH2PasswordDialog(pprompt, ppassword);
|
valid = SSH2PasswordDialog(prompt, ppassword);
|
||||||
pthread_mutex_unlock( &dialock );
|
pthread_mutex_unlock( &dialock );
|
||||||
if (valid) {
|
if (valid) {
|
||||||
memcpy(password, ppassword + 1, ppassword[0]);
|
memcpy(password, ppassword + 1, ppassword[0]);
|
||||||
|
@ -805,12 +803,9 @@ char *getpass( const char *prompt )
|
||||||
&& getnextcachedpassphrase(prompt, context->_kpassword, &context->_kindex) ) {
|
&& getnextcachedpassphrase(prompt, context->_kpassword, &context->_kindex) ) {
|
||||||
return context->_kpassword;
|
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;
|
context->_kpassword[0] = 0;
|
||||||
pthread_mutex_lock( &dialock );
|
pthread_mutex_lock( &dialock );
|
||||||
valid = SSH2PasswordDialog(pprompt, (StringPtr)context->_kpassword);
|
valid = SSH2PasswordDialog(prompt, (StringPtr)context->_kpassword);
|
||||||
pthread_mutex_unlock( &dialock );
|
pthread_mutex_unlock( &dialock );
|
||||||
if (valid) {
|
if (valid) {
|
||||||
plen = context->_kpassword[0];
|
plen = context->_kpassword[0];
|
||||||
|
@ -825,6 +820,23 @@ char *getpass( const char *prompt )
|
||||||
return (valid) ? password : NULL;
|
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
|
* save_once_cancel1
|
||||||
*/
|
*/
|
||||||
|
@ -1110,6 +1122,7 @@ void init_context(lshcontext *context, short port)
|
||||||
context->_kpassword[0] = 0;
|
context->_kpassword[0] = 0;
|
||||||
context->_kindex = 0;
|
context->_kindex = 0;
|
||||||
context->_pindex = 0;
|
context->_pindex = 0;
|
||||||
|
context->_keychainprompt[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue