diff options
Diffstat (limited to 'src/sss_client')
-rw-r--r-- | src/sss_client/autofs/sss_autofs.c | 360 | ||||
-rw-r--r-- | src/sss_client/autofs/sss_autofs.exports | 14 | ||||
-rw-r--r-- | src/sss_client/autofs/sss_autofs_private.h | 45 | ||||
-rw-r--r-- | src/sss_client/common.c | 20 | ||||
-rw-r--r-- | src/sss_client/sss_cli.h | 12 |
5 files changed, 451 insertions, 0 deletions
diff --git a/src/sss_client/autofs/sss_autofs.c b/src/sss_client/autofs/sss_autofs.c new file mode 100644 index 00000000..6195c0fc --- /dev/null +++ b/src/sss_client/autofs/sss_autofs.c @@ -0,0 +1,360 @@ +/* + Authors: + Jakub Hrozek <jhrozek@redhat.com> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <errno.h> +#include <stdlib.h> + +#include "sss_client/autofs/sss_autofs_private.h" +#include "sss_client/sss_cli.h" + +/* Historically, autofs map and key names were just file names */ +#define MAX_AUTOMNTMAPNAME_LEN NAME_MAX +#define MAX_AUTOMNTKEYNAME_LEN NAME_MAX + +struct automtent { + char *mapname; + size_t cursor; +}; + +errno_t +_sss_setautomntent(const char *mapname, void **context) +{ + errno_t ret; + int errnop; + struct automtent *ctx; + char *name; + size_t name_len; + struct sss_cli_req_data rd; + uint8_t *repbuf = NULL; + size_t replen; + + if (!mapname) return EINVAL; + + sss_nss_lock(); + + ret = sss_strnlen(mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len); + if (ret != 0) { + ret = EINVAL; + goto out; + } + + name = malloc(sizeof(char)*name_len + 1); + if (name == NULL) { + ret = ENOMEM; + goto out; + } + strncpy(name, mapname, name_len + 1); + + rd.data = name; + rd.len = name_len + 1; + + sss_autofs_make_request(SSS_AUTOFS_SETAUTOMNTENT, &rd, + &repbuf, &replen, &errnop); + if (errnop != 0) { + free(name); + ret = errnop; + goto out; + } + + /* no results if not found */ + if (((uint32_t *)repbuf)[0] == 0) { + free(name); + free(repbuf); + ret = ENOENT; + goto out; + } + free(repbuf); + + ctx = malloc(sizeof(struct automtent)); + if (!ctx) { + free(name); + ret = ENOMEM; + goto out; + } + + ctx->mapname = strdup(name); + if (!ctx->mapname) { + free(name); + free(ctx); + ret = ENOMEM; + goto out; + } + ctx->cursor = 0; + free(name); + + *context = ctx; + ret = 0; +out: + sss_nss_unlock(); + return ret; +} + +errno_t +_sss_getautomntent_r(char **key, char **value, void *context) +{ + int errnop; + errno_t ret; + size_t name_len; + struct sss_cli_req_data rd; + uint8_t *repbuf = NULL; + size_t replen; + struct automtent *ctx; + size_t ctr = 0; + size_t data_len = 0; + uint8_t *data; + uint32_t v; + + char *buf; + uint32_t len; + uint32_t keylen; + uint32_t vallen; + size_t rp; + + sss_nss_lock(); + + ctx = (struct automtent *) context; + if (!ctx) { + ret = EINVAL; + goto out; + } + + /* Be paranoid in case someone tries to smuggle in a huge map name */ + ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len); + if (ret != 0) { + ret = EINVAL; + goto out; + } + + data_len = sizeof(uint32_t) + /* mapname len */ + name_len + 1 + /* mapname\0 */ + sizeof(uint32_t); /* index into the map */ + + data = malloc(data_len); + if (!data) { + ret = ENOMEM; + goto out; + } + + v = name_len; + SAFEALIGN_COPY_UINT32(data, &v, &ctr); + + safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr); + + v = ctx->cursor; + SAFEALIGN_COPY_UINT32(data+ctr, &v, &ctr); + + rd.data = data; + rd.len = data_len; + + sss_autofs_make_request(SSS_AUTOFS_GETAUTOMNTENT, &rd, + &repbuf, &replen, &errnop); + free(data); + if (errnop != 0) { + ret = errnop; + goto out; + } + + /* Got reply, let's parse it */ + rp = 0; + SAFEALIGN_COPY_UINT32(&len, repbuf+rp, &rp); + if (len == 0) { + /* End of iteration */ + *key = NULL; + *value = NULL; + ret = ENOENT; + goto out; + } + + SAFEALIGN_COPY_UINT32(&keylen, repbuf+rp, &rp); + if (keylen > len-rp) { + ret = EIO; + goto out; + } + + buf = malloc(keylen); + if (!buf) { + ret = ENOMEM; + goto out; + } + + safealign_memcpy(buf, repbuf+rp, keylen, &rp); + *key = buf; + + SAFEALIGN_COPY_UINT32(&vallen, repbuf+rp, &rp); + if (vallen > len-rp) { + ret = EIO; + goto out; + } + + buf = malloc(vallen); + if (!buf) { + free(*key); + ret = ENOMEM; + goto out; + } + + safealign_memcpy(buf, repbuf+rp, vallen, &rp); + *value = buf; + + /* Advance the cursor so that we'll fetch the next map + * next time getautomntent is called */ + ctx->cursor++; + ret = 0; +out: + free(repbuf); + sss_nss_unlock(); + return ret; +} + +errno_t +_sss_getautomntbyname_r(const char *key, char **value, void *context) +{ + int errnop; + errno_t ret; + struct automtent *ctx; + size_t key_len; + size_t name_len; + size_t data_len = 0; + uint8_t *data; + uint32_t v; + size_t ctr = 0; + struct sss_cli_req_data rd; + uint8_t *repbuf = NULL; + size_t replen; + + char *buf; + uint32_t len; + uint32_t vallen; + size_t rp; + + sss_nss_lock(); + + ctx = (struct automtent *) context; + if (!ctx || !key) { + ret = EINVAL; + goto out; + } + + /* Be paranoid in case someone tries to smuggle in a huge map name */ + ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len); + if (ret != 0) { + ret = EINVAL; + goto out; + } + + ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTKEYNAME_LEN, &key_len); + if (ret != 0) { + ret = EINVAL; + goto out; + } + + + data_len = sizeof(uint32_t) + /* mapname len */ + name_len + 1 + /* mapname\0 */ + sizeof(uint32_t) + /* keyname len */ + key_len + 1; /* keyname\0 */ + + data = malloc(data_len); + if (!data) { + ret = ENOMEM; + goto out; + } + + v = name_len; + SAFEALIGN_COPY_UINT32(data, &v, &ctr); + + safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr); + + v = key_len; + SAFEALIGN_COPY_UINT32(data+ctr, &v, &ctr); + + safealign_memcpy(data+ctr, key, key_len + 1, &ctr); + + rd.data = data; + rd.len = data_len; + + sss_autofs_make_request(SSS_AUTOFS_GETAUTOMNTBYNAME, &rd, + &repbuf, &replen, &errnop); + free(data); + if (errnop != 0) { + ret = errnop; + goto out; + } + + /* Got reply, let's parse it */ + rp = 0; + SAFEALIGN_COPY_UINT32(&len, repbuf+rp, &rp); + if (len == 0) { + /* No data */ + *value = NULL; + ret = ENOENT; + goto out; + } + + SAFEALIGN_COPY_UINT32(&vallen, repbuf+rp, &rp); + if (vallen > len-rp) { + ret = EIO; + goto out; + } + + buf = malloc(vallen); + if (!buf) { + ret = ENOMEM; + goto out; + } + + safealign_memcpy(buf, repbuf+rp, vallen, &rp); + *value = buf; + + ret = 0; +out: + free(repbuf); + sss_nss_unlock(); + return ret; +} + +errno_t +_sss_endautomntent(void **context) +{ + struct automtent *fctx; + errno_t ret; + int errnop; + + if (!context) return 0; + + sss_nss_lock(); + + fctx = (struct automtent *) *context; + + free(fctx->mapname); + free(fctx); + + sss_autofs_make_request(SSS_AUTOFS_ENDAUTOMNTENT, + NULL, NULL, NULL, &errnop); + if (errnop != 0) { + ret = errnop; + goto out; + } + + ret = 0; +out: + sss_nss_unlock(); + return ret; +} diff --git a/src/sss_client/autofs/sss_autofs.exports b/src/sss_client/autofs/sss_autofs.exports new file mode 100644 index 00000000..f9ce8f5b --- /dev/null +++ b/src/sss_client/autofs/sss_autofs.exports @@ -0,0 +1,14 @@ +EXPORTED { + + # public functions + global: + _sss_setautomntent; + _sss_getautomntent_r; + _sss_getautomntbyname_r; + _sss_endautomntent; + + # everything else is local + local: + *; +}; + diff --git a/src/sss_client/autofs/sss_autofs_private.h b/src/sss_client/autofs/sss_autofs_private.h new file mode 100644 index 00000000..6459c1cc --- /dev/null +++ b/src/sss_client/autofs/sss_autofs_private.h @@ -0,0 +1,45 @@ +/* + Authors: + Jakub Hrozek <jhrozek@redhat.com> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <errno.h> +#include "util/util.h" + +/** + * Selects a map for processing. + */ +errno_t _sss_setautomntent(const char *mapname, void **context); + +/** + * Iterates through key/value pairs in the selected map. The key is usually + * the mount point, the value is mount information (server:/export) + */ +errno_t _sss_getautomntent_r(char **key, char **value, void *context); + +/** + * Returns value for a specific key + */ +errno_t +_sss_getautomntbyname_r(const char *key, char **value, void *context); + +/** + * Deselect a map, end the processing + */ +errno_t _sss_endautomntent(void **context); + diff --git a/src/sss_client/common.c b/src/sss_client/common.c index 998f7c8c..8fe8b44c 100644 --- a/src/sss_client/common.c +++ b/src/sss_client/common.c @@ -379,6 +379,8 @@ static bool sss_cli_check_version(const char *socket_name) expected_version = SSS_PAM_PROTOCOL_VERSION; } else if (strcmp(socket_name, SSS_SUDO_SOCKET_NAME) == 0) { expected_version = SSS_SUDO_PROTOCOL_VERSION; + } else if (strcmp(socket_name, SSS_AUTOFS_SOCKET_NAME) == 0) { + expected_version = SSS_AUTOFS_PROTOCOL_VERSION; } else { return false; } @@ -830,6 +832,24 @@ int sss_sudo_make_request(enum sss_cli_command cmd, return ret; } +int sss_autofs_make_request(enum sss_cli_command cmd, + struct sss_cli_req_data *rd, + uint8_t **repbuf, size_t *replen, + int *errnop) +{ + enum sss_status ret = SSS_STATUS_UNAVAIL; + + ret = sss_cli_check_socket(errnop, SSS_AUTOFS_SOCKET_NAME); + if (ret != SSS_STATUS_SUCCESS) { + return SSS_STATUS_UNAVAIL; + } + + ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop); + + return ret; +} + + const char *ssscli_err2string(int err) { const char *m; diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h index dc137dc4..15a2b1cb 100644 --- a/src/sss_client/sss_cli.h +++ b/src/sss_client/sss_cli.h @@ -45,6 +45,7 @@ typedef int errno_t; #define SSS_NSS_PROTOCOL_VERSION 1 #define SSS_PAM_PROTOCOL_VERSION 3 #define SSS_SUDO_PROTOCOL_VERSION 0 +#define SSS_AUTOFS_PROTOCOL_VERSION 1 #ifdef LOGIN_NAME_MAX #define SSS_NAME_MAX LOGIN_NAME_MAX @@ -163,6 +164,12 @@ enum sss_cli_command { SSS_SUDO_GET_SUDORULES = 0x00C1, SSS_SUDO_GET_DEFAULTS = 0x00C2, +/* autofs */ + SSS_AUTOFS_SETAUTOMNTENT = 0x00D1, + SSS_AUTOFS_GETAUTOMNTENT = 0x00D2, + SSS_AUTOFS_GETAUTOMNTBYNAME = 0x00D3, + SSS_AUTOFS_ENDAUTOMNTENT = 0x00D4, + /* PAM related calls */ SSS_PAM_AUTHENTICATE = 0x00F1, /**< see pam_sm_authenticate(3) for * details. @@ -470,6 +477,11 @@ int sss_sudo_make_request(enum sss_cli_command cmd, uint8_t **repbuf, size_t *replen, int *errnop); +int sss_autofs_make_request(enum sss_cli_command cmd, + struct sss_cli_req_data *rd, + uint8_t **repbuf, size_t *replen, + int *errnop); + #ifndef SAFEALIGN_COPY_UINT32 static inline void safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter) |