>From 0f8fed558c34411e58da0dbfffdde29309f5cddb Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Mon, 27 Aug 2012 04:43:23 -0400
Subject: [PATCH 1/3] SSH: Return error code in SSH utility functions

---
 src/responder/ssh/sshsrv_cmd.c              | 13 ++++----
 src/sss_client/ssh/sss_ssh_authorizedkeys.c | 13 ++++----
 src/util/sss_ssh.c                          | 47 +++++++++++++++++++++--------
 src/util/sss_ssh.h                          | 10 +++---
 4 files changed, 54 insertions(+), 29 deletions(-)

diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
index 3c67fd4..a689515 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -420,6 +420,7 @@ ssh_host_pubkeys_format_known_host_plain(TALLOC_CTX *mem_ctx,
                                          struct sss_ssh_ent *ent)
 {
     TALLOC_CTX *tmp_ctx;
+    errno_t ret;
     char *name, *pubkey;
     char *result = NULL;
     size_t i;
@@ -447,9 +448,9 @@ ssh_host_pubkeys_format_known_host_plain(TALLOC_CTX *mem_ctx,
     }
 
     for (i = 0; i < ent->num_pubkeys; i++) {
-        pubkey = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
-                                       SSS_SSH_FORMAT_OPENSSH, "");
-        if (!pubkey) {
+        ret = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
+                                    SSS_SSH_FORMAT_OPENSSH, "", &pubkey);
+        if (ret != EOK) {
             result = NULL;
             goto done;
         }
@@ -491,9 +492,9 @@ ssh_host_pubkeys_format_known_host_hashed(TALLOC_CTX *mem_ctx,
     }
 
     for (i = 0; i < ent->num_pubkeys; i++) {
-        pubkey = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
-                                       SSS_SSH_FORMAT_OPENSSH, "");
-        if (!pubkey) {
+        ret = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
+                                    SSS_SSH_FORMAT_OPENSSH, "", &pubkey);
+        if (ret != EOK) {
             result = NULL;
             goto done;
         }
diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
index dd9a062..74b9693 100644
--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
@@ -109,12 +109,13 @@ int main(int argc, const char **argv)
 
     /* print results */
     for (i = 0; i < ent->num_pubkeys; i++) {
-        repr = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i],
-                                     SSS_SSH_FORMAT_OPENSSH, NULL);
-        if (!repr) {
-            ERROR("Not enough memory\n");
-            ret = EXIT_FAILURE;
-            goto fini;
+        ret = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i],
+                                    SSS_SSH_FORMAT_OPENSSH, NULL, &repr);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  ("sss_ssh_format_pubkey() failed (%d): %s\n",
+                    ret, strerror(ret)));
+            continue;
         }
 
         printf("%s\n", repr);
diff --git a/src/util/sss_ssh.c b/src/util/sss_ssh.c
index 60ed587..a713eab 100644
--- a/src/util/sss_ssh.c
+++ b/src/util/sss_ssh.c
@@ -111,38 +111,50 @@ done:
     return ret;
 }
 
-char *
+errno_t
 sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx,
-                             struct sss_ssh_pubkey *pubkey)
+                             struct sss_ssh_pubkey *pubkey,
+                             char **result)
 {
     size_t c = 0;
     uint32_t algo_len;
     char *algo;
 
+    if (pubkey->data_len < 5) {
+        return EINVAL;
+    }
+
     SAFEALIGN_COPY_UINT32(&algo_len, pubkey->data, &c);
     algo_len = ntohl(algo_len);
+    if (algo_len < 1 || algo_len > 64 || algo_len > pubkey->data_len - 4) {
+        /* the maximum length of 64 is defined in RFC 4250 */
+        return EINVAL;
+    }
 
     algo = talloc_zero_array(mem_ctx, char, algo_len+1);
     if (!algo) {
-        return NULL;
+        return ENOMEM;
     }
 
     memcpy(algo, pubkey->data+c, algo_len);
 
-    return algo;
+    *result = algo;
+    return EOK;
 }
 
-char *
+errno_t
 sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
                       struct sss_ssh_ent *ent,
                       struct sss_ssh_pubkey *pubkey,
                       enum sss_ssh_pubkey_format format,
-                      const char *comment)
+                      const char *comment,
+                      char **result)
 {
     TALLOC_CTX *tmp_ctx;
+    errno_t ret;
     char *blob;
     char *algo;
-    char *result = NULL;
+    char *out = NULL;
 
     if (!comment) {
         comment = ent->name;
@@ -150,33 +162,42 @@ sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
 
     tmp_ctx = talloc_new(NULL);
     if (!tmp_ctx) {
-        return NULL;
+        return ENOMEM;
     }
 
     blob = sss_base64_encode(tmp_ctx, pubkey->data, pubkey->data_len);
     if (!blob) {
+        ret = ENOMEM;
         goto done;
     }
 
     switch (format) {
     case SSS_SSH_FORMAT_RAW:
         /* base64-encoded key blob */
-        result = talloc_steal(mem_ctx, blob);
+        out = talloc_steal(mem_ctx, blob);
         break;
 
     case SSS_SSH_FORMAT_OPENSSH:
         /* OpenSSH authorized_keys/known_hosts format */
-        algo = sss_ssh_get_pubkey_algorithm(tmp_ctx, pubkey);
-        if (!algo) {
+        ret = sss_ssh_get_pubkey_algorithm(tmp_ctx, pubkey, &algo);
+        if (ret != EOK) {
+            goto done;
+        }
+
+        out = talloc_asprintf(mem_ctx, "%s %s %s", algo, blob, comment);
+        if (!out) {
+            ret = ENOMEM;
             goto done;
         }
 
-        result = talloc_asprintf(mem_ctx, "%s %s %s", algo, blob, comment);
         break;
     }
 
+    *result = out;
+    ret = EOK;
+
 done:
     talloc_free(tmp_ctx);
 
-    return result;
+    return ret;
 }
diff --git a/src/util/sss_ssh.h b/src/util/sss_ssh.h
index 29743a0..ef663d9 100644
--- a/src/util/sss_ssh.h
+++ b/src/util/sss_ssh.h
@@ -41,20 +41,22 @@ sss_ssh_make_ent(TALLOC_CTX *mem_ctx,
                  struct ldb_message *msg,
                  struct sss_ssh_ent **result);
 
-char *
+errno_t
 sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx,
-                             struct sss_ssh_pubkey *pubkey);
+                             struct sss_ssh_pubkey *pubkey,
+                             char **result);
 
 enum sss_ssh_pubkey_format {
     SSS_SSH_FORMAT_RAW,
     SSS_SSH_FORMAT_OPENSSH
 };
 
-char *
+errno_t
 sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
                       struct sss_ssh_ent *ent,
                       struct sss_ssh_pubkey *pubkey,
                       enum sss_ssh_pubkey_format format,
-                      const char *comment);
+                      const char *comment,
+                      char **result);
 
 #endif /* _SSS_SSH_H_ */
-- 
1.7.11.4

