LCOV - code coverage report
Current view: top level - sss_client - nss_services.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 191 0.0 %
Date: 2016-06-29 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Authors:
       5             :         Stephen Gallagher <sgallagh@redhat.com>
       6             : 
       7             :     Copyright (C) 2012 Red Hat
       8             : 
       9             :     This program is free software; you can redistribute it and/or modify
      10             :     it under the terms of the GNU General Public License as published by
      11             :     the Free Software Foundation; either version 3 of the License, or
      12             :     (at your option) any later version.
      13             : 
      14             :     This program is distributed in the hope that it will be useful,
      15             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :     GNU General Public License for more details.
      18             : 
      19             :     You should have received a copy of the GNU General Public License
      20             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include <nss.h>
      24             : #include <netdb.h>
      25             : #include <errno.h>
      26             : #include <sys/types.h>
      27             : #include <unistd.h>
      28             : #include <stdlib.h>
      29             : #include <stdint.h>
      30             : #include <stdio.h>
      31             : #include <string.h>
      32             : #include "sss_cli.h"
      33             : 
      34             : static struct sss_nss_getservent_data {
      35             :     size_t len;
      36             :     size_t ptr;
      37             :     uint8_t *data;
      38             : } sss_nss_getservent_data;
      39             : 
      40           0 : static void sss_nss_getservent_data_clean(void) {
      41             : 
      42           0 :     if (sss_nss_getservent_data.data != NULL) {
      43           0 :         free(sss_nss_getservent_data.data);
      44           0 :         sss_nss_getservent_data.data = NULL;
      45             :     }
      46           0 :     sss_nss_getservent_data.len = 0;
      47           0 :     sss_nss_getservent_data.ptr = 0;
      48           0 : }
      49             : 
      50             : /* GETSERVBYNAME Request
      51             :  *
      52             :  * 0-X: Sequence of two, zero-terminated strings (name, protocol).
      53             :  * Protocol may be zero-length to imply "any"
      54             :  *
      55             :  * GETSERVBYPORT Request:
      56             :  * 0-3: 16-bit port number in network byte order
      57             :  * 4-15: Reserved/padding
      58             :  * 16-X: Zero-terminated string (protocol)
      59             :  * Protocol may be zero-length to imply "any"
      60             :  *
      61             :  * Replies:
      62             :  * 0-3: 32-bit unsigned number of results
      63             :  * 4-7: 32-bit unsigned (reserved/padding)
      64             :  * 7-X: Result data (blocks equal to number of results)
      65             :  *
      66             :  * Result data:
      67             :  * 0-3: 32-bit unsigned port number in network byte order
      68             :  * 4-7: 32-bit unsigned number of aliases
      69             :  * 8-X: sequence of zero-terminated strings
      70             :  *      (name, protocol, zero or more aliases)
      71             :  */
      72             : struct sss_nss_svc_rep {
      73             :     struct servent *result;
      74             :     char *buffer;
      75             :     size_t buflen;
      76             : };
      77             : 
      78             : #define SVC_METADATA_COUNT 8
      79             : 
      80             : static errno_t
      81           0 : sss_nss_getsvc_readrep(struct sss_nss_svc_rep *sr,
      82             :                        uint8_t *buf, size_t *len)
      83             : {
      84             :     errno_t ret;
      85             :     uint32_t c;
      86             :     uint32_t num_aliases;
      87             :     size_t i, l, slen, dlen, pad, ptaliases, alen;
      88             :     char *sbuf;
      89             : 
      90             :     /* Buffer must contain two 32-bit integers,
      91             :      * at least one character and null-terminator
      92             :      * for the name, and at least a null-
      93             :      * terminator for the protocol.
      94             :      */
      95           0 :     if (*len < 11) {
      96             :         /* not enough space for data, bad packet */
      97           0 :         return EBADMSG;
      98             :     }
      99             : 
     100             :     /* Get the port */
     101           0 :     SAFEALIGN_COPY_UINT32(&c, buf, NULL);
     102           0 :     sr->result->s_port = (uint16_t)c;
     103             : 
     104             :     /* Get the number of aliases */
     105           0 :     SAFEALIGN_COPY_UINT32(&num_aliases, buf + sizeof(uint32_t), NULL);
     106             : 
     107           0 :     sbuf = (char *)&buf[2 * sizeof(uint32_t)];
     108           0 :     slen = *len - (2 * sizeof(uint32_t));
     109           0 :     dlen = sr->buflen;
     110             : 
     111             :     /* Copy in the name */
     112           0 :     i = 0;
     113           0 :     sr->result->s_name = &(sr->buffer[i]);
     114             : 
     115           0 :     ret = sss_readrep_copy_string(sbuf, &i,
     116             :                                   &slen, &dlen,
     117           0 :                                   &sr->result->s_name,
     118             :                                   NULL);
     119           0 :     if (ret != EOK) return ret;
     120             : 
     121             :     /* Copy in the protocol */
     122           0 :     sr->result->s_proto = &(sr->buffer[i]);
     123             : 
     124           0 :     ret = sss_readrep_copy_string(sbuf, &i,
     125             :                                   &slen, &dlen,
     126           0 :                                   &sr->result->s_proto,
     127             :                                   NULL);
     128           0 :     if (ret != EOK) return ret;
     129             : 
     130             :     /* Make sure sr->buffer[i+pad] is aligned to sizeof(char *) */
     131           0 :     pad = PADDING_SIZE(i, char *);
     132             : 
     133             :     /* Copy in the aliases */
     134           0 :     sr->result->s_aliases = DISCARD_ALIGN(&(sr->buffer[i+pad]), char **);
     135             : 
     136           0 :     ptaliases = (sizeof(char *) * (num_aliases + 1)) + pad;
     137           0 :     if (ptaliases > dlen) {
     138           0 :         return ERANGE; /* not ENOMEM, ERANGE is what glibc looks for */
     139             :     }
     140             : 
     141           0 :     dlen -= ptaliases;
     142           0 :     ptaliases += i;
     143           0 :     sr->result->s_aliases[num_aliases] = NULL; /* terminate array */
     144             : 
     145           0 :     for (l = 0; l < num_aliases; l++) {
     146           0 :         sr->result->s_aliases[l] = &(sr->buffer[ptaliases]);
     147           0 :         ret = sss_readrep_copy_string(sbuf, &i,
     148             :                                       &slen, &dlen,
     149           0 :                                       &sr->result->s_aliases[l],
     150             :                                       &alen);
     151           0 :         if (ret != EOK) return ret;
     152             : 
     153           0 :         ptaliases += alen + 1;
     154             :     }
     155             : 
     156           0 :     *len = slen - i;
     157             : 
     158           0 :     return EOK;
     159             : }
     160             : 
     161             : enum nss_status
     162           0 : _nss_sss_getservbyname_r(const char *name,
     163             :                          const char *protocol,
     164             :                          struct servent *result,
     165             :                          char *buffer, size_t buflen,
     166             :                          int *errnop)
     167             : {
     168             :     struct sss_cli_req_data rd;
     169             :     struct sss_nss_svc_rep svcrep;
     170             :     size_t name_len;
     171           0 :     size_t proto_len = 0;
     172             :     uint8_t *repbuf;
     173             :     uint8_t *data;
     174             :     size_t replen, len;
     175             :     uint32_t num_results;
     176             :     enum nss_status nret;
     177             :     int ret;
     178             : 
     179             :     /* Caught once glibc passing in buffer == 0x0 */
     180           0 :     if (!buffer || !buflen) return ERANGE;
     181             : 
     182           0 :     ret = sss_strnlen(name, SSS_NAME_MAX, &name_len);
     183           0 :     if (ret != 0) {
     184           0 :         *errnop = EINVAL;
     185           0 :         return NSS_STATUS_NOTFOUND;
     186             :     }
     187             : 
     188           0 :     if (protocol) {
     189           0 :         ret = sss_strnlen(protocol, SSS_NAME_MAX, &proto_len);
     190           0 :         if (ret != 0) {
     191           0 :             *errnop = EINVAL;
     192           0 :             return NSS_STATUS_NOTFOUND;
     193             :         }
     194             :     }
     195             : 
     196           0 :     rd.len = name_len + proto_len + 2;
     197           0 :     data = malloc(sizeof(uint8_t)*rd.len);
     198           0 :     if (data == NULL) {
     199           0 :         nret = NSS_STATUS_TRYAGAIN;
     200           0 :         goto out;
     201             :     }
     202             : 
     203           0 :     memcpy(data, name, name_len + 1);
     204             : 
     205           0 :     if (protocol) {
     206           0 :         memcpy(data + name_len + 1, protocol, proto_len + 1);
     207             :     } else {
     208             :         /* No protocol specified, pass empty string */
     209           0 :         data[name_len + 1] = '\0';
     210             :     }
     211           0 :     rd.data = data;
     212             : 
     213           0 :     sss_nss_lock();
     214             : 
     215           0 :     nret = sss_nss_make_request(SSS_NSS_GETSERVBYNAME, &rd,
     216             :                                 &repbuf, &replen, errnop);
     217           0 :     free(data);
     218           0 :     if (nret != NSS_STATUS_SUCCESS) {
     219           0 :         goto out;
     220             :     }
     221             : 
     222           0 :     svcrep.result = result;
     223           0 :     svcrep.buffer = buffer;
     224           0 :     svcrep.buflen = buflen;
     225             : 
     226             :     /* Get number of results from repbuf. */
     227           0 :     SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
     228             : 
     229             :     /* no results if not found */
     230           0 :     if (num_results == 0) {
     231           0 :         free(repbuf);
     232           0 :         nret = NSS_STATUS_NOTFOUND;
     233           0 :         goto out;
     234             :     }
     235             : 
     236             :     /* only 1 result is accepted for this function */
     237           0 :     if (num_results != 1) {
     238           0 :         *errnop = EBADMSG;
     239           0 :         free(repbuf);
     240           0 :         nret = NSS_STATUS_TRYAGAIN;
     241           0 :         goto out;
     242             :     }
     243             : 
     244           0 :     len = replen - SVC_METADATA_COUNT;
     245           0 :     ret = sss_nss_getsvc_readrep(&svcrep,
     246             :                                  repbuf + SVC_METADATA_COUNT,
     247             :                                  &len);
     248           0 :     free(repbuf);
     249           0 :     if (ret) {
     250           0 :         *errnop = ret;
     251           0 :         nret = NSS_STATUS_TRYAGAIN;
     252           0 :         goto out;
     253             :     }
     254             : 
     255           0 :     nret = NSS_STATUS_SUCCESS;
     256             : 
     257             : out:
     258           0 :     sss_nss_unlock();
     259           0 :     return nret;
     260             : }
     261             : 
     262             : 
     263             : enum nss_status
     264           0 : _nss_sss_getservbyport_r(int port, const char *protocol,
     265             :                          struct servent *result,
     266             :                          char *buffer, size_t buflen,
     267             :                          int *errnop)
     268             : {
     269             :     struct sss_cli_req_data rd;
     270             :     struct sss_nss_svc_rep svcrep;
     271           0 :     size_t proto_len = 0;
     272             :     uint8_t *repbuf;
     273             :     uint8_t *data;
     274           0 :     size_t p = 0;
     275             :     size_t replen, len;
     276             :     uint32_t num_results;
     277             :     enum nss_status nret;
     278             :     int ret;
     279             : 
     280             :     /* Caught once glibc passing in buffer == 0x0 */
     281           0 :     if (!buffer || !buflen) return ERANGE;
     282             : 
     283           0 :     if (protocol) {
     284           0 :         ret = sss_strnlen(protocol, SSS_NAME_MAX, &proto_len);
     285           0 :         if (ret != 0) {
     286           0 :             *errnop = EINVAL;
     287           0 :             return NSS_STATUS_NOTFOUND;
     288             :         }
     289             :     }
     290             : 
     291           0 :     rd.len = sizeof(uint32_t)*2 + proto_len + 1;
     292           0 :     data = malloc(sizeof(uint8_t)*rd.len);
     293           0 :     if (data == NULL) {
     294           0 :         nret = NSS_STATUS_TRYAGAIN;
     295           0 :         goto out;
     296             :     }
     297             : 
     298           0 :     SAFEALIGN_SET_UINT16(data, port, &p);
     299             : 
     300             :     /* Padding */
     301           0 :     SAFEALIGN_SET_UINT16(data + p, 0, &p);
     302           0 :     SAFEALIGN_SET_UINT32(data + p, 0, &p);
     303             : 
     304           0 :     if (protocol) {
     305           0 :         memcpy(data + p, protocol, proto_len + 1);
     306             :     } else {
     307             :         /* No protocol specified, pass empty string */
     308           0 :         data[p] = '\0';
     309             :     }
     310           0 :     rd.data = data;
     311             : 
     312           0 :     sss_nss_lock();
     313             : 
     314           0 :     nret = sss_nss_make_request(SSS_NSS_GETSERVBYPORT, &rd,
     315             :                                 &repbuf, &replen, errnop);
     316           0 :     free(data);
     317           0 :     if (nret != NSS_STATUS_SUCCESS) {
     318           0 :         goto out;
     319             :     }
     320             : 
     321           0 :     svcrep.result = result;
     322           0 :     svcrep.buffer = buffer;
     323           0 :     svcrep.buflen = buflen;
     324             : 
     325             :     /* Get number of results from repbuf. */
     326           0 :     SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
     327             : 
     328             :     /* no results if not found */
     329           0 :     if (num_results == 0) {
     330           0 :         free(repbuf);
     331           0 :         nret = NSS_STATUS_NOTFOUND;
     332           0 :         goto out;
     333             :     }
     334             : 
     335             :     /* only 1 result is accepted for this function */
     336           0 :     if (num_results != 1) {
     337           0 :         *errnop = EBADMSG;
     338           0 :         free(repbuf);
     339           0 :         nret = NSS_STATUS_TRYAGAIN;
     340           0 :         goto out;
     341             :     }
     342             : 
     343           0 :     len = replen - SVC_METADATA_COUNT;
     344           0 :     ret = sss_nss_getsvc_readrep(&svcrep,
     345             :                                  repbuf + SVC_METADATA_COUNT,
     346             :                                  &len);
     347           0 :     free(repbuf);
     348           0 :     if (ret) {
     349           0 :         *errnop = ret;
     350           0 :         nret = NSS_STATUS_TRYAGAIN;
     351           0 :         goto out;
     352             :     }
     353             : 
     354           0 :     nret = NSS_STATUS_SUCCESS;
     355             : 
     356             : out:
     357           0 :     sss_nss_unlock();
     358           0 :     return nret;
     359             : }
     360             : 
     361             : 
     362             : enum nss_status
     363           0 : _nss_sss_setservent(void)
     364             : {
     365             :     enum nss_status nret;
     366             :     int errnop;
     367           0 :     sss_nss_lock();
     368             : 
     369             :     /* make sure we do not have leftovers, and release memory */
     370           0 :     sss_nss_getservent_data_clean();
     371             : 
     372           0 :     nret = sss_nss_make_request(SSS_NSS_SETSERVENT,
     373             :                                 NULL, NULL, NULL, &errnop);
     374           0 :     if (nret != NSS_STATUS_SUCCESS) {
     375           0 :         errno = errnop;
     376             :     }
     377             : 
     378           0 :     sss_nss_unlock();
     379           0 :     return nret;
     380             : }
     381             : 
     382             : static enum nss_status internal_getservent_r(struct servent *result,
     383             :                                              char *buffer, size_t buflen,
     384             :                                              int *errnop);
     385             : 
     386             : enum nss_status
     387           0 : _nss_sss_getservent_r(struct servent *result,
     388             :                       char *buffer, size_t buflen,
     389             :                       int *errnop)
     390             : {
     391             :     enum nss_status nret;
     392             : 
     393           0 :     sss_nss_lock();
     394           0 :     nret = internal_getservent_r(result, buffer, buflen, errnop);
     395           0 :     sss_nss_unlock();
     396             : 
     397           0 :     return nret;
     398             : }
     399             : 
     400           0 : static enum nss_status internal_getservent_r(struct servent *result,
     401             :                                              char *buffer, size_t buflen,
     402             :                                              int *errnop)
     403             : {
     404             :     struct sss_cli_req_data rd;
     405             :     struct sss_nss_svc_rep pwrep;
     406             :     uint8_t *repbuf;
     407             :     size_t replen;
     408             :     uint32_t num_results;
     409             :     enum nss_status nret;
     410             :     uint32_t num_entries;
     411             :     int ret;
     412             : 
     413             :     /* Caught once glibc passing in buffer == 0x0 */
     414           0 :     if (!buffer || !buflen) return ERANGE;
     415             : 
     416             :     /* if there are leftovers return the next one */
     417           0 :     if (sss_nss_getservent_data.data != NULL &&
     418           0 :         sss_nss_getservent_data.ptr < sss_nss_getservent_data.len) {
     419             : 
     420           0 :         repbuf = sss_nss_getservent_data.data + sss_nss_getservent_data.ptr;
     421           0 :         replen = sss_nss_getservent_data.len - sss_nss_getservent_data.ptr;
     422             : 
     423           0 :         pwrep.result = result;
     424           0 :         pwrep.buffer = buffer;
     425           0 :         pwrep.buflen = buflen;
     426             : 
     427           0 :         ret = sss_nss_getsvc_readrep(&pwrep, repbuf, &replen);
     428           0 :         if (ret) {
     429           0 :             *errnop = ret;
     430           0 :             return NSS_STATUS_TRYAGAIN;
     431             :         }
     432             : 
     433             :         /* advance buffer pointer */
     434           0 :         sss_nss_getservent_data.ptr = sss_nss_getservent_data.len - replen;
     435             : 
     436           0 :         return NSS_STATUS_SUCCESS;
     437             :     }
     438             : 
     439             :     /* release memory if any */
     440           0 :     sss_nss_getservent_data_clean();
     441             : 
     442             :     /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
     443           0 :     num_entries = SSS_NSS_MAX_ENTRIES;
     444           0 :     rd.len = sizeof(uint32_t);
     445           0 :     rd.data = &num_entries;
     446             : 
     447           0 :     nret = sss_nss_make_request(SSS_NSS_GETSERVENT, &rd,
     448             :                                 &repbuf, &replen, errnop);
     449           0 :     if (nret != NSS_STATUS_SUCCESS) {
     450           0 :         return nret;
     451             :     }
     452             : 
     453             :     /* Get number of results from repbuf */
     454           0 :     SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
     455             : 
     456             :     /* no results if not found */
     457           0 :     if ((num_results == 0) || (replen - SVC_METADATA_COUNT == 0)) {
     458           0 :         free(repbuf);
     459           0 :         return NSS_STATUS_NOTFOUND;
     460             :     }
     461             : 
     462           0 :     sss_nss_getservent_data.data = repbuf;
     463           0 :     sss_nss_getservent_data.len = replen;
     464             : 
     465             :     /* skip metadata fields */
     466           0 :     sss_nss_getservent_data.ptr = SVC_METADATA_COUNT;
     467             : 
     468             :     /* call again ourselves, this will return the first result */
     469           0 :     return internal_getservent_r(result, buffer, buflen, errnop);
     470             : }
     471             : 
     472             : 
     473             : enum nss_status
     474           0 : _nss_sss_endservent(void)
     475             : {
     476             :     enum nss_status nret;
     477             :     int errnop;
     478             : 
     479           0 :     sss_nss_lock();
     480             : 
     481             :     /* make sure we do not have leftovers, and release memory */
     482           0 :     sss_nss_getservent_data_clean();
     483             : 
     484           0 :     nret = sss_nss_make_request(SSS_NSS_ENDSERVENT,
     485             :                                 NULL, NULL, NULL, &errnop);
     486           0 :     if (nret != NSS_STATUS_SUCCESS) {
     487           0 :         errno = errnop;
     488             :     }
     489             : 
     490           0 :     sss_nss_unlock();
     491           0 :     return nret;
     492             : }

Generated by: LCOV version 1.10