version 1.22.2.3, 2001/03/21 19:46:29 |
version 1.22.2.4, 2001/05/07 21:09:35 |
|
|
#include "pathnames.h" |
#include "pathnames.h" |
#include "readpass.h" |
#include "readpass.h" |
|
|
|
/* we keep a cache of one passphrases */ |
|
static char *pass = NULL; |
void |
void |
|
clear_pass(void) |
|
{ |
|
if (pass) { |
|
memset(pass, 0, strlen(pass)); |
|
xfree(pass); |
|
pass = NULL; |
|
} |
|
} |
|
|
|
void |
delete_file(AuthenticationConnection *ac, const char *filename) |
delete_file(AuthenticationConnection *ac, const char *filename) |
{ |
{ |
Key *public; |
Key *public; |
char *comment; |
char *comment = NULL; |
|
|
public = key_new(KEY_RSA1); |
public = key_load_public(filename, &comment); |
if (!load_public_key(filename, public, &comment)) { |
if (public == NULL) { |
key_free(public); |
printf("Bad key file %s\n", filename); |
public = key_new(KEY_UNSPEC); |
return; |
if (!try_load_public_key(filename, public, &comment)) { |
|
printf("Bad key file %s\n", filename); |
|
return; |
|
} |
|
} |
} |
if (ssh_remove_identity(ac, public)) |
if (ssh_remove_identity(ac, public)) |
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); |
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); |
|
|
fprintf(stderr, "Failed to remove all identities.\n"); |
fprintf(stderr, "Failed to remove all identities.\n"); |
} |
} |
|
|
char * |
|
ssh_askpass(char *askpass, char *msg) |
|
{ |
|
pid_t pid; |
|
size_t len; |
|
char *nl, *pass; |
|
int p[2], status; |
|
char buf[1024]; |
|
|
|
if (fflush(stdout) != 0) |
|
error("ssh_askpass: fflush: %s", strerror(errno)); |
|
if (askpass == NULL) |
|
fatal("internal error: askpass undefined"); |
|
if (pipe(p) < 0) |
|
fatal("ssh_askpass: pipe: %s", strerror(errno)); |
|
if ((pid = fork()) < 0) |
|
fatal("ssh_askpass: fork: %s", strerror(errno)); |
|
if (pid == 0) { |
|
close(p[0]); |
|
if (dup2(p[1], STDOUT_FILENO) < 0) |
|
fatal("ssh_askpass: dup2: %s", strerror(errno)); |
|
execlp(askpass, askpass, msg, (char *) 0); |
|
fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); |
|
} |
|
close(p[1]); |
|
len = read(p[0], buf, sizeof buf); |
|
close(p[0]); |
|
while (waitpid(pid, &status, 0) < 0) |
|
if (errno != EINTR) |
|
break; |
|
if (len <= 1) |
|
return xstrdup(""); |
|
nl = strchr(buf, '\n'); |
|
if (nl) |
|
*nl = '\0'; |
|
pass = xstrdup(buf); |
|
memset(buf, 0, sizeof(buf)); |
|
return pass; |
|
} |
|
|
|
void |
void |
add_file(AuthenticationConnection *ac, const char *filename) |
add_file(AuthenticationConnection *ac, const char *filename) |
{ |
{ |
struct stat st; |
struct stat st; |
Key *public; |
|
Key *private; |
Key *private; |
char *saved_comment, *comment, *askpass = NULL; |
char *comment = NULL; |
char buf[1024], msg[1024]; |
char msg[1024]; |
int success; |
|
int interactive = isatty(STDIN_FILENO); |
|
int type = KEY_RSA1; |
|
|
|
if (stat(filename, &st) < 0) { |
if (stat(filename, &st) < 0) { |
perror(filename); |
perror(filename); |
exit(1); |
exit(1); |
} |
} |
/* |
|
* try to load the public key. right now this only works for RSA, |
|
* since DSA keys are fully encrypted |
|
*/ |
|
public = key_new(KEY_RSA1); |
|
if (!load_public_key(filename, public, &saved_comment)) { |
|
/* ok, so we will assume this is 'some' key */ |
|
type = KEY_UNSPEC; |
|
saved_comment = xstrdup(filename); |
|
} |
|
key_free(public); |
|
|
|
if (!interactive && getenv("DISPLAY")) { |
|
if (getenv(SSH_ASKPASS_ENV)) |
|
askpass = getenv(SSH_ASKPASS_ENV); |
|
else |
|
askpass = _PATH_SSH_ASKPASS_DEFAULT; |
|
} |
|
|
|
/* At first, try empty passphrase */ |
/* At first, try empty passphrase */ |
private = key_new(type); |
private = key_load_private(filename, "", &comment); |
success = load_private_key(filename, "", private, &comment); |
if (comment == NULL) |
if (!success) { |
comment = xstrdup(filename); |
|
/* try last */ |
|
if (private == NULL && pass != NULL) |
|
private = key_load_private(filename, pass, NULL); |
|
if (private == NULL) { |
|
/* clear passphrase since it did not work */ |
|
clear_pass(); |
printf("Need passphrase for %.200s\n", filename); |
printf("Need passphrase for %.200s\n", filename); |
if (!interactive && askpass == NULL) { |
snprintf(msg, sizeof msg, "Enter passphrase for %.200s ", |
xfree(saved_comment); |
comment); |
return; |
|
} |
|
snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment); |
|
for (;;) { |
for (;;) { |
char *pass; |
pass = read_passphrase(msg, 1); |
if (interactive) { |
|
snprintf(buf, sizeof buf, "%s: ", msg); |
|
pass = read_passphrase(buf, 1); |
|
} else { |
|
pass = ssh_askpass(askpass, msg); |
|
} |
|
if (strcmp(pass, "") == 0) { |
if (strcmp(pass, "") == 0) { |
xfree(pass); |
clear_pass(); |
xfree(saved_comment); |
xfree(comment); |
return; |
return; |
} |
} |
success = load_private_key(filename, pass, private, &comment); |
private = key_load_private(filename, pass, &comment); |
memset(pass, 0, strlen(pass)); |
if (private != NULL) |
xfree(pass); |
|
if (success) |
|
break; |
break; |
strlcpy(msg, "Bad passphrase, try again", sizeof msg); |
clear_pass(); |
|
strlcpy(msg, "Bad passphrase, try again ", sizeof msg); |
} |
} |
} |
} |
xfree(comment); |
if (ssh_add_identity(ac, private, comment)) |
if (ssh_add_identity(ac, private, saved_comment)) |
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); |
fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment); |
|
else |
else |
fprintf(stderr, "Could not add identity: %s\n", filename); |
fprintf(stderr, "Could not add identity: %s\n", filename); |
|
xfree(comment); |
key_free(private); |
key_free(private); |
xfree(saved_comment); |
|
} |
} |
|
|
void |
void |
|
|
else |
else |
add_file(ac, buf); |
add_file(ac, buf); |
} |
} |
|
clear_pass(); |
ssh_close_authentication_connection(ac); |
ssh_close_authentication_connection(ac); |
exit(0); |
exit(0); |
} |
} |