From 748ba184db97b7534254f97018fa04e8aa458fae Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Sun, 26 Feb 2012 13:24:16 -0500 Subject: SSH: Refactor responder and client common code --- Makefile.am | 11 +- src/sss_client/ssh/sss_ssh.c | 303 --------------------------- src/sss_client/ssh/sss_ssh.h | 63 ------ src/sss_client/ssh/sss_ssh_authorizedkeys.c | 23 +- src/sss_client/ssh/sss_ssh_client.c | 232 ++++++++++++++++++++ src/sss_client/ssh/sss_ssh_client.h | 39 ++++ src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 23 +- src/util/sss_ssh.c | 174 +++++++++++++++ src/util/sss_ssh.h | 59 ++++++ 9 files changed, 529 insertions(+), 398 deletions(-) delete mode 100644 src/sss_client/ssh/sss_ssh.c delete mode 100644 src/sss_client/ssh/sss_ssh.h create mode 100644 src/sss_client/ssh/sss_ssh_client.c create mode 100644 src/sss_client/ssh/sss_ssh_client.h create mode 100644 src/util/sss_ssh.c create mode 100644 src/util/sss_ssh.h diff --git a/Makefile.am b/Makefile.am index 8ce8c64d..a1fafcd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -322,6 +322,7 @@ dist_noinst_HEADERS = \ src/util/sss_krb5.h \ src/util/sss_selinux.h \ src/util/sss_utf8.h \ + src/util/sss_ssh.h \ src/util/refcount.h \ src/util/find_uid.h \ src/util/user_info_msg.h \ @@ -391,7 +392,7 @@ dist_noinst_HEADERS = \ src/resolv/ares/ares_parse_txt_reply.h \ src/resolv/ares/ares_data.h \ src/tests/common.h \ - src/sss_client/ssh/sss_ssh.h + src/sss_client/ssh/sss_ssh_client.h if HAVE_NSS @@ -450,7 +451,9 @@ if BUILD_SUDO libsss_util_la_SOURCES += src/db/sysdb_sudo.c endif if BUILD_SSH - libsss_util_la_SOURCES += src/db/sysdb_ssh.c +libsss_util_la_SOURCES += \ + src/db/sysdb_ssh.c \ + src/util/sss_ssh.c endif lib_LTLIBRARIES = libipa_hbac.la @@ -648,7 +651,7 @@ endif if BUILD_SSH sss_ssh_authorizedkeys_SOURCES = \ src/sss_client/common.c \ - src/sss_client/ssh/sss_ssh.c \ + src/sss_client/ssh/sss_ssh_client.c \ src/sss_client/ssh/sss_ssh_authorizedkeys.c sss_ssh_authorizedkeys_CFLAGS = $(AM_CFLAGS) sss_ssh_authorizedkeys_LDADD = \ @@ -656,7 +659,7 @@ sss_ssh_authorizedkeys_LDADD = \ sss_ssh_knownhostsproxy_SOURCES = \ src/sss_client/common.c \ - src/sss_client/ssh/sss_ssh.c \ + src/sss_client/ssh/sss_ssh_client.c \ src/sss_client/ssh/sss_ssh_knownhostsproxy.c sss_ssh_knownhostsproxy_CFLAGS = $(AM_CFLAGS) sss_ssh_knownhostsproxy_LDADD = \ diff --git a/src/sss_client/ssh/sss_ssh.c b/src/sss_client/ssh/sss_ssh.c deleted file mode 100644 index bb76800a..00000000 --- a/src/sss_client/ssh/sss_ssh.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - Authors: - Jan Cholasta - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "util/crypto/sss_crypto.h" -#include "sss_client/sss_cli.h" -#include "sss_client/ssh/sss_ssh.h" - -/* FIXME - split from tools_util to create a common function */ -void usage(poptContext pc, const char *error) -{ - poptPrintUsage(pc, stderr, 0); - if (error) fprintf(stderr, "%s", error); -} - -/* FIXME - split from tools_util to create a common function */ -int set_locale(void) -{ - char *c; - - c = setlocale(LC_ALL, ""); - if (c == NULL) { - return EIO; - } - - errno = 0; - c = bindtextdomain(PACKAGE, LOCALEDIR); - if (c == NULL) { - return errno; - } - - errno = 0; - c = textdomain(PACKAGE); - if (c == NULL) { - return errno; - } - - return EOK; -} - -/* SSH public key request: - * - * 0..3: flags (unsigned int, must be 0) - * 4..7: name length (unsigned int) - * 8..$: name (null-terminated UTF-8 string) - * - * SSH public key reply: - * - * 0..3: number of results (unsigned int) - * 4..7: reserved (unsigned int, must be 0) - * 8..$: array of results: - * 0..3: flags (unsigned int, must be 0) - * 4..7: name length (unsigned int) - * 8..(X-1): name (null-terminated UTF-8 string) - * X..(X+3): key length (unsigned int) - * (X+4)..Y: key (public key blob as defined in RFC4253, section 6.6) - */ -errno_t -sss_ssh_get_pubkeys(TALLOC_CTX *mem_ctx, - enum sss_cli_command command, - const char *name, - struct sss_ssh_pubkey **pubkeys, - size_t *pubkeys_len) -{ - TALLOC_CTX *tmp_ctx; - errno_t ret = EOK; - uint32_t name_len; - size_t req_len; - uint8_t *req = NULL; - size_t c = 0; - struct sss_cli_req_data rd; - int req_ret, req_errno; - uint8_t *rep = NULL; - size_t rep_len; - uint32_t count, reserved, len, i; - struct sss_ssh_pubkey *result = NULL; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - /* build request */ - name_len = strlen(name)+1; - req_len = 2*sizeof(uint32_t) + name_len; - - req = talloc_array(tmp_ctx, uint8_t, req_len); - if (!req) { - ret = ENOMEM; - goto done; - } - - SAFEALIGN_SET_UINT32(req+c, 0, &c); - SAFEALIGN_SET_UINT32(req+c, name_len, &c); - safealign_memcpy(req+c, name, name_len, &c); - - /* send request */ - rd.data = req; - rd.len = req_len; - - req_ret = sss_ssh_make_request(command, &rd, &rep, &rep_len, &req_errno); - if (req_ret != SSS_STATUS_SUCCESS) { - ret = EFAULT; - goto done; - } - if (req_errno != EOK) { - ret = req_errno; - goto done; - } - - /* parse reply */ - c = 0; - if (rep_len-c < 2*sizeof(uint32_t)) { - ret = EINVAL; - goto done; - } - - SAFEALIGN_COPY_UINT32(&count, rep+c, &c); - - SAFEALIGN_COPY_UINT32(&reserved, rep+c, &c); - if (reserved != 0) { - ret = EINVAL; - goto done; - } - - if (count > 0) { - result = talloc_zero_array(tmp_ctx, struct sss_ssh_pubkey, count); - if (!result) { - ret = ENOMEM; - goto done; - } - } - - for (i = 0; i < count; i++) { - if (rep_len-c < 2*sizeof(uint32_t)) { - ret = EINVAL; - goto done; - } - - SAFEALIGN_COPY_UINT32(&result[i].flags, rep+c, &c); - if (result[i].flags != 0) { - ret = EINVAL; - goto done; - } - - SAFEALIGN_COPY_UINT32(&len, rep+c, &c); - - if (rep_len-c < len + sizeof(uint32_t)) { - ret = EINVAL; - goto done; - } - - result[i].name = talloc_array(result, char, len); - if (!result[i].name) { - ret = ENOMEM; - goto done; - } - - safealign_memcpy(result[i].name, rep+c, len, &c); - if (strnlen(result[i].name, len) != len-1) { - ret = EINVAL; - goto done; - } - - SAFEALIGN_COPY_UINT32(&len, rep+c, &c); - - if (rep_len-c < len) { - ret = EINVAL; - goto done; - } - - result[i].key = talloc_array(result, uint8_t, len); - if (!result[i].key) { - ret = ENOMEM; - goto done; - } - - safealign_memcpy(result[i].key, rep+c, len, &c); - result[i].key_len = len; - } - - *pubkeys = result ? talloc_steal(mem_ctx, result) : NULL; - *pubkeys_len = count; - -done: - talloc_free(tmp_ctx); - - return ret; -} - -char * -sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx, - struct sss_ssh_pubkey *pubkey) -{ - size_t c = 0; - uint32_t algo_len; - char *algo; - - SAFEALIGN_COPY_UINT32(&algo_len, pubkey->key, &c); - algo_len = ntohl(algo_len); - - algo = talloc_zero_array(mem_ctx, char, algo_len+1); - if (!algo) { - return NULL; - } - - memcpy(algo, pubkey->key+c, algo_len); - - return algo; -} - -errno_t -sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx, - struct sss_ssh_pubkey *pubkey, - enum sss_ssh_pubkey_format format, - char **result) -{ - TALLOC_CTX *tmp_ctx; - errno_t ret = EOK; - char *pk; - char *algo; - char *out; - - if (!pubkey) { - return EINVAL; - } - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - pk = sss_base64_encode(tmp_ctx, pubkey->key, pubkey->key_len); - if (!pk) { - ret = ENOMEM; - goto done; - } - - switch (format) { - case SSS_SSH_FORMAT_RAW: - /* base64-encoded key blob */ - - out = talloc_steal(mem_ctx, pk); - - break; - - case SSS_SSH_FORMAT_OPENSSH: - /* OpenSSH authorized_keys/known_hosts format */ - - algo = sss_ssh_get_pubkey_algorithm(tmp_ctx, pubkey); - if (!algo) { - ret = ENOMEM; - goto done; - } - - out = talloc_asprintf(tmp_ctx, "%s %s %s", - algo, pk, pubkey->name); - if (!out) { - ret = ENOMEM; - goto done; - } - - talloc_steal(mem_ctx, out); - - break; - } - - *result = out; - -done: - talloc_free(tmp_ctx); - - return ret; -} diff --git a/src/sss_client/ssh/sss_ssh.h b/src/sss_client/ssh/sss_ssh.h deleted file mode 100644 index 633c3af7..00000000 --- a/src/sss_client/ssh/sss_ssh.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - Authors: - Jan Cholasta - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SSS_SSH_H_ -#define _SSS_SSH_H_ - -void usage(poptContext pc, const char *error); -int set_locale(void); - -#define BAD_POPT_PARAMS(pc, msg, val, label) do { \ - usage(pc, msg); \ - val = EXIT_FAILURE; \ - goto label; \ -} while(0) - -struct sss_ssh_pubkey { - uint32_t flags; - char *name; - - uint8_t *key; - size_t key_len; -}; - -errno_t -sss_ssh_get_pubkeys(TALLOC_CTX *mem_ctx, - enum sss_cli_command command, - const char *name, - struct sss_ssh_pubkey **pubkeys, - size_t *pubkeys_len); - -char * -sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx, - struct sss_ssh_pubkey *pubkey); - -enum sss_ssh_pubkey_format { - SSS_SSH_FORMAT_RAW, - SSS_SSH_FORMAT_OPENSSH -}; - -errno_t -sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx, - struct sss_ssh_pubkey *pubkey, - enum sss_ssh_pubkey_format format, - char **result); - -#endif /* _SSS_SSH_H_ */ diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c index c8aa45c3..bc3cdf47 100644 --- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c +++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c @@ -24,8 +24,9 @@ #include "util/util.h" #include "util/crypto/sss_crypto.h" +#include "util/sss_ssh.h" #include "sss_client/sss_cli.h" -#include "sss_client/ssh/sss_ssh.h" +#include "sss_client/ssh/sss_ssh_client.h" int main(int argc, const char **argv) { @@ -43,8 +44,8 @@ int main(int argc, const char **argv) }; poptContext pc = NULL; const char *user; - struct sss_ssh_pubkey *pubkeys; - size_t num_pubkeys, i; + struct sss_ssh_ent *ent; + size_t i; char *repr; int ret; @@ -96,24 +97,18 @@ int main(int argc, const char **argv) } /* look up public keys */ - ret = sss_ssh_get_pubkeys(mem_ctx, SSS_SSH_GET_USER_PUBKEYS, user, - &pubkeys, &num_pubkeys); + ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_USER_PUBKEYS, user, &ent); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("sss_ssh_get_pubkeys() failed (%d): %s\n", ret, strerror(ret))); ERROR("Error looking up public keys\n"); ret = EXIT_FAILURE; goto fini; } /* print results */ - for (i = 0; i < num_pubkeys; i++) { - ret = sss_ssh_format_pubkey(mem_ctx, &pubkeys[i], - SSS_SSH_FORMAT_OPENSSH, &repr); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - ("sss_ssh_format_pubkey() failed (%d): %s\n", - ret, strerror(ret))); + for (i = 0; i < ent->num_pubkeys; i++) { + repr = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i], + SSS_SSH_FORMAT_OPENSSH); + if (!repr) { continue; } diff --git a/src/sss_client/ssh/sss_ssh_client.c b/src/sss_client/ssh/sss_ssh_client.c new file mode 100644 index 00000000..82507787 --- /dev/null +++ b/src/sss_client/ssh/sss_ssh_client.c @@ -0,0 +1,232 @@ +/* + Authors: + Jan Cholasta + + Copyright (C) 2012 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "util/util.h" +#include "util/crypto/sss_crypto.h" +#include "util/sss_ssh.h" +#include "sss_client/sss_cli.h" +#include "sss_client/ssh/sss_ssh_client.h" + +/* FIXME - split from tools_util to create a common function */ +void usage(poptContext pc, const char *error) +{ + poptPrintUsage(pc, stderr, 0); + if (error) fprintf(stderr, "%s", error); +} + +/* FIXME - split from tools_util to create a common function */ +int set_locale(void) +{ + char *c; + + c = setlocale(LC_ALL, ""); + if (c == NULL) { + return EIO; + } + + errno = 0; + c = bindtextdomain(PACKAGE, LOCALEDIR); + if (c == NULL) { + return errno; + } + + errno = 0; + c = textdomain(PACKAGE); + if (c == NULL) { + return errno; + } + + return EOK; +} + +/* SSH public key request: + * + * 0..3: flags (unsigned int, must be 0) + * 4..7: name length (unsigned int) + * 8..(X-1): name (null-terminated UTF-8 string) + * + * SSH public key reply: + * + * 0..3: number of results (unsigned int) + * 4..7: reserved (unsigned int, must be 0) + * 8..$: array of results: + * 0..3: flags (unsigned int, must be 0) + * 4..7: name length (unsigned int) + * 8..(X-1): name (null-terminated UTF-8 string) + * X..(X+3): key length (unsigned int) + * (X+4)..Y: key (public key blob as defined in RFC4253, section 6.6) + */ +errno_t +sss_ssh_get_ent(TALLOC_CTX *mem_ctx, + enum sss_cli_command command, + const char *name, + struct sss_ssh_ent **result) +{ + TALLOC_CTX *tmp_ctx; + struct sss_ssh_ent *res = NULL; + errno_t ret; + uint32_t flags; + uint32_t name_len; + size_t req_len; + uint8_t *req = NULL; + size_t c = 0; + struct sss_cli_req_data rd; + int req_ret, req_errno; + uint8_t *rep = NULL; + size_t rep_len; + uint32_t count, reserved, len, i; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + /* build request */ + flags = 0; + name_len = strlen(name)+1; + req_len = 2*sizeof(uint32_t) + name_len; + + req = talloc_array(tmp_ctx, uint8_t, req_len); + if (!req) { + ret = ENOMEM; + goto done; + } + + SAFEALIGN_SET_UINT32(req+c, flags, &c); + SAFEALIGN_SET_UINT32(req+c, name_len, &c); + safealign_memcpy(req+c, name, name_len, &c); + + /* send request */ + rd.data = req; + rd.len = req_len; + + req_ret = sss_ssh_make_request(command, &rd, &rep, &rep_len, &req_errno); + if (req_ret != SSS_STATUS_SUCCESS) { + ret = EFAULT; + goto done; + } + if (req_errno != EOK) { + ret = req_errno; + goto done; + } + + /* parse reply */ + c = 0; + if (rep_len-c < 2*sizeof(uint32_t)) { + ret = EINVAL; + goto done; + } + + SAFEALIGN_COPY_UINT32(&count, rep+c, &c); + + SAFEALIGN_COPY_UINT32(&reserved, rep+c, &c); + if (reserved != 0) { + ret = EINVAL; + goto done; + } + + res = talloc_zero(tmp_ctx, struct sss_ssh_ent); + if (!res) { + ret = ENOMEM; + goto done; + } + + if (count > 0) { + res->pubkeys = talloc_zero_array(res, struct sss_ssh_pubkey, count); + if (!res->pubkeys) { + ret = ENOMEM; + goto done; + } + + res->num_pubkeys = count; + } + + for (i = 0; i < count; i++) { + if (rep_len-c < 2*sizeof(uint32_t)) { + ret = EINVAL; + goto done; + } + + SAFEALIGN_COPY_UINT32(&flags, rep+c, &c); + if (flags != 0) { + ret = EINVAL; + goto done; + } + + SAFEALIGN_COPY_UINT32(&len, rep+c, &c); + + if (rep_len-c < len + sizeof(uint32_t)) { + ret = EINVAL; + goto done; + } + + if (!res->name) { + res->name = talloc_array(res, char, len); + if (!res->name) { + ret = ENOMEM; + goto done; + } + + safealign_memcpy(res->name, rep+c, len, &c); + if (strnlen(res->name, len) != len-1) { + ret = EINVAL; + goto done; + } + } else { + c += len; + } + + SAFEALIGN_COPY_UINT32(&len, rep+c, &c); + + if (rep_len-c < len) { + ret = EINVAL; + goto done; + } + + res->pubkeys[i].data = talloc_array(res, uint8_t, len); + if (!res->pubkeys[i].data) { + ret = ENOMEM; + goto done; + } + + safealign_memcpy(res->pubkeys[i].data, rep+c, len, &c); + res->pubkeys[i].data_len = len; + } + + *result = talloc_steal(mem_ctx, res); + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} diff --git a/src/sss_client/ssh/sss_ssh_client.h b/src/sss_client/ssh/sss_ssh_client.h new file mode 100644 index 00000000..1c8db1ff --- /dev/null +++ b/src/sss_client/ssh/sss_ssh_client.h @@ -0,0 +1,39 @@ +/* + Authors: + Jan Cholasta + + Copyright (C) 2012 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SSS_SSH_CLIENT_H_ +#define _SSS_SSH_CLIENT_H_ + +void usage(poptContext pc, const char *error); +int set_locale(void); + +#define BAD_POPT_PARAMS(pc, msg, val, label) do { \ + usage(pc, msg); \ + val = EXIT_FAILURE; \ + goto label; \ +} while(0) + +errno_t +sss_ssh_get_ent(TALLOC_CTX *mem_ctx, + enum sss_cli_command command, + const char *name, + struct sss_ssh_ent **result); + +#endif /* _SSS_SSH_CLIENT_H_ */ diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c index b95dbe8e..fb93e4ad 100644 --- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c +++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c @@ -33,9 +33,10 @@ #include "util/util.h" #include "util/crypto/sss_crypto.h" +#include "util/sss_ssh.h" #include "tools/tools_util.h" #include "sss_client/sss_cli.h" -#include "sss_client/ssh/sss_ssh.h" +#include "sss_client/ssh/sss_ssh_client.h" #define DEFAULT_FILE ".ssh/sss_known_hosts" @@ -247,8 +248,8 @@ int main(int argc, const char **argv) const char *host; FILE *f; struct addrinfo ai_hint, *ai = NULL; - struct sss_ssh_pubkey *pubkeys; - size_t num_pubkeys, i; + struct sss_ssh_ent *ent; + size_t i; char *repr; int ret; @@ -345,11 +346,8 @@ int main(int argc, const char **argv) } /* look up public keys */ - ret = sss_ssh_get_pubkeys(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS, host, - &pubkeys, &num_pubkeys); + ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS, host, &ent); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("sss_ssh_get_pubkeys failed() (%d): %s\n", ret, strerror(ret))); ERROR("Error looking up public keys\n"); ret = EXIT_FAILURE; goto fini; @@ -370,13 +368,10 @@ int main(int argc, const char **argv) fprintf(f, "# Generated by sss_ssh_knownhostsproxy. Please do not modify.\n"); - for (i = 0; i < num_pubkeys; i++) { - ret = sss_ssh_format_pubkey(mem_ctx, &pubkeys[i], - SSS_SSH_FORMAT_OPENSSH, &repr); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - ("sss_ssh_format_pubkey() failed (%d): %s\n", - ret, strerror(ret))); + for (i = 0; i < ent->num_pubkeys; i++) { + repr = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i], + SSS_SSH_FORMAT_OPENSSH); + if (!repr) { continue; } diff --git a/src/util/sss_ssh.c b/src/util/sss_ssh.c new file mode 100644 index 00000000..83c1ec15 --- /dev/null +++ b/src/util/sss_ssh.c @@ -0,0 +1,174 @@ +/* + Authors: + Jan Cholasta + + Copyright (C) 2012 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include "db/sysdb.h" +#include "util/util.h" +#include "util/crypto/sss_crypto.h" +#include "util/sss_ssh.h" + +errno_t +sss_ssh_make_ent(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + struct sss_ssh_ent **result) +{ + TALLOC_CTX *tmp_ctx; + struct sss_ssh_ent *res = NULL; + errno_t ret; + const char *name; + struct ldb_message_element *el; + unsigned int i; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); + if (!name) { + ret = EINVAL; + goto done; + } + + res = talloc_zero(tmp_ctx, struct sss_ssh_ent); + if (!res) { + ret = ENOMEM; + goto done; + } + + res->name = talloc_strdup(res, name); + if (!res->name) { + ret = ENOMEM; + goto done; + } + + el = ldb_msg_find_element(msg, SYSDB_SSH_PUBKEY); + if (el) { + res->num_pubkeys = el->num_values; + + res->pubkeys = talloc_array(res, struct sss_ssh_pubkey, + res->num_pubkeys); + if (!res->pubkeys) { + ret = ENOMEM; + goto done; + } + + for (i = 0; i < el->num_values; i++) { + res->pubkeys[i].data = sss_base64_decode(res->pubkeys, + (char *)el->values[i].data, &res->pubkeys[i].data_len); + if (!res->pubkeys[i].data) { + ret = ENOMEM; + goto done; + } + } + } + + el = ldb_msg_find_element(msg, SYSDB_NAME_ALIAS); + if (el) { + res->num_aliases = el->num_values; + + res->aliases = talloc_array(res, char *, res->num_aliases); + if (!res->aliases) { + ret = ENOMEM; + goto done; + } + + for (i = 0; i < el->num_values; i++) { + res->aliases[i] = talloc_strdup(res->aliases, + (char *)el->values[i].data); + if (!res->aliases[i]) { + ret = ENOMEM; + goto done; + } + } + } + + *result = talloc_steal(mem_ctx, res); + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +char * +sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx, + struct sss_ssh_pubkey *pubkey) +{ + size_t c = 0; + uint32_t algo_len; + char *algo; + + SAFEALIGN_COPY_UINT32(&algo_len, pubkey->data, &c); + algo_len = ntohl(algo_len); + + algo = talloc_zero_array(mem_ctx, char, algo_len+1); + if (!algo) { + return NULL; + } + + memcpy(algo, pubkey->data+c, algo_len); + + return algo; +} + +char * +sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx, + struct sss_ssh_ent *ent, + struct sss_ssh_pubkey *pubkey, + enum sss_ssh_pubkey_format format) +{ + TALLOC_CTX *tmp_ctx; + char *blob; + char *algo; + char *result = NULL; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return NULL; + } + + blob = sss_base64_encode(tmp_ctx, pubkey->data, pubkey->data_len); + if (!blob) { + goto done; + } + + switch (format) { + case SSS_SSH_FORMAT_RAW: + /* base64-encoded key blob */ + result = talloc_steal(mem_ctx, blob); + + case SSS_SSH_FORMAT_OPENSSH: + /* OpenSSH authorized_keys/known_hosts format */ + algo = sss_ssh_get_pubkey_algorithm(tmp_ctx, pubkey); + if (!algo) { + goto done; + } + + result = talloc_asprintf(mem_ctx, "%s %s %s", algo, blob, ent->name); + } + +done: + talloc_free(tmp_ctx); + + return result; +} diff --git a/src/util/sss_ssh.h b/src/util/sss_ssh.h new file mode 100644 index 00000000..a4ac7391 --- /dev/null +++ b/src/util/sss_ssh.h @@ -0,0 +1,59 @@ +/* + Authors: + Jan Cholasta + + Copyright (C) 2012 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SSS_SSH_H_ +#define _SSS_SSH_H_ + +struct sss_ssh_pubkey { + uint8_t *data; + size_t data_len; +}; + +struct sss_ssh_ent { + char *name; + + struct sss_ssh_pubkey *pubkeys; + size_t num_pubkeys; + + char **aliases; + size_t num_aliases; +}; + +errno_t +sss_ssh_make_ent(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + struct sss_ssh_ent **result); + +char * +sss_ssh_get_pubkey_algorithm(TALLOC_CTX *mem_ctx, + struct sss_ssh_pubkey *pubkey); + +enum sss_ssh_pubkey_format { + SSS_SSH_FORMAT_RAW, + SSS_SSH_FORMAT_OPENSSH +}; + +char * +sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx, + struct sss_ssh_ent *ent, + struct sss_ssh_pubkey *pubkey, + enum sss_ssh_pubkey_format format); + +#endif /* _SSS_SSH_H_ */ -- cgit