summaryrefslogtreecommitdiff
path: root/src/sss_client
diff options
context:
space:
mode:
Diffstat (limited to 'src/sss_client')
-rw-r--r--src/sss_client/autofs/sss_autofs.c360
-rw-r--r--src/sss_client/autofs/sss_autofs.exports14
-rw-r--r--src/sss_client/autofs/sss_autofs_private.h45
-rw-r--r--src/sss_client/common.c20
-rw-r--r--src/sss_client/sss_cli.h12
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)