summaryrefslogtreecommitdiff
path: root/src/sss_client/nss_services.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sss_client/nss_services.c')
-rw-r--r--src/sss_client/nss_services.c129
1 files changed, 125 insertions, 4 deletions
diff --git a/src/sss_client/nss_services.c b/src/sss_client/nss_services.c
index e6aea58b..3f042b4a 100644
--- a/src/sss_client/nss_services.c
+++ b/src/sss_client/nss_services.c
@@ -31,6 +31,21 @@
#include <string.h>
#include "sss_cli.h"
+static struct sss_nss_getservent_data {
+ size_t len;
+ size_t ptr;
+ uint8_t *data;
+} sss_nss_getservent_data;
+
+static void sss_nss_getservent_data_clean(void) {
+
+ if (sss_nss_getservent_data.data != NULL) {
+ free(sss_nss_getservent_data.data);
+ sss_nss_getservent_data.data = NULL;
+ }
+ sss_nss_getservent_data.len = 0;
+ sss_nss_getservent_data.ptr = 0;
+}
/* GETSERVBYNAME Request
*
@@ -340,22 +355,128 @@ out:
enum nss_status
_nss_sss_setservent(void)
{
- return NSS_STATUS_UNAVAIL;
+ enum nss_status nret;
+ int errnop;
+ sss_nss_lock();
+
+ /* make sure we do not have leftovers, and release memory */
+ sss_nss_getservent_data_clean();
+
+ nret = sss_nss_make_request(SSS_NSS_SETSERVENT,
+ NULL, NULL, NULL, &errnop);
+ if (nret != NSS_STATUS_SUCCESS) {
+ errno = errnop;
+ }
+
+ sss_nss_unlock();
+ return nret;
}
+static enum nss_status internal_getservent_r(struct servent *result,
+ char *buffer, size_t buflen,
+ int *errnop);
enum nss_status
_nss_sss_getservent_r(struct servent *result,
char *buffer, size_t buflen,
int *errnop)
{
- fprintf(stderr, "getservent [%s]\n", buffer);
- return NSS_STATUS_UNAVAIL;
+ enum nss_status nret;
+
+ sss_nss_lock();
+ nret = internal_getservent_r(result, buffer, buflen, errnop);
+ sss_nss_unlock();
+
+ return nret;
+}
+
+static enum nss_status internal_getservent_r(struct servent *result,
+ char *buffer, size_t buflen,
+ int *errnop)
+{
+ struct sss_cli_req_data rd;
+ struct sss_nss_svc_rep pwrep;
+ uint8_t *repbuf;
+ size_t replen;
+ enum nss_status nret;
+ uint32_t num_entries;
+ int ret;
+
+ /* Caught once glibc passing in buffer == 0x0 */
+ if (!buffer || !buflen) return ERANGE;
+
+ /* if there are leftovers return the next one */
+ if (sss_nss_getservent_data.data != NULL &&
+ sss_nss_getservent_data.ptr < sss_nss_getservent_data.len) {
+
+ repbuf = sss_nss_getservent_data.data + sss_nss_getservent_data.ptr;
+ replen = sss_nss_getservent_data.len - sss_nss_getservent_data.ptr;
+
+ pwrep.result = result;
+ pwrep.buffer = buffer;
+ pwrep.buflen = buflen;
+
+ ret = sss_nss_getsvc_readrep(&pwrep, repbuf, &replen);
+ if (ret) {
+ *errnop = ret;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ /* advance buffer pointer */
+ sss_nss_getservent_data.ptr = sss_nss_getservent_data.len - replen;
+
+ return NSS_STATUS_SUCCESS;
+ }
+
+ /* release memory if any */
+ sss_nss_getservent_data_clean();
+
+ /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
+ num_entries = SSS_NSS_MAX_ENTRIES;
+ rd.len = sizeof(uint32_t);
+ rd.data = &num_entries;
+
+ nret = sss_nss_make_request(SSS_NSS_GETSERVENT, &rd,
+ &repbuf, &replen, errnop);
+ if (nret != NSS_STATUS_SUCCESS) {
+ return nret;
+ }
+
+ /* no results if not found */
+ if ((((uint32_t *)repbuf)[0] == 0)
+ || (replen - SVC_METADATA_COUNT == 0)) {
+ free(repbuf);
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ sss_nss_getservent_data.data = repbuf;
+ sss_nss_getservent_data.len = replen;
+
+ /* skip metadata fields */
+ sss_nss_getservent_data.ptr = SVC_METADATA_COUNT;
+
+ /* call again ourselves, this will return the first result */
+ return internal_getservent_r(result, buffer, buflen, errnop);
}
enum nss_status
_nss_sss_endservent(void)
{
- return NSS_STATUS_UNAVAIL;
+ enum nss_status nret;
+ int errnop;
+
+ sss_nss_lock();
+
+ /* make sure we do not have leftovers, and release memory */
+ sss_nss_getservent_data_clean();
+
+ nret = sss_nss_make_request(SSS_NSS_ENDSERVENT,
+ NULL, NULL, NULL, &errnop);
+ if (nret != NSS_STATUS_SUCCESS) {
+ errno = errnop;
+ }
+
+ sss_nss_unlock();
+ return nret;
}