/*
Authors:
Pavel Březina <pbrezina@redhat.com>
Copyright (C) 2016 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 "db/sysdb.h"
#include "db/sysdb_services.h"
#include "responder/nss/nss_protocol.h"
static errno_t
nss_protocol_fill_netgr_triple(struct sss_packet *packet,
struct sysdb_netgroup_ctx *entry,
size_t *_rp)
{
struct sized_string host;
struct sized_string user;
struct sized_string domain;
size_t body_len;
uint8_t *body;
errno_t ret;
to_sized_string(&host, entry->value.triple.hostname);
to_sized_string(&user, entry->value.triple.username);
to_sized_string(&domain, entry->value.triple.domainname);
if (host.len == 0) {
host.len = 1;
host.str = "";
}
if (user.len == 0) {
user.len = 1;
user.str = "";
}
if (domain.len == 0) {
domain.len = 1;
domain.str = "";
}
ret = sss_packet_grow(packet, sizeof(uint32_t)
+ host.len + user.len + domain.len);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to grow packet!\n");
return ret;
}
sss_packet_get_body(packet, &body, &body_len);
SAFEALIGN_SET_UINT32(&body[*_rp], SSS_NETGR_REP_TRIPLE, _rp);
SAFEALIGN_SET_STRING(&body[*_rp], host.str, host.len, _rp);
SAFEALIGN_SET_STRING(&body[*_rp], user.str, user.len, _rp);
SAFEALIGN_SET_STRING(&body[*_rp], domain.str, domain.len, _rp);
return EOK;
}
static errno_t
nss_protocol_fill_netgr_member(struct sss_packet *packet,
struct sysdb_netgroup_ctx *entry,
size_t *_rp)
{
struct sized_string group;
size_t body_len;
uint8_t *body;
errno_t ret;
if (entry->value.groupname == NULL || entry->value.groupname[0] == '\0') {
DEBUG(SSSDBG_CRIT_FAILURE, "Empty netgroup member!\n");
return EINVAL;
}
to_sized_string(&group, entry->value.groupname);
ret = sss_packet_grow(packet, sizeof(uint32_t) + group.len);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to grow packet!\n");
return ret;
}
sss_packet_get_body(packet, &body, &body_len);
SAFEALIGN_SET_UINT32(&body[*_rp], SSS_NETGR_REP_GROUP, _rp);
SAFEALIGN_SET_STRING(&body[*_rp], group.str, group.len, _rp);
return EOK;
}
errno_t
nss_protocol_fill_netgrent(struct nss_ctx *nss_ctx,
struct nss_cmd_ctx *cmd_ctx,
struct sss_packet *packet,
struct cache_req_result *result)
{
struct sysdb_netgroup_ctx **entries;
struct sysdb_netgroup_ctx *entry;
struct nss_enum_index *idx;
uint32_t num_results;
size_t rp;
size_t body_len;
uint8_t *body;
errno_t ret;
unsigned int start;
idx = cmd_ctx->enum_index;
entries = cmd_ctx->enum_ctx->netgroup;
if (idx->result > cmd_ctx->enum_ctx->netgroup_count) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unconsistent state while processing netgroups.\n");
ret = EINVAL;
goto done;
}
/* First two fields (length and reserved), filled up later. */
ret = sss_packet_grow(packet, 2 * sizeof(uint32_t));
if (ret != EOK) {
return ret;
}
rp = 2 * sizeof(uint32_t);
if (entries == NULL) {
num_results = 0;
ret = EOK;
goto done;
}
num_results = 0;
start = idx->result;
for (; entries[idx->result] != NULL; idx->result++) {
if ((idx->result - start) >= cmd_ctx->enum_limit) {
/* We have reached result limit. */
break;
}
entry = entries[idx->result];
switch (entry->type) {
case SYSDB_NETGROUP_TRIPLE_VAL:
ret = nss_protocol_fill_netgr_triple(packet, entry, &rp);
break;
case SYSDB_NETGROUP_GROUP_VAL:
ret = nss_protocol_fill_netgr_member(packet, entry, &rp);
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected value type!\n");
ret = ERR_INTERNAL;
break;
}
if (ret != EOK) {
goto done;
}
num_results++;
}
ret = EOK;
done:
if (ret != EOK) {
sss_packet_set_size(packet, 0);
return ret;
}
sss_packet_get_body(packet, &body, &body_len);
SAFEALIGN_COPY_UINT32(body, &num_results, NULL);
SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL); /* reserved */
return EOK;
}
errno_t
nss_protocol_fill_setnetgrent(struct nss_ctx *nss_ctx,
struct nss_cmd_ctx *cmd_ctx,
struct sss_packet *packet,
struct cache_req_result *result)
{
size_t body_len;
uint8_t *body;
errno_t ret;
/* Two fields (length and reserved). */
ret = sss_packet_grow(packet, 2 * sizeof(uint32_t));
if (ret != EOK) {
return ret;
}
sss_packet_get_body(packet, &body, &body_len);
SAFEALIGN_SET_UINT32(body, 1, NULL); /* Netgroup was found. */
SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL); /* reserved */
return EOK;
}