key-based authentication

This commit is contained in:
cy384 2020-09-15 21:17:02 -04:00
parent 560e77cccb
commit 749b6a3a22
4 changed files with 258 additions and 8 deletions

View File

@ -59,6 +59,18 @@
#define ALRT_PW_FAIL 135
#define DITL_PW_FAIL 135
/* alert for requesting public key */
#define ALRT_PUBKEY 136
#define DITL_PUBKEY 136
/* alert for requesting private key */
#define ALRT_PRIVKEY 137
#define DITL_PRIVKEY 137
/* alert for requesting key decryption password */
#define DLOG_KEY_PASSWORD 138
#define DITL_KEY_PASSWORD 138
/* menus */
#define MBAR_SSHEVEN 128
#define MENU_APPLE 128

170
ssheven.c
View File

@ -21,10 +21,13 @@ struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NUL
enum { WAIT, READ, EXIT } read_thread_command = WAIT;
enum { UNINTIALIZED, OPEN, CLEANUP, DONE } read_thread_state = UNINTIALIZED;
enum { KEY_LOGIN, PASSWORD_LOGIN } login_type = PASSWORD_LOGIN;
char hostname[512] = {0};
char username[256] = {0};
char password[256] = {0};
char* pubkey_path = NULL;
char* privkey_path = NULL;
// borrowed from Retro68 sample code
// draws the "default" indicator around a button
@ -541,7 +544,7 @@ pascal Boolean TwoItemFilter(DialogPtr dlog, EventRecord *event, short *itemHit)
// from the ATS password sample code
// 1 for ok, 0 for cancel
int password_dialog(void)
int password_dialog(int dialog_resource)
{
int ret = 1;
// n.b. dialog strings can't be longer than this, so no overflow risk
@ -552,7 +555,7 @@ int password_dialog(void)
Rect box;
DialogItemType type;
dlog = GetNewDialog(DLOG_PASSWORD, 0, (WindowPtr) - 1);
dlog = GetNewDialog(dialog_resource, 0, (WindowPtr) - 1);
// draw default button indicator around the connect button
GetDialogItem(dlog, 2, &type, &itemH, &box);
@ -567,17 +570,154 @@ int password_dialog(void)
// read out of the hidden text box
GetDialogItem(dlog, 5, &type, &itemH, &box);
GetDialogItemText(itemH, (unsigned char*)password);
login_type = PASSWORD_LOGIN;
DisposeDialog(dlog);
return ret;
}
// derived from More Files sample code
OSErr
FSpPathFromLocation(
FSSpec *spec, /* The location we want a path for. */
int *length, /* Length of the resulting path. */
Handle *fullPath) /* Handle to path. */
{
OSErr err;
FSSpec tempSpec;
CInfoPBRec pb;
*fullPath = NULL;
/*
* Make a copy of the input FSSpec that can be modified.
*/
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
if (tempSpec.parID == fsRtParID) {
/*
* The object is a volume. Add a colon to make it a full
* pathname. Allocate a handle for it and we are done.
*/
tempSpec.name[0] += 2;
tempSpec.name[tempSpec.name[0] - 1] = ':';
tempSpec.name[tempSpec.name[0]] = '\0';
err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
} else {
/*
* The object isn't a volume. Is the object a file or a directory?
*/
pb.dirInfo.ioNamePtr = tempSpec.name;
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
pb.dirInfo.ioDrDirID = tempSpec.parID;
pb.dirInfo.ioFDirIndex = 0;
err = PBGetCatInfoSync(&pb);
if ((err == noErr) || (err == fnfErr)) {
/*
* If the file doesn't currently exist we start over. If the
* directory exists everything will work just fine. Otherwise we
* will just fail later. If the object is a directory, append a
* colon so full pathname ends with colon.
*/
if (err == fnfErr) {
BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
} else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
tempSpec.name[0] += 1;
tempSpec.name[tempSpec.name[0]] = ':';
}
/*
* Create a new Handle for the object - make it a C string
*/
tempSpec.name[0] += 1;
tempSpec.name[tempSpec.name[0]] = '\0';
err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
if (err == noErr) {
/*
* Get the ancestor directory names - loop until we have an
* error or find the root directory.
*/
pb.dirInfo.ioNamePtr = tempSpec.name;
pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
pb.dirInfo.ioDrParID = tempSpec.parID;
do {
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
err = PBGetCatInfoSync(&pb);
if (err == noErr) {
/*
* Append colon to directory name and add
* directory name to beginning of fullPath
*/
++tempSpec.name[0];
tempSpec.name[tempSpec.name[0]] = ':';
(void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
tempSpec.name[0]);
err = MemError();
}
} while ( (err == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
}
}
}
/*
* On error Dispose the handle, set it to NULL & return the err.
* Otherwise, set the length & return.
*/
if (err == noErr) {
*length = GetHandleSize(*fullPath) - 1;
} else {
if ( *fullPath != NULL ) {
DisposeHandle(*fullPath);
}
*fullPath = NULL;
*length = 0;
}
return err;
}
int key_dialog(void)
{
// TODO: keys
printf_i("key authentication not implemented yet\r\n");
return 0;
Handle full_path = NULL;
int path_length = 0;
// get public key path
NoteAlert(ALRT_PUBKEY, nil);
StandardFileReply pubkey;
StandardGetFile(NULL, 0, NULL, &pubkey);
FSpPathFromLocation(&pubkey.sfFile, &path_length, &full_path);
pubkey_path = malloc(path_length+1);
strncpy(pubkey_path, (char*)(*full_path), path_length+1);
DisposeHandle(full_path);
path_length = 0;
full_path = NULL;
// if the user hit cancel, 0
if (!pubkey.sfGood) return 0;
// get private key path
NoteAlert(ALRT_PRIVKEY, nil);
StandardFileReply privkey;
StandardGetFile(NULL, 0, NULL, &privkey);
FSpPathFromLocation(&privkey.sfFile, &path_length, &full_path);
privkey_path = malloc(path_length+1);
strncpy(privkey_path, (char*)(*full_path), path_length+1);
DisposeHandle(full_path);
// if the user hit cancel, 0
if (!privkey.sfGood) return 0;
// get the key decryption password
if (!password_dialog(DLOG_KEY_PASSWORD)) return 0;
login_type = KEY_LOGIN;
return 1;
}
int intro_dialog(char* hostname, char* username, char* password)
@ -658,7 +798,7 @@ int intro_dialog(char* hostname, char* username, char* password)
if (use_password)
{
return password_dialog();
return password_dialog(DLOG_PASSWORD);
}
else
{
@ -686,7 +826,20 @@ void* read_thread(void* arg)
if (ok)
{
printf_i("Authenticating... "); YieldToAnyThread();
rc = libssh2_userauth_password(ssh_con.session, username+1, password+1);
if (login_type == PASSWORD_LOGIN)
{
rc = libssh2_userauth_password(ssh_con.session, username+1, password+1);
}
else
{
rc = libssh2_userauth_publickey_fromfile_ex(ssh_con.session,
username+1,
username[0],
pubkey_path,
privkey_path,
password+1);
}
if (rc == LIBSSH2_ERROR_NONE)
{
@ -965,6 +1118,9 @@ int main(int argc, char** argv)
if (ssh_con.recv_buffer != NULL) OTFreeMem(ssh_con.recv_buffer);
if (ssh_con.send_buffer != NULL) OTFreeMem(ssh_con.send_buffer);
if (pubkey_path != NULL) free(pubkey_path);
if (privkey_path != NULL) free(privkey_path);
if (con.vterm != NULL) vterm_free(con.vterm);
if (ssh_con.endpoint != kOTInvalidEndpointRef)

View File

@ -23,6 +23,7 @@
#include <Scrap.h>
#include <Controls.h>
#include <ControlDefinitions.h>
#include <StandardFile.h>
// libssh2
#include <libssh2.h>

View File

@ -110,7 +110,7 @@ resource 'DITL' (DITL_TM) {
resource 'ALRT' (ALRT_TM, purgeable) {
{ 50, 100, 50+80, 100+350 },
ALRT_TM,
DITL_TM,
/* OK means draw default border on first button */
{
@ -203,6 +203,39 @@ resource 'DITL' (DITL_PASSWORD) {
}
};
resource 'DLOG' (DLOG_KEY_PASSWORD) {
{ 50, 100, 150, 420 },
dBoxProc,
visible,
noGoAway,
0,
DLOG_KEY_PASSWORD,
"",
centerMainScreen
};
resource 'DITL' (DITL_KEY_PASSWORD) {
{
{ 70, 320-10-80, 90, 320-10 },
Button { enabled, "OK" };
{ 190-10-20-5, 320-10-80-5, 190-10+5, 320-10+5 },
UserItem { enabled };
{ 10, 10, 30, 310 },
StaticText { enabled, "Key decryption password:" };
{ 35, 15, 51, 305 },
EditText { enabled, "" };
{ 240, 10, 240, 10 },
EditText { enabled, "" };
{ 70, 10, 90, 90 },
Button { enabled, "Cancel" };
}
};
resource 'DITL' (DITL_PW_FAIL) {
{
{ 50, 260, 70, 340 },
@ -227,6 +260,54 @@ resource 'ALRT' (ALRT_PW_FAIL, purgeable) {
alertPositionMainScreen
};
resource 'DITL' (DITL_PUBKEY) {
{
{ 50, 260, 70, 340 },
Button { enabled, "OK" };
{ 10, 70, 30, 340 },
StaticText { enabled, "Please locate your public key." };
}
};
resource 'ALRT' (ALRT_PUBKEY, purgeable) {
{ 50, 100, 50+80, 100+350 },
DITL_PUBKEY,
/* OK means draw default border on first button */
{
OK, visible, silent,
OK, visible, silent,
OK, visible, silent,
OK, visible, silent
},
alertPositionMainScreen
};
resource 'DITL' (DITL_PRIVKEY) {
{
{ 50, 260, 70, 340 },
Button { enabled, "OK" };
{ 10, 70, 30, 340 },
StaticText { enabled, "Please locate your private key." };
}
};
resource 'ALRT' (ALRT_PRIVKEY, purgeable) {
{ 50, 100, 50+80, 100+350 },
DITL_PRIVKEY,
/* OK means draw default border on first button */
{
OK, visible, silent,
OK, visible, silent,
OK, visible, silent,
OK, visible, silent
},
alertPositionMainScreen
};
#include "Processes.r"
resource 'SIZE' (-1) {