mirror of https://github.com/cy384/ssheven.git
key-based authentication
This commit is contained in:
parent
560e77cccb
commit
749b6a3a22
|
@ -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
170
ssheven.c
|
@ -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)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <Scrap.h>
|
||||
#include <Controls.h>
|
||||
#include <ControlDefinitions.h>
|
||||
#include <StandardFile.h>
|
||||
|
||||
// libssh2
|
||||
#include <libssh2.h>
|
||||
|
|
83
ssheven.r
83
ssheven.r
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue