[BACK]Return to ssh-add.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/ssh-add.c between version 1.22.2.7 and 1.23

version 1.22.2.7, 2002/03/08 17:04:43 version 1.23, 2000/11/12 19:50:38
Line 11 
Line 11 
  * called by a name other than "ssh" or "Secure Shell".   * called by a name other than "ssh" or "Secure Shell".
  *   *
  * SSH2 implementation,   * SSH2 implementation,
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.   * Copyright (c) 2000 Markus Friedl. All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 38 
Line 38 
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include <openssl/evp.h>  #include <openssl/evp.h>
   #include <openssl/rsa.h>
   #include <openssl/dsa.h>
   
 #include "ssh.h"  
 #include "rsa.h"  #include "rsa.h"
 #include "log.h"  #include "ssh.h"
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "key.h"  #include "key.h"
 #include "authfd.h"  #include "authfd.h"
 #include "authfile.h"  #include "authfile.h"
 #include "pathnames.h"  
 #include "readpass.h"  
   
 /* argv0 */  void
 extern char *__progname;  
   
 /* Default files to add */  
 static char *default_files[] = {  
         _PATH_SSH_CLIENT_ID_RSA,  
         _PATH_SSH_CLIENT_ID_DSA,  
         _PATH_SSH_CLIENT_IDENTITY,  
         NULL  
 };  
   
   
 /* we keep a cache of one passphrases */  
 static char *pass = NULL;  
 static void  
 clear_pass(void)  
 {  
         if (pass) {  
                 memset(pass, 0, strlen(pass));  
                 xfree(pass);  
                 pass = NULL;  
         }  
 }  
   
 static int  
 delete_file(AuthenticationConnection *ac, const char *filename)  delete_file(AuthenticationConnection *ac, const char *filename)
 {  {
         Key *public;          Key *public;
         char *comment = NULL;          char *comment;
         int ret = -1;  
   
         public = key_load_public(filename, &comment);          public = key_new(KEY_RSA1);
         if (public == NULL) {          if (!load_public_key(filename, public, &comment)) {
                 printf("Bad key file %s\n", filename);                  key_free(public);
                 return -1;                  public = key_new(KEY_UNSPEC);
                   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);
                 ret = 0;          else
         } else  
                 fprintf(stderr, "Could not remove identity: %s\n", filename);                  fprintf(stderr, "Could not remove identity: %s\n", filename);
   
         key_free(public);          key_free(public);
         xfree(comment);          xfree(comment);
   
         return ret;  
 }  }
   
 /* Send a request to remove all identities. */  /* Send a request to remove all identities. */
 static int  void
 delete_all(AuthenticationConnection *ac)  delete_all(AuthenticationConnection *ac)
 {  {
         int ret = -1;          int success = 1;
   
         if (ssh_remove_all_identities(ac, 1))          if (!ssh_remove_all_identities(ac, 1))
                 ret = 0;                  success = 0;
         /* ignore error-code for ssh2 */          /* ignore error-code for ssh2 */
         ssh_remove_all_identities(ac, 2);          ssh_remove_all_identities(ac, 2);
   
         if (ret == 0)          if (success)
                 fprintf(stderr, "All identities removed.\n");                  fprintf(stderr, "All identities removed.\n");
         else          else
                 fprintf(stderr, "Failed to remove all identities.\n");                  fprintf(stderr, "Failed to remove all identitities.\n");
   }
   
         return ret;  char *
   ssh_askpass(char *askpass, char *msg)
   {
           pid_t pid;
           size_t len;
           char *nl, *pass;
           int p[2], status;
           char buf[1024];
   
           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;
 }  }
   
 static int  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 *comment = NULL;          char *saved_comment, *comment, *askpass = NULL;
         char msg[1024];          char buf[1024], msg[1024];
         int ret = -1;          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);
                 return -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 = SSH_ASKPASS_DEFAULT;
           }
   
         /* At first, try empty passphrase */          /* At first, try empty passphrase */
         private = key_load_private(filename, "", &comment);          private = key_new(type);
         if (comment == NULL)          success = load_private_key(filename, "", private, &comment);
                 comment = xstrdup(filename);          if (!success) {
         /* try last */                  printf("Need passphrase for %.200s\n", filename);
         if (private == NULL && pass != NULL)                  if (!interactive && askpass == NULL) {
                 private = key_load_private(filename, pass, NULL);                          xfree(saved_comment);
         if (private == NULL) {                          return;
                 /* clear passphrase since it did not work */                  }
                 clear_pass();                  snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
                 snprintf(msg, sizeof msg, "Enter passphrase for %.200s: ",  
                    comment);  
                 for (;;) {                  for (;;) {
                         pass = read_passphrase(msg, RP_ALLOW_STDIN);                          char *pass;
                           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) {
                                 clear_pass();                                  xfree(pass);
                                 xfree(comment);                                  xfree(saved_comment);
                                 return -1;                                  return;
                         }                          }
                         private = key_load_private(filename, pass, &comment);                          success = load_private_key(filename, pass, private, &comment);
                         if (private != NULL)                          memset(pass, 0, strlen(pass));
                           xfree(pass);
                           if (success)
                                 break;                                  break;
                         clear_pass();                          strlcpy(msg, "Bad passphrase, try again", sizeof msg);
                         strlcpy(msg, "Bad passphrase, try again: ", sizeof msg);  
                 }                  }
         }          }
         if (ssh_add_identity(ac, private, comment)) {  
                 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);  
                 ret = 0;  
         } else  
                 fprintf(stderr, "Could not add identity: %s\n", filename);  
   
         xfree(comment);          xfree(comment);
           if (ssh_add_identity(ac, private, saved_comment))
                   fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
           else
                   fprintf(stderr, "Could not add identity: %s\n", filename);
         key_free(private);          key_free(private);
           xfree(saved_comment);
         return ret;  
 }  }
   
 static int  void
 update_card(AuthenticationConnection *ac, int add, const char *id)  list_identities(AuthenticationConnection *ac, int fp)
 {  {
         if (ssh_update_card(ac, add, id)) {  
                 fprintf(stderr, "Card %s: %s\n",  
                     add ? "added" : "removed", id);  
                 return 0;  
         } else {  
                 fprintf(stderr, "Could not %s card: %s\n",  
                     add ? "add" : "remove", id);  
                 return -1;  
         }  
 }  
   
 static int  
 list_identities(AuthenticationConnection *ac, int do_fp)  
 {  
         Key *key;          Key *key;
         char *comment, *fp;          char *comment;
         int had_identities = 0;          int had_identities = 0;
         int version;          int version;
   
         for (version = 1; version <= 2; version++) {          for (version = 1; version <= 2; version++) {
                 for (key = ssh_get_first_identity(ac, &comment, version);                  for (key = ssh_get_first_identity(ac, &comment, version);
                     key != NULL;                       key != NULL;
                     key = ssh_get_next_identity(ac, &comment, version)) {                       key = ssh_get_next_identity(ac, &comment, version)) {
                         had_identities = 1;                          had_identities = 1;
                         if (do_fp) {                          if (fp) {
                                 fp = key_fingerprint(key, SSH_FP_MD5,  
                                     SSH_FP_HEX);  
                                 printf("%d %s %s (%s)\n",                                  printf("%d %s %s (%s)\n",
                                     key_size(key), fp, comment, key_type(key));                                      key_size(key), key_fingerprint(key),
                                 xfree(fp);                                      comment, key_type(key));
                         } else {                          } else {
                                 if (!key_write(key, stdout))                                  if (!key_write(key, stdout))
                                         fprintf(stderr, "key_write failed");                                          fprintf(stderr, "key_write failed");
Line 209 
Line 227 
                         xfree(comment);                          xfree(comment);
                 }                  }
         }          }
         if (!had_identities) {          if (!had_identities)
                 printf("The agent has no identities.\n");                  printf("The agent has no identities.\n");
                 return -1;  
         }  
         return 0;  
 }  }
   
 static int  
 do_file(AuthenticationConnection *ac, int deleting, char *file)  
 {  
         if (deleting) {  
                 if (delete_file(ac, file) == -1)  
                         return -1;  
         } else {  
                 if (add_file(ac, file) == -1)  
                         return -1;  
         }  
         return 0;  
 }  
   
 static void  
 usage(void)  
 {  
         fprintf(stderr, "Usage: %s [options]\n", __progname);  
         fprintf(stderr, "Options:\n");  
         fprintf(stderr, "  -l          List fingerprints of all identities.\n");  
         fprintf(stderr, "  -L          List public key parameters of all identities.\n");  
         fprintf(stderr, "  -d          Delete identity.\n");  
         fprintf(stderr, "  -D          Delete all identities.\n");  
 #ifdef SMARTCARD  
         fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");  
         fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");  
 #endif  
 }  
   
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
         extern char *optarg;  
         extern int optind;  
         AuthenticationConnection *ac = NULL;          AuthenticationConnection *ac = NULL;
         char *sc_reader_id = NULL;          struct passwd *pw;
         int i, ch, deleting = 0, ret = 0;          char buf[1024];
           int no_files = 1;
           int i;
           int deleting = 0;
   
         SSLeay_add_all_algorithms();          SSLeay_add_all_algorithms();
   
         /* At first, get a connection to the authentication agent. */          /* At first, get a connection to the authentication agent. */
         ac = ssh_get_authentication_connection();          ac = ssh_get_authentication_connection();
         if (ac == NULL) {          if (ac == NULL) {
                 fprintf(stderr, "Could not open a connection to your authentication agent.\n");                  fprintf(stderr, "Could not open a connection to your authentication agent.\n");
                 exit(2);                  exit(1);
         }          }
         while ((ch = getopt(argc, argv, "lLdDe:s:")) != -1) {          for (i = 1; i < argc; i++) {
                 switch (ch) {                  if ((strcmp(argv[i], "-l") == 0) ||
                 case 'l':                      (strcmp(argv[i], "-L") == 0)) {
                 case 'L':                          list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
                         if (list_identities(ac, ch == 'l' ? 1 : 0) == -1)                          /* Don't default-add/delete if -l. */
                                 ret = 1;                          no_files = 0;
                         goto done;                          continue;
                         break;                  }
                 case 'd':                  if (strcmp(argv[i], "-d") == 0) {
                         deleting = 1;                          deleting = 1;
                         break;                          continue;
                 case 'D':  
                         if (delete_all(ac) == -1)  
                                 ret = 1;  
                         goto done;  
                         break;  
                 case 's':  
                         sc_reader_id = optarg;  
                         break;  
                 case 'e':  
                         deleting = 1;  
                         sc_reader_id = optarg;  
                         break;  
                 default:  
                         usage();  
                         ret = 1;  
                         goto done;  
                 }                  }
                   if (strcmp(argv[i], "-D") == 0) {
                           delete_all(ac);
                           no_files = 0;
                           continue;
                   }
                   no_files = 0;
                   if (deleting)
                           delete_file(ac, argv[i]);
                   else
                           add_file(ac, argv[i]);
         }          }
         argc -= optind;          if (no_files) {
         argv += optind;                  pw = getpwuid(getuid());
         if (sc_reader_id != NULL) {                  if (!pw) {
                 if (update_card(ac, !deleting, sc_reader_id) == -1)  
                         ret = 1;  
                 goto done;  
         }  
         if (argc == 0) {  
                 char buf[MAXPATHLEN];  
                 struct passwd *pw;  
   
                 if ((pw = getpwuid(getuid())) == NULL) {  
                         fprintf(stderr, "No user found with uid %u\n",                          fprintf(stderr, "No user found with uid %u\n",
                             (u_int)getuid());                              (u_int)getuid());
                         ret = 1;                          ssh_close_authentication_connection(ac);
                         goto done;                          exit(1);
                 }                  }
                   snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
                 for(i = 0; default_files[i]; i++) {                  if (deleting)
                         snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,                          delete_file(ac, buf);
                             default_files[i]);                  else
                         if (do_file(ac, deleting, buf) == -1)                          add_file(ac, buf);
                                 ret = 1;  
                 }  
         } else {  
                 for(i = 0; i < argc; i++) {  
                         if (do_file(ac, deleting, argv[i]) == -1)  
                                 ret = 1;  
                 }  
         }          }
         clear_pass();  
   
 done:  
         ssh_close_authentication_connection(ac);          ssh_close_authentication_connection(ac);
         return ret;          exit(0);
 }  }

Legend:
Removed from v.1.22.2.7  
changed lines
  Added in v.1.23