Blame nslcd/service.c

Packit 6bd9ab
/*
Packit 6bd9ab
   service.c - service entry lookup routines
Packit 6bd9ab
   Parts of this file were part of the nss_ldap library (as ldap-service.c)
Packit 6bd9ab
   which has been forked into the nss-pam-ldapd library.
Packit 6bd9ab
Packit 6bd9ab
   Copyright (C) 1997-2005 Luke Howard
Packit 6bd9ab
   Copyright (C) 2006 West Consulting
Packit 6bd9ab
   Copyright (C) 2006-2014 Arthur de Jong
Packit 6bd9ab
Packit 6bd9ab
   This library is free software; you can redistribute it and/or
Packit 6bd9ab
   modify it under the terms of the GNU Lesser General Public
Packit 6bd9ab
   License as published by the Free Software Foundation; either
Packit 6bd9ab
   version 2.1 of the License, or (at your option) any later version.
Packit 6bd9ab
Packit 6bd9ab
   This library is distributed in the hope that it will be useful,
Packit 6bd9ab
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6bd9ab
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6bd9ab
   Lesser General Public License for more details.
Packit 6bd9ab
Packit 6bd9ab
   You should have received a copy of the GNU Lesser General Public
Packit 6bd9ab
   License along with this library; if not, write to the Free Software
Packit 6bd9ab
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit 6bd9ab
   02110-1301 USA
Packit 6bd9ab
*/
Packit 6bd9ab
Packit 6bd9ab
#include "config.h"
Packit 6bd9ab
Packit 6bd9ab
#include <stdio.h>
Packit 6bd9ab
#include <stdlib.h>
Packit 6bd9ab
#include <string.h>
Packit 6bd9ab
#ifdef HAVE_STDINT_H
Packit 6bd9ab
#include <stdint.h>
Packit 6bd9ab
#endif /* HAVE_STDINT_H */
Packit 6bd9ab
Packit 6bd9ab
#include "common.h"
Packit 6bd9ab
#include "log.h"
Packit 6bd9ab
#include "myldap.h"
Packit 6bd9ab
#include "cfg.h"
Packit 6bd9ab
#include "attmap.h"
Packit 6bd9ab
Packit 6bd9ab
/* ( nisSchema.2.3 NAME 'ipService' SUP top STRUCTURAL
Packit 6bd9ab
 *   DESC 'Abstraction an Internet Protocol service.
Packit 6bd9ab
 *         Maps an IP port and protocol (such as tcp or udp)
Packit 6bd9ab
 *         to one or more names; the distinguished value of
Packit 6bd9ab
 *         the cn attribute denotes the service's canonical
Packit 6bd9ab
 *         name'
Packit 6bd9ab
 *   MUST ( cn $ ipServicePort $ ipServiceProtocol )
Packit 6bd9ab
 *   MAY ( description ) )
Packit 6bd9ab
 */
Packit 6bd9ab
Packit 6bd9ab
/* the search base for searches */
Packit 6bd9ab
const char *service_bases[NSS_LDAP_CONFIG_MAX_BASES] = { NULL };
Packit 6bd9ab
Packit 6bd9ab
/* the search scope for searches */
Packit 6bd9ab
int service_scope = LDAP_SCOPE_DEFAULT;
Packit 6bd9ab
Packit 6bd9ab
/* the basic search filter for searches */
Packit 6bd9ab
const char *service_filter = "(objectClass=ipService)";
Packit 6bd9ab
Packit 6bd9ab
/* the attributes to request with searches */
Packit 6bd9ab
const char *attmap_service_cn                = "cn";
Packit 6bd9ab
const char *attmap_service_ipServicePort     = "ipServicePort";
Packit 6bd9ab
const char *attmap_service_ipServiceProtocol = "ipServiceProtocol";
Packit 6bd9ab
Packit 6bd9ab
/* the attribute list to request with searches */
Packit 6bd9ab
static const char *service_attrs[4];
Packit 6bd9ab
Packit 6bd9ab
static int mkfilter_service_byname(const char *name, const char *protocol,
Packit 6bd9ab
                                   char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  char safename[BUFLEN_SAFENAME], safeprotocol[BUFLEN_SAFENAME];
Packit 6bd9ab
  /* escape attributes */
Packit 6bd9ab
  if (myldap_escape(name, safename, sizeof(safename)))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_ERR, "mkfilter_service_byname(): safename buffer too small");
Packit 6bd9ab
    return -1;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* build filter */
Packit 6bd9ab
  if (*protocol != '\0')
Packit 6bd9ab
  {
Packit 6bd9ab
    if (myldap_escape(protocol, safeprotocol, sizeof(safeprotocol)))
Packit 6bd9ab
    {
Packit 6bd9ab
      log_log(LOG_ERR, "mkfilter_service_byname(): safeprotocol buffer too small");
Packit 6bd9ab
      return -1;
Packit 6bd9ab
    }
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%s)(%s=%s))",
Packit 6bd9ab
                      service_filter, attmap_service_cn, safename,
Packit 6bd9ab
                      attmap_service_ipServiceProtocol, safeprotocol);
Packit 6bd9ab
  }
Packit 6bd9ab
  else
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%s))",
Packit 6bd9ab
                      service_filter, attmap_service_cn, safename);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static int mkfilter_service_bynumber(int number, const char *protocol,
Packit 6bd9ab
                                     char *buffer, size_t buflen)
Packit 6bd9ab
{
Packit 6bd9ab
  char safeprotocol[BUFLEN_SAFENAME];
Packit 6bd9ab
  if (*protocol != '\0')
Packit 6bd9ab
  {
Packit 6bd9ab
    if (myldap_escape(protocol, safeprotocol, sizeof(safeprotocol)))
Packit 6bd9ab
    {
Packit 6bd9ab
      log_log(LOG_ERR, "mkfilter_service_bynumber(): safeprotocol buffer too small");
Packit 6bd9ab
      return -1;
Packit 6bd9ab
    }
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%d)(%s=%s))",
Packit 6bd9ab
                      service_filter, attmap_service_ipServicePort, number,
Packit 6bd9ab
                      attmap_service_ipServiceProtocol, safeprotocol);
Packit 6bd9ab
  }
Packit 6bd9ab
  else
Packit 6bd9ab
    return mysnprintf(buffer, buflen, "(&%s(%s=%d))",
Packit 6bd9ab
                      service_filter, attmap_service_ipServicePort, number);
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
void service_init(void)
Packit 6bd9ab
{
Packit 6bd9ab
  int i;
Packit 6bd9ab
  /* set up search bases */
Packit 6bd9ab
  if (service_bases[0] == NULL)
Packit 6bd9ab
    for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++)
Packit 6bd9ab
      service_bases[i] = nslcd_cfg->bases[i];
Packit 6bd9ab
  /* set up scope */
Packit 6bd9ab
  if (service_scope == LDAP_SCOPE_DEFAULT)
Packit 6bd9ab
    service_scope = nslcd_cfg->scope;
Packit 6bd9ab
  /* set up attribute list */
Packit 6bd9ab
  service_attrs[0] = attmap_service_cn;
Packit 6bd9ab
  service_attrs[1] = attmap_service_ipServicePort;
Packit 6bd9ab
  service_attrs[2] = attmap_service_ipServiceProtocol;
Packit 6bd9ab
  service_attrs[3] = NULL;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
static int write_service(TFILE *fp, MYLDAP_ENTRY *entry,
Packit 6bd9ab
                         const char *reqname, const char *reqprotocol)
Packit 6bd9ab
{
Packit 6bd9ab
  int32_t tmpint32, tmp2int32, tmp3int32;
Packit 6bd9ab
  const char *name;
Packit 6bd9ab
  const char **aliases;
Packit 6bd9ab
  const char **ports;
Packit 6bd9ab
  const char **protocols;
Packit 6bd9ab
  char *tmp;
Packit 6bd9ab
  long port;
Packit 6bd9ab
  int i;
Packit 6bd9ab
  /* get the most canonical name */
Packit 6bd9ab
  name = myldap_get_rdn_value(entry, attmap_service_cn);
Packit 6bd9ab
  /* get the other names for the service entries */
Packit 6bd9ab
  aliases = myldap_get_values(entry, attmap_service_cn);
Packit 6bd9ab
  if ((aliases == NULL) || (aliases[0] == NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: missing",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_cn);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* if the service name is not yet found, get the first entry */
Packit 6bd9ab
  if (name == NULL)
Packit 6bd9ab
    name = aliases[0];
Packit 6bd9ab
  /* check case of returned services entry */
Packit 6bd9ab
  if ((reqname != NULL) && (STR_CMP(reqname, name) != 0))
Packit 6bd9ab
  {
Packit 6bd9ab
    for (i = 0; (aliases[i] != NULL) && (STR_CMP(reqname, aliases[i]) != 0); i++)
Packit 6bd9ab
      /* nothing */ ;
Packit 6bd9ab
    if (aliases[i] == NULL)
Packit 6bd9ab
      return 0; /* neither the name nor any of the aliases matched */
Packit 6bd9ab
  }
Packit 6bd9ab
  /* get the service number */
Packit 6bd9ab
  ports = myldap_get_values(entry, attmap_service_ipServicePort);
Packit 6bd9ab
  if ((ports == NULL) || (ports[0] == NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: missing",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_ipServicePort);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if (ports[1] != NULL)
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: multiple values",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_ipServicePort);
Packit 6bd9ab
  }
Packit 6bd9ab
  errno = 0;
Packit 6bd9ab
  port = strtol(ports[0], &tmp, 10);
Packit 6bd9ab
  if ((*(ports[0]) == '\0') || (*tmp != '\0'))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: non-numeric value",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_ipServicePort);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  else if ((errno != 0) || (port <= 0) || (port > (long)UINT16_MAX))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: out of range",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_ipServicePort);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* get protocols */
Packit 6bd9ab
  protocols = myldap_get_values(entry, attmap_service_ipServiceProtocol);
Packit 6bd9ab
  if ((protocols == NULL) || (protocols[0] == NULL))
Packit 6bd9ab
  {
Packit 6bd9ab
    log_log(LOG_WARNING, "%s: %s: missing",
Packit 6bd9ab
            myldap_get_dn(entry), attmap_service_ipServiceProtocol);
Packit 6bd9ab
    return 0;
Packit 6bd9ab
  }
Packit 6bd9ab
  /* write the entries */
Packit 6bd9ab
  for (i = 0; protocols[i] != NULL; i++)
Packit 6bd9ab
    if ((reqprotocol == NULL) || (*reqprotocol == '\0') ||
Packit 6bd9ab
        (STR_CMP(reqprotocol, protocols[i]) == 0))
Packit 6bd9ab
    {
Packit 6bd9ab
      WRITE_INT32(fp, NSLCD_RESULT_BEGIN);
Packit 6bd9ab
      WRITE_STRING(fp, name);
Packit 6bd9ab
      WRITE_STRINGLIST_EXCEPT(fp, aliases, name);
Packit 6bd9ab
      /* port number is actually a 16-bit value but we write 32 bits anyway */
Packit 6bd9ab
      WRITE_INT32(fp, port);
Packit 6bd9ab
      WRITE_STRING(fp, protocols[i]);
Packit 6bd9ab
    }
Packit 6bd9ab
  return 0;
Packit 6bd9ab
}
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  service, byname, NSLCD_ACTION_SERVICE_BYNAME,
Packit 6bd9ab
  char name[BUFLEN_NAME];
Packit 6bd9ab
  char protocol[BUFLEN_NAME];
Packit 6bd9ab
  char filter[BUFLEN_FILTER];
Packit 6bd9ab
  READ_STRING(fp, name);
Packit 6bd9ab
  READ_STRING(fp, protocol);
Packit 6bd9ab
  log_setrequest("service=\"%s\"%s%s", name,
Packit 6bd9ab
                 *protocol != '\0' ? "/" : "", protocol);,
Packit 6bd9ab
  mkfilter_service_byname(name, protocol, filter, sizeof(filter)),
Packit 6bd9ab
  write_service(fp, entry, name, protocol)
Packit 6bd9ab
)
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  service, bynumber, NSLCD_ACTION_SERVICE_BYNUMBER,
Packit 6bd9ab
  int number;
Packit 6bd9ab
  char protocol[BUFLEN_NAME];
Packit 6bd9ab
  char filter[BUFLEN_FILTER];
Packit 6bd9ab
  READ_INT32(fp, number);
Packit 6bd9ab
  READ_STRING(fp, protocol);
Packit 6bd9ab
  log_setrequest("service=%lu%s%s", (unsigned long int)number,
Packit 6bd9ab
                 *protocol != '\0' ? "/" : "", protocol);,
Packit 6bd9ab
  mkfilter_service_bynumber(number, protocol, filter, sizeof(filter)),
Packit 6bd9ab
  write_service(fp, entry, NULL, protocol)
Packit 6bd9ab
)
Packit 6bd9ab
Packit 6bd9ab
NSLCD_HANDLE(
Packit 6bd9ab
  service, all, NSLCD_ACTION_SERVICE_ALL,
Packit 6bd9ab
  const char *filter;
Packit 6bd9ab
  log_setrequest("service(all)");,
Packit 6bd9ab
  (filter = service_filter, 0),
Packit 6bd9ab
  write_service(fp, entry, NULL, NULL)
Packit 6bd9ab
)