[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Question on ssh_auth_pubkey (was: privatekey_from_file)


Hi Andreas,

Please see the attached patches, implementing 1. and 2. respectively.
With this new function and the callback system, I can probably eliminate
more than 100 lines of code in my program.

Thanks,

Vic

On Tue, 2009-12-29 at 18:10 +0100, Andreas Schneider wrote:
> On Tuesday 22 December 2009 13:44:41 Vic Lee wrote:
> > Hmm... after some checking in auth.c, it seems there's no way to change
> > ssh_auth_pubkey() function to check the existence of a .pub file, since
> > it does not have a file name parameter. So how about this:
> > 
> > 1. In ssh_auth_pubkey(), if publickey is NULL, call
> > publickey_from_privatekey() to generate it.
> > 
> > 2. Add a new function ssh_auth_privatekey_file(), which takes the file
> > name and passphrase of the private key as parameter. The logic looks
> > like:
> > ssh_auth_privatekey_file(keyfile, passphrase) {
> >   if (exists <keyfile>.pub) {
> >     pubkey = publickey_from_file(<keyfile>.pub, &keytype);
> >     privkey = privatekey_from_file(<keyfile>, keytype, passphrase);
> >     ssh_auth_pubkey(pubkey, privkey);
> >   }
> >   else {
> >     /* auto-detect private key type */
> >     privkey = privatekey_from_file(<keyfile>, 0, passphrase);
> >     /* auto-generate pubkey implemented in 1. above */
> >     ssh_auth_pubkey(NULL, privkey);
> >   }
> > }
> > 
> 
> Ups, sorry for the late reply. I've talked to Aris and this sounds good.
> 
> We try to fix master and keep it will try to keep it in a working state in the 
> future. Authentication works again...
> 
> I will try to start with gssapi support, but first I will implement some 
> testing framework.
> 
> 
> 
> 	-- andreas

From 043654ba5cb00d1aca05ed670175b7fad66d7a6d Mon Sep 17 00:00:00 2001
From: Vic Lee <llyzs@xxxxxxx>
Date: Wed, 30 Dec 2009 10:40:34 +0800
Subject: [PATCH 1/2] In ssh_userauth_pubkey, if publickey argument is NULL, generate it from privatekey.


Signed-off-by: Vic Lee <llyzs@xxxxxxx>
---
 libssh/auth.c |   20 ++++++++++++++++++--
 1 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libssh/auth.c b/libssh/auth.c
index 171f4b7..48871ed 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -408,7 +408,8 @@ error:
  *                      ssh_option_set_username() has been used. You cannot try
  *                      two different logins in a row.
  *
- * @param publickey     A public key returned by publickey_from_file().
+ * @param publickey     A public key returned by publickey_from_file(), or NULL
+ *                      to generate automatically from privatekey.
  *
  * @param privatekey    A private key returned by privatekey_from_file().
  *
@@ -430,6 +431,8 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
   ssh_string method = NULL;
   ssh_string algo = NULL;
   ssh_string sign = NULL;
+  ssh_public_key pk = NULL;
+  ssh_string pkstr = NULL;
   int rc = SSH_AUTH_ERROR;
 
   enter_function();
@@ -475,6 +478,17 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
   if (algo == NULL) {
     goto error;
   }
+  if (publickey == NULL) {
+    pk = publickey_from_privatekey(privatekey);
+    if (pk == NULL) {
+      goto error;
+    }
+    pkstr = publickey_to_string(pk);
+    publickey_free(pk);
+    if (pkstr == NULL) {
+      goto error;
+    }
+  }
 
   /* we said previously the public key was accepted */
   if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_REQUEST) < 0 ||
@@ -483,7 +497,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
       buffer_add_ssh_string(session->out_buffer, method) < 0 ||
       buffer_add_u8(session->out_buffer, 1) < 0 ||
       buffer_add_ssh_string(session->out_buffer, algo) < 0 ||
-      buffer_add_ssh_string(session->out_buffer, publickey) < 0) {
+      buffer_add_ssh_string(session->out_buffer, (publickey == NULL ? pkstr : publickey)) < 0) {
     goto error;
   }
 
@@ -491,6 +505,7 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
   string_free(service);
   string_free(method);
   string_free(algo);
+  string_free(pkstr);
 
   sign = ssh_do_sign(session,session->out_buffer, privatekey);
   if (sign) {
@@ -514,6 +529,7 @@ error:
   string_free(service);
   string_free(method);
   string_free(algo);
+  string_free(pkstr);
 
   leave_function();
   return rc;
-- 
1.6.5

From 1f14eee07c84a96e50694c19a93a955e66fc0967 Mon Sep 17 00:00:00 2001
From: Vic Lee <llyzs@xxxxxxx>
Date: Wed, 30 Dec 2009 12:02:36 +0800
Subject: [PATCH 2/2] Add new API function ssh_userauth_privatekey_file().


Signed-off-by: Vic Lee <llyzs@xxxxxxx>
---
 include/libssh/libssh.h |    2 +
 libssh/auth.c           |   66 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 4ea7430..e685cc9 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -426,6 +426,8 @@ LIBSSH_API int ssh_userauth_none(ssh_session session, const char *username);
 LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
 LIBSSH_API int ssh_userauth_password(ssh_session session, const char *username, const char *password);
 LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
+LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
+    const char *filename, const char *passphrase);
 LIBSSH_API const char *ssh_version(int req_version);
 LIBSSH_API int ssh_write_knownhost(ssh_session session);
 
diff --git a/libssh/auth.c b/libssh/auth.c
index 48871ed..dc86874 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -535,6 +535,72 @@ error:
   return rc;
 }
 
+/**
+ * @brief Try to authenticate through a private key file.
+ *
+ * @param session       The ssh session to use.
+ *
+ * @param username      The username to authenticate. You can specify NULL if
+ *                      ssh_option_set_username() has been used. You cannot try
+ *                      two different logins in a row.
+ *
+ * @param filename      Filename containing the private key.
+ *
+ * @param passphrase    Passphrase to decrypt the private key. Set to null if
+ *                      none is needed or it is unknown.
+ *
+ * @returns SSH_AUTH_ERROR:   A serious error happened.\n
+ *          SSH_AUTH_DENIED:  Authentication failed: use another method.\n
+ *          SSH_AUTH_PARTIAL: You've been partially authenticated, you still
+ *                            have to use another method.\n
+ *          SSH_AUTH_SUCCESS: Authentication successful.
+ *
+ * @see publickey_from_file()
+ * @see privatekey_from_file()
+ * @see privatekey_free()
+ * @see ssh_userauth_pubkey()
+ */
+int ssh_userauth_privatekey_file(ssh_session session, const char *username,
+    const char *filename, const char *passphrase) {
+  char *pubkeyfile = NULL;
+  ssh_string pubkey = NULL;
+  ssh_private_key privkey = NULL;
+  int type = 0;
+  int rc = SSH_AUTH_ERROR;
+
+  enter_function();
+
+  pubkeyfile = malloc(strlen(filename) + 1 + 4);
+  if (pubkeyfile == NULL) {
+    leave_function();
+    return SSH_AUTH_ERROR;
+  }
+  sprintf(pubkeyfile, "%s.pub", filename);
+
+  pubkey = publickey_from_file(session, pubkeyfile, &type);
+  if (pubkey == NULL) {
+    ssh_log(session, SSH_LOG_RARE, "Public key file %s not found. Trying to generate it.", pubkeyfile);
+    /* auto-detect the key type with type=0 */
+    privkey = privatekey_from_file(session, filename, 0, passphrase);
+  } else {
+    ssh_log(session, SSH_LOG_RARE, "Public key file %s loaded.", pubkeyfile);
+    privkey = privatekey_from_file(session, filename, type, passphrase);
+  }
+  if (privkey == NULL) {
+    goto error;
+  }
+  /* ssh_userauth_pubkey is responsible for taking care of null-pubkey */
+  rc = ssh_userauth_pubkey(session, username, pubkey, privkey);
+  privatekey_free(privkey);
+
+error:
+  SAFE_FREE(pubkeyfile);
+  string_free(pubkey);
+
+  leave_function();
+  return rc;
+}
+
 #ifndef _WIN32
 /**
  * @brief Try to authenticate through public key with an ssh agent.
-- 
1.6.5


References:
Question on privatekey_from_fileVic Lee <llyzs@xxxxxxx>
Re: Question on privatekey_from_fileAndreas Schneider <mail@xxxxxxxxxxxx>
Re: Question on ssh_auth_pubkey (was: privatekey_from_file)Vic Lee <llyzs@xxxxxxx>
Re: Question on ssh_auth_pubkey (was: privatekey_from_file)Andreas Schneider <mail@xxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org