Diff
14 commits, 25 files changed
+377 -177

file modified
+11 -33
@@ -12,6 +12,10 @@

  

  If you want to build them from source download the latest samba master branch.

  

+ Additionally the ding-libs are needed. These used to be included in the sssd

+ release but are now a separate project. The lastest ding-libs release can be

+ downloaded from https://fedorahosted.org/sssd/wiki/Releases#DING-LIBSReleases .

+ 

  To install all of the dependencies in Fedora before building sssd:

  yum install openldap-devel gettext libtool pcre-devel c-ares-devel \

      dbus-devel libxslt-devel docbook-style-xsl krb5-devel \
@@ -19,9 +23,12 @@

      libtevent-devel libtdb libtdb-devel libtalloc libtalloc-devel \

      libldb libldb-devel cvs popt-devel c-ares-devel

  

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- How to build everything in one go (Preferred approach)

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ ding-libs are available in Fedora 14 and later version:

+ yum install  libcollection-devel  libdhash-devel  libini_config-devel \

+      libpath_utils-devel  libref_array-devel

+ 

+ How to build:

+ ~~~~~~~~~~~~~

  From the root of the source, run:

  autoreconf -i -f && \

  ./configure && \
@@ -33,35 +40,6 @@

  ../configure && \

  make

  

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- How to build components individually

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- 

- Internal Library Requirements

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- sssd provides several required libraries within its source tree:

- collection

- ini_config

- dhash

- refarray

- path_utils

- 

- Compiling sssd internal libraries

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- pushd common;

- autoreconf -i -f && \

- ./configure --disable-static --enable-shared && \

- make;

- popd

- 

- Compiling sssd with system installed libraries

- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- pushd src; \

- autoreconf -i -f && \

- ./configure && \

- make; \

- popd

- 

  Now you have to copy libnss_sss* into /lib (or /lib64) and add the 'sss' target

  to nsswitch.conf passwd database

  
@@ -79,4 +57,4 @@

  ./pam_test_client [auth|chau|acct|setc|open|clos] username@domain

  

  ~~~~~

- Simo and Steve (Last updated for 1.1.0)

+ Simo and Steve (Last updated for 1.4.1)

file modified
+2
@@ -635,6 +635,7 @@

  find_uid_tests_SOURCES = \

      src/tests/find_uid-tests.c \

      src/util/find_uid.c \

+     src/util/strtonum.c \

      $(SSSD_DEBUG_OBJ)

  find_uid_tests_CFLAGS = \

      $(AM_CFLAGS) \
@@ -795,6 +796,7 @@

      src/providers/proxy/proxy_common.c \

      src/providers/proxy/proxy_init.c \

      src/providers/proxy/proxy_id.c \

+     src/providers/proxy/proxy_netgroup.c \

      src/providers/proxy/proxy_auth.c

  libsss_proxy_la_CFLAGS = \

      $(AM_CFLAGS)

file modified
+3 -5
@@ -6,7 +6,7 @@

  "Project-Id-Version: pl\n"

  "Report-Msgid-Bugs-To: sssd-devel@lists.fedorahosted.org\n"

  "POT-Creation-Date: 2010-10-18 13:14-0400\n"

- "PO-Revision-Date: 2010-07-15 16:47+0200\n"

+ "PO-Revision-Date: 2010-10-19 06:19+0200\n"

  "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"

  "Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"

  "Language: pl\n"
@@ -608,9 +608,8 @@

  

  #: src/tools/sss_useradd.c:84 src/tools/sss_groupmod.c:76

  #: src/tools/sss_usermod.c:85

- #, fuzzy

  msgid "Specify group to add to\n"

- msgstr "Proszę podać grupę do dodania\n"

+ msgstr "Proszę podać grupę, do której dodać\n"

  

  #: src/tools/sss_useradd.c:108

  msgid "Specify user to add\n"
@@ -753,9 +752,8 @@

  msgstr "Grupy, z których usunąć tę grupę"

  

  #: src/tools/sss_groupmod.c:84 src/tools/sss_usermod.c:93

- #, fuzzy

  msgid "Specify group to remove from\n"

- msgstr "Proszę podać grupę do zmodyfikowania\n"

+ msgstr "Proszę podać grupę, z której usunąć\n"

  

  #: src/tools/sss_groupmod.c:98

  msgid "Specify group to modify\n"

file modified
+7 -7
@@ -20,6 +20,7 @@

  */

  

  #include "util/util.h"

+ #include "util/strtonum.h"

  #include "db/sysdb_private.h"

  #include "confdb/confdb.h"

  #include <time.h>
@@ -171,13 +172,13 @@

      return EOK;

  }

  

- int sysdb_attrs_get_ulong(struct sysdb_attrs *attrs, const char *name,

-                           unsigned long *value)

+ int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,

+                              uint32_t *value)

  {

      struct ldb_message_element *el;

      int ret;

      char *endptr;

-     unsigned long val;

+     uint32_t val;

  

      ret = sysdb_attrs_get_el_int(attrs, name, false, &el);

      if (ret) {
@@ -189,10 +190,9 @@

      }

  

      errno = 0;

-     val = strtoul((const char *) el->values[0].data, &endptr, 0);

-     if (errno || *endptr) {

-         return EINVAL;

-     }

+     val = strtouint32((const char *) el->values[0].data, &endptr, 0);

+     if (errno != 0) return errno;

+     if (*endptr) return EINVAL;

  

      *value = val;

      return EOK;

file modified
+2 -2
@@ -196,8 +196,8 @@

                             const char **string);

  int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name,

                                   TALLOC_CTX *mem_ctx, const char ***string);

- int sysdb_attrs_get_ulong(struct sysdb_attrs *attrs, const char *name,

-                           unsigned long *value);

+ int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,

+                              uint32_t *value);

  

  int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,

                                   const char *newname);

@@ -803,7 +803,7 @@

      kr->kpasswd_srv = NULL;

      subreq = be_resolve_server_send(state, state->ev, state->be_ctx,

                                      krb5_ctx->service->name);

-     if (req == NULL) {

+     if (subreq == NULL) {

          DEBUG(1, ("be_resolve_server_send failed.\n"));

          ret = ENOMEM;

          goto done;
@@ -844,7 +844,7 @@

              kr->krb5_ctx->kpasswd_service != NULL) {

              subreq = be_resolve_server_send(state, state->ev, state->be_ctx,

                                              kr->krb5_ctx->kpasswd_service->name);

-             if (req == NULL) {

+             if (subreq == NULL) {

                  DEBUG(1, ("be_resolve_server_send failed.\n"));

                  ret = ENOMEM;

                  goto failed;
@@ -870,7 +870,7 @@

      int ret;

  

      ret = be_resolve_server_recv(subreq, &state->kr->kpasswd_srv);

-     talloc_zfree(req);

+     talloc_zfree(subreq);

      if (ret) {

          /* all kpasswd servers have been tried and none was found good, but the

           * kdc seems ok. Password changes are not possible but

file modified
+5 -6
@@ -27,6 +27,7 @@

  #include <sys/time.h>

  

  #include "util/util.h"

+ #include "util/strtonum.h"

  #include "db/sysdb.h"

  #include "providers/ldap/ldap_common.h"

  #include "providers/ldap/sdap_async.h"
@@ -219,10 +220,9 @@

              break;

  

          case BE_FILTER_IDNUM:

-             errno = 0;

-             uid = (uid_t) strtoul(state->name, &endptr, 0);

+             uid = (uid_t) strtouint32(state->name, &endptr, 0);

              if (errno || *endptr || (state->name == endptr)) {

-                 tevent_req_error(req, errno);

+                 tevent_req_error(req, errno ? errno : EINVAL);

                  return;

              }

  
@@ -445,10 +445,9 @@

              break;

  

          case BE_FILTER_IDNUM:

-             errno = 0;

-             gid = (gid_t) strtoul(state->name, &endptr, 0);

+             gid = (gid_t) strtouint32(state->name, &endptr, 0);

              if (errno || *endptr || (state->name == endptr)) {

-                 tevent_req_error(req, errno);

+                 tevent_req_error(req, errno ? errno : EINVAL);

                  return;

              }

  

@@ -43,7 +43,6 @@

      const char *gecos;

      const char *homedir;

      const char *shell;

-     unsigned long l;

      uid_t uid;

      gid_t gid;

      struct sysdb_attrs *user_attrs;
@@ -90,16 +89,15 @@

      if (el->num_values == 0) shell = NULL;

      else shell = (const char *)el->values[0].data;

  

-     ret = sysdb_attrs_get_ulong(attrs,

-                                 opts->user_map[SDAP_AT_USER_UID].sys_name,

-                                 &l);

+     ret = sysdb_attrs_get_uint32_t(attrs,

+                                    opts->user_map[SDAP_AT_USER_UID].sys_name,

+                                    &uid);

      if (ret != EOK) {

          DEBUG(1, ("no uid provided for [%s] in domain [%s].\n",

                    name, dom->name));

          ret = EINVAL;

          goto fail;

      }

-     uid = l;

  

      /* check that the uid is valid for this domain */

      if (OUT_OF_ID_RANGE(uid, dom->id_min, dom->id_max)) {
@@ -109,16 +107,15 @@

          goto fail;

      }

  

-     ret = sysdb_attrs_get_ulong(attrs,

-                                 opts->user_map[SDAP_AT_USER_GID].sys_name,

-                                 &l);

+     ret = sysdb_attrs_get_uint32_t(attrs,

+                                    opts->user_map[SDAP_AT_USER_GID].sys_name,

+                                    &gid);

      if (ret != EOK) {

          DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",

                    name, dom->name));

          ret = EINVAL;

          goto fail;

      }

-     gid = l;

  

      /* check that the gid is valid for this domain */

      if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
@@ -609,7 +606,6 @@

      struct ldb_message_element *el;

      struct sysdb_attrs *group_attrs;

      const char *name = NULL;

-     unsigned long l;

      gid_t gid;

      int ret;

      char *timestamp = NULL;
@@ -623,16 +619,15 @@

      }

      name = (const char *)el->values[0].data;

  

-     ret = sysdb_attrs_get_ulong(attrs,

-                                 opts->group_map[SDAP_AT_GROUP_GID].sys_name,

-                                 &l);

+     ret = sysdb_attrs_get_uint32_t(attrs,

+                                    opts->group_map[SDAP_AT_GROUP_GID].sys_name,

+                                    &gid);

      if (ret != EOK) {

          DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",

                    name, dom->name));

          ret = EINVAL;

          goto fail;

      }

-     gid = l;

  

      /* check that the gid is valid for this domain */

      if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) {
@@ -1792,9 +1787,9 @@

              }

  

              if (strcmp(name, missing[i]) == 0) {

-                 ret = sysdb_attrs_get_ulong(ldap_groups[ai],

-                                             SYSDB_GIDNUM,

-                                             (unsigned long *) &gid);

+                 ret = sysdb_attrs_get_uint32_t(ldap_groups[ai],

+                                                SYSDB_GIDNUM,

+                                                &gid);

                  if (ret) {

                      DEBUG(1, ("The GID attribute is missing or malformed\n"));

                      goto fail;

@@ -603,7 +603,7 @@

  

      subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,

                                     dp_opt_get_string(state->opts->basic,

-                                                      SDAP_SEARCH_BASE),

+                                                      SDAP_NETGROUP_SEARCH_BASE),

                                     LDAP_SCOPE_SUBTREE,

                                     state->filter, state->attrs,

                                     state->opts->netgroup_map,

@@ -40,6 +40,7 @@

  #include "providers/dp_backend.h"

  #include "db/sysdb.h"

  #include "proxy.h"

+ #include "sss_client/nss_compat.h"

  #include <dhash.h>

  

  struct proxy_nss_ops {
@@ -64,6 +65,11 @@

                                        long int *start, long int *size,

                                        gid_t **groups, long int limit,

                                        int *errnop);

+     enum nss_status (*setnetgrent)(const char *netgroup,

+                                    struct __netgrent *result);

+     enum nss_status (*getnetgrent_r)(struct __netgrent *result, char *buffer,

+                                      size_t buflen, int *errnop);

+     enum nss_status (*endnetgrent)(struct __netgrent *result);

  };

  

  struct authtok_conv {
@@ -132,4 +138,11 @@

  /* From proxy_auth.c */

  void proxy_pam_handler(struct be_req *req);

  

+ /* From proxy_netgroup.c */

+ errno_t get_netgroup(struct proxy_id_ctx *ctx,

+                      struct sysdb_ctx *sysdb,

+                      struct sss_domain_info *dom,

+                      const char *name);

+ 

+ 

  #endif /* __PROXY_H__ */

@@ -22,6 +22,7 @@

      along with this program.  If not, see <http://www.gnu.org/licenses/>.

  */

  

+ #include "util/strtonum.h"

  #include "providers/proxy/proxy.h"

  

  /* =Getpwnam-wrapper======================================================*/
@@ -1077,8 +1078,7 @@

                                     EINVAL, "Invalid attr type");

              } else {

                  char *endptr;

-                 errno = 0;

-                 uid = (uid_t) strtoul(ar->filter_value, &endptr, 0);

+                 uid = (uid_t) strtouint32(ar->filter_value, &endptr, 0);

                  if (errno || *endptr || (ar->filter_value == endptr)) {

                      return proxy_reply(breq, DP_ERR_FATAL,

                                         EINVAL, "Invalid attr type");
@@ -1107,8 +1107,7 @@

                                     EINVAL, "Invalid attr type");

              } else {

                  char *endptr;

-                 errno = 0;

-                 gid = (gid_t) strtoul(ar->filter_value, &endptr, 0);

+                 gid = (gid_t) strtouint32(ar->filter_value, &endptr, 0);

                  if (errno || *endptr || (ar->filter_value == endptr)) {

                      return proxy_reply(breq, DP_ERR_FATAL,

                                         EINVAL, "Invalid attr type");
@@ -1138,6 +1137,20 @@

          ret = get_initgr(breq, ctx, sysdb, domain, ar->filter_value);

          break;

  

+     case BE_REQ_NETGROUP:

+         if (ar->filter_type != BE_FILTER_NAME) {

+             return proxy_reply(breq, DP_ERR_FATAL,

+                                EINVAL, "Invalid filter type");

+         }

+         if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL ||

+             ctx->ops.endnetgrent == NULL) {

+             return proxy_reply(breq, DP_ERR_FATAL,

+                                ENODEV, "Netgroups are not supported");

+         }

+ 

+         ret = get_netgroup(ctx, sysdb, domain, ar->filter_value);

+         break;

+ 

      default: /*fail*/

          return proxy_reply(breq, DP_ERR_FATAL,

                             EINVAL, "Invalid request type");

@@ -207,6 +207,28 @@

                    "full groups enumeration!\n", libname));

      }

  

+     ctx->ops.setnetgrent = proxy_dlsym(handle, "_nss_%s_setnetgrent", libname);

+     if (!ctx->ops.setnetgrent) {

+         DEBUG(0, ("Failed to load _nss_%s_setnetgrent, error: %s. "

+                   "The library does not support netgroups.\n", libname,

+                                                                dlerror()));

+     }

+ 

+     ctx->ops.getnetgrent_r = proxy_dlsym(handle, "_nss_%s_getnetgrent_r",

+                                          libname);

+     if (!ctx->ops.getgrent_r) {

+         DEBUG(0, ("Failed to load _nss_%s_getnetgrent_r, error: %s. "

+                   "The library does not support netgroups.\n", libname,

+                                                                dlerror()));

+     }

+ 

+     ctx->ops.endnetgrent = proxy_dlsym(handle, "_nss_%s_endnetgrent", libname);

+     if (!ctx->ops.endnetgrent) {

+         DEBUG(0, ("Failed to load _nss_%s_endnetgrent, error: %s. "

+                   "The library does not support netgroups.\n", libname,

+                                                                dlerror()));

+     }

+ 

      *ops = &proxy_id_ops;

      *pvt_data = ctx;

      ret = EOK;

@@ -0,0 +1,134 @@

+ /*

+     SSSD

+ 

+     Proxy netgroup handler

+ 

+     Authors:

+ 

+         Sumit Bose <sbose@redhat.com>

+ 

+     Copyright (C) 2010 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 "providers/proxy/proxy.h"

+ #include "util/util.h"

+ 

+ #define BUFLEN  1024

+ 

+ static errno_t make_netgroup_attr(struct __netgrent netgrent,

+                                   struct sysdb_attrs *attrs)

+ {

+     int ret;

+     char *dummy;

+ 

+     if (netgrent.type == group_val) {

+         ret =sysdb_attrs_add_string(attrs, SYSDB_NETGROUP_MEMBER,

+                                     netgrent.val.group);

+         if (ret != EOK) {

+             DEBUG(1, ("sysdb_attrs_add_string failed.\n"));

+             return ret;

+         }

+     } else if (netgrent.type == triple_val) {

+         dummy = talloc_asprintf(attrs, "(%s,%s,%s)", netgrent.val.triple.host,

+                                 netgrent.val.triple.user,

+                                 netgrent.val.triple.domain);

+         if (dummy == NULL) {

+             DEBUG(1, ("talloc_asprintf failed.\n"));

+             return ENOMEM;

+         }

+ 

+         ret = sysdb_attrs_add_string(attrs, SYSDB_NETGROUP_TRIPLE, dummy);

+         if (ret != EOK) {

+             DEBUG(1, ("sysdb_attrs_add_string failed.\n"));

+             return ret;

+         }

+     } else {

+         DEBUG(1, ("Unknown netgrent entry type [%d].\n", netgrent.type));

+         return EINVAL;

+     }

+ 

+     return EOK;

+ }

+ 

+ errno_t get_netgroup(struct proxy_id_ctx *ctx,

+                      struct sysdb_ctx *sysdb,

+                      struct sss_domain_info *dom,

+                      const char *name)

+ {

+     struct __netgrent result;

+     enum nss_status status;

+     char buffer[BUFLEN];

+     int ret;

+     TALLOC_CTX *tmp_ctx;

+     struct sysdb_attrs *attrs;

+ 

+     memset(&result, 0 ,sizeof(result));

+     status = ctx->ops.setnetgrent(name, &result);

+     if (status != NSS_STATUS_SUCCESS) {

+         DEBUG(5, ("setnetgrent failed for netgroup [%s].\n", name));

+         return EIO;

+     }

+ 

+     tmp_ctx = talloc_new(NULL);

+     if (tmp_ctx == NULL) {

+         DEBUG(1, ("talloc_new failed.\n"));

+         return ENOMEM;

+     }

+ 

+     attrs = sysdb_new_attrs(tmp_ctx);

+     if (attrs == NULL) {

+         DEBUG(1, ("sysdb_new_attrs failed.\n"));

+         return ENOMEM;

+     }

+ 

+     do {

+         status = ctx->ops.getnetgrent_r(&result, buffer, BUFLEN, &ret);

+         if (status != NSS_STATUS_SUCCESS && status != NSS_STATUS_RETURN) {

+             DEBUG(1, ("getnetgrent_r failed for netgroup [%s]: [%d][%s].\n",

+                       name, ret, strerror(ret)));

+             goto done;

+         }

+ 

+         if (status == NSS_STATUS_SUCCESS) {

+             ret = make_netgroup_attr(result, attrs);

+             if (ret != EOK) {

+                 DEBUG(1, ("make_netgroup_attr failed.\n"));

+                 goto done;

+             }

+         }

+     } while (status != NSS_STATUS_RETURN);

+ 

+     status = ctx->ops.endnetgrent(&result);

+     if (status != NSS_STATUS_SUCCESS) {

+         DEBUG(1, ("endnetgrent failed.\n"));

+         ret = EIO;

+         goto done;

+     }

+ 

+     ret = sysdb_add_netgroup(sysdb, dom, name, NULL, attrs,

+                              ctx->entry_cache_timeout);

+     if (ret != EOK) {

+         DEBUG(1, ("sysdb_add_netgroup failed.\n"));

+         goto done;

+     }

+ 

+     ret = EOK;

+ 

+ done:

+     talloc_free(tmp_ctx);

+ 

+     return ret;

+ }

@@ -161,6 +161,8 @@

  typedef void (*sss_dp_callback_t)(uint16_t err_maj, uint32_t err_min,

                                    const char *err_msg, void *ptr);

  

+ void handle_requests_after_reconnect(void);

+ 

  int sss_dp_send_acct_req(struct resp_ctx *rctx, TALLOC_CTX *callback_memctx,

                           sss_dp_callback_t callback, void *callback_ctx,

                           int timeout, const char *domain,

@@ -95,18 +95,37 @@

  

      cb = sdp_req->cb_list;

      while (cb) {

+         next = cb->next;

+         /* It is the responsibility of the callback to free cb */

          cb->callback(sdp_req->err_maj,

                       sdp_req->err_min,

                       sdp_req->err_msg,

                       cb->callback_ctx);

-         next = cb->next;

-         talloc_free(cb);

          cb = next;

      }

  

      return 0;

  }

  

+ static bool reconnect_handler(hash_entry_t *item, void *user_data)

+ {

+     struct sss_dp_req *sdp_req = talloc_get_type(item->value.ptr,

+                                                  struct sss_dp_req);

+ 

+     return (talloc_free(sdp_req) == EOK ? true : false);

+ }

+ 

+ void handle_requests_after_reconnect(void)

+ {

+     int ret;

+ 

+     ret = hash_iterate(dp_requests, reconnect_handler, NULL);

+     if (ret != HASH_SUCCESS) {

+         DEBUG(1, ("hash_iterate failed, "

+                   "not all request might be handled after reconnect.\n"));

+     }

+ }

+ 

  static void sdp_req_timeout(struct tevent_context *ev,

                              struct tevent_timer *te,

                              struct timeval t, void *ptr)

file modified
+5 -1
@@ -39,6 +39,7 @@

  #include "dbus/dbus.h"

  #include "sbus/sssd_dbus.h"

  #include "responder/common/responder_packet.h"

+ #include "responder/common/responder.h"

  #include "providers/data_provider.h"

  #include "monitor/monitor_interfaces.h"

  #include "sbus/sbus_client.h"
@@ -143,7 +144,10 @@

                                  DATA_PROVIDER_VERSION,

                                  "NSS");

          /* all fine */

-         if (ret == EOK) return;

+         if (ret == EOK) {

+             handle_requests_after_reconnect();

+             return;

+         }

      }

  

      /* Failed to reconnect */

@@ -1301,7 +1301,7 @@

  

      DEBUG(4, ("Requesting info for all accounts\n"));

  

-     cmdctx = talloc(cctx, struct nss_cmd_ctx);

+     cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);

      if (!cmdctx) {

          return ENOMEM;

      }
@@ -2630,7 +2630,7 @@

  

      DEBUG(4, ("Requesting info for all groups\n"));

  

-     cmdctx = talloc(cctx, struct nss_cmd_ctx);

+     cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);

      if (!cmdctx) {

          return ENOMEM;

      }

@@ -595,7 +595,7 @@

  

      DEBUG(4, ("Requesting netgroup data\n"));

  

-     cmdctx = talloc(client, struct nss_cmd_ctx);

+     cmdctx = talloc_zero(client, struct nss_cmd_ctx);

      if (!cmdctx) {

          return ENOMEM;

      }

file modified
+75 -76
@@ -33,18 +33,15 @@

  

  static void pam_reply(struct pam_auth_req *preq);

  

- static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok, uint8_t *body, size_t blen, size_t *c) {

-     uint32_t data_size;

+ static int extract_authtok(uint32_t *type, uint32_t *size, uint8_t **tok,

+                            size_t data_size, uint8_t *body, size_t blen,

+                            size_t *c) {

  

-     if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;

- 

-     memcpy(&data_size, &body[*c], sizeof(uint32_t));

-     *c += sizeof(uint32_t);

-     if (data_size < sizeof(uint32_t) || (*c)+(data_size) > blen) return EINVAL;

+     if (data_size < sizeof(uint32_t) || *c+data_size > blen ||

+         SIZE_T_OVERFLOW(*c, data_size)) return EINVAL;

      *size = data_size - sizeof(uint32_t);

  

-     memcpy(type, &body[*c], sizeof(uint32_t));

-     *c += sizeof(uint32_t);

+     SAFEALIGN_COPY_UINT32_CHECK(type, &body[*c], blen, c);

  

      *tok = body+(*c);

  
@@ -53,15 +50,11 @@

      return EOK;

  }

  

- static int extract_string(char **var, uint8_t *body, size_t blen, size_t *c) {

-     uint32_t size;

+ static int extract_string(char **var, size_t size, uint8_t *body, size_t blen,

+                           size_t *c) {

      uint8_t *str;

  

-     if (blen-(*c) < sizeof(uint32_t)+1) return EINVAL;

- 

-     memcpy(&size, &body[*c], sizeof(uint32_t));

-     *c += sizeof(uint32_t);

-     if (*c+size > blen) return EINVAL;

+     if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL;

  

      str = body+(*c);

  
@@ -74,16 +67,13 @@

      return EOK;

  }

  

- static int extract_uint32_t(uint32_t *var, uint8_t *body, size_t blen, size_t *c) {

-     uint32_t size;

- 

-     if (blen-(*c) < 2*sizeof(uint32_t)) return EINVAL;

+ static int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body,

+                             size_t blen, size_t *c) {

  

-     memcpy(&size, &body[*c], sizeof(uint32_t));

-     *c += sizeof(uint32_t);

+     if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size))

+         return EINVAL;

  

-     memcpy(var, &body[*c], sizeof(uint32_t));

-     *c += sizeof(uint32_t);

+     SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c);

  

      return EOK;

  }
@@ -108,59 +98,66 @@

  

      c = sizeof(uint32_t);

      do {

-         memcpy(&type, &body[c], sizeof(uint32_t));

-         c += sizeof(uint32_t);

-         if (c > blen) return EINVAL;

- 

-         switch(type) {

-             case SSS_PAM_ITEM_USER:

-                 ret = extract_string(&pam_user, body, blen, &c);

-                 if (ret != EOK) return ret;

- 

-                 ret = sss_parse_name(pd, snctx, pam_user,

-                                      &pd->domain, &pd->user);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_SERVICE:

-                 ret = extract_string(&pd->service, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_TTY:

-                 ret = extract_string(&pd->tty, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_RUSER:

-                 ret = extract_string(&pd->ruser, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_RHOST:

-                 ret = extract_string(&pd->rhost, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_CLI_PID:

-                 ret = extract_uint32_t(&pd->cli_pid,

-                                        body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_AUTHTOK:

-                 ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,

-                                       &pd->authtok, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_PAM_ITEM_NEWAUTHTOK:

-                 ret = extract_authtok(&pd->newauthtok_type,

-                                       &pd->newauthtok_size,

-                                       &pd->newauthtok, body, blen, &c);

-                 if (ret != EOK) return ret;

-                 break;

-             case SSS_END_OF_PAM_REQUEST:

-                 if (c != blen) return EINVAL;

-                 break;

-             default:

-                 DEBUG(1,("Ignoring unknown data type [%d].\n", type));

-                 size = ((uint32_t *)&body[c])[0];

-                 c += size+sizeof(uint32_t);

+         SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c);

+ 

+         if (type == SSS_END_OF_PAM_REQUEST) {

+             if (c != blen) return EINVAL;

+         } else {

+             SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c);

+             /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to

+              * the remaining buffer */

+             if (size > (blen - c - sizeof(uint32_t))) {

+                 DEBUG(1, ("Invalid data size.\n"));

+                 return EINVAL;

+             }

+ 

+             switch(type) {

+                 case SSS_PAM_ITEM_USER:

+                     ret = extract_string(&pam_user, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+ 

+                     ret = sss_parse_name(pd, snctx, pam_user,

+                                          &pd->domain, &pd->user);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_SERVICE:

+                     ret = extract_string(&pd->service, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_TTY:

+                     ret = extract_string(&pd->tty, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_RUSER:

+                     ret = extract_string(&pd->ruser, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_RHOST:

+                     ret = extract_string(&pd->rhost, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_CLI_PID:

+                     ret = extract_uint32_t(&pd->cli_pid, size,

+                                            body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_AUTHTOK:

+                     ret = extract_authtok(&pd->authtok_type, &pd->authtok_size,

+                                           &pd->authtok, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 case SSS_PAM_ITEM_NEWAUTHTOK:

+                     ret = extract_authtok(&pd->newauthtok_type,

+                                           &pd->newauthtok_size,

+                                           &pd->newauthtok, size, body, blen, &c);

+                     if (ret != EOK) return ret;

+                     break;

+                 default:

+                     DEBUG(1,("Ignoring unknown data type [%d].\n", type));

+                     c += size;

+             }

          }

+ 

      } while(c < blen);

  

      if (pd->user == NULL || *pd->user == '\0') return EINVAL;
@@ -231,6 +228,7 @@

  

      start += sizeof(uint32_t);

      pd->authtok_size = (int) body[start];

+     if (pd->authtok_size >= blen) return EINVAL;

  

      start += sizeof(uint32_t);

      end = start + pd->authtok_size;
@@ -250,6 +248,7 @@

  

      start += sizeof(uint32_t);

      pd->newauthtok_size = (int) body[start];

+     if (pd->newauthtok_size >= blen) return EINVAL;

  

      start += sizeof(uint32_t);

      end = start + pd->newauthtok_size;

file modified
+10 -10
@@ -38,15 +38,15 @@

  

  #define CHECK_RESULT(expected, actual) \

      do { \

-         fail_unless(result == expected, "Expected %ld, got %ld", \

-                                         expected, result); \

+         fail_unless(actual == expected, "Expected %ld, got %ld", \

+                                         expected, actual); \

      } while(0)

  

  #define CHECK_ERRNO(expected, actual) \

      do { \

-         fail_unless(error == ERANGE, "Expected errno %d[%s], got %d[%s]", \

-                                      ERANGE, strerror(ERANGE), \

-                                      error, strerror(ERANGE)); \

+         fail_unless(actual == expected, "Expected errno %d[%s], got %d[%s]", \

+                                         expected, strerror(expected), \

+                                         actual, strerror(actual)); \

      } while(0)

  

  #define CHECK_ENDPTR(expected, actual) \
@@ -146,7 +146,7 @@

  

      CHECK_ERRNO(ERANGE, error);

      CHECK_ZERO_ENDPTR(endptr);

-     CHECK_RESULT(expected, actual);

+     CHECK_RESULT(expected, result);

  }

  END_TEST

  
@@ -163,7 +163,7 @@

  

      CHECK_ERRNO(ERANGE, error);

      CHECK_ZERO_ENDPTR(endptr);

-     CHECK_RESULT(expected, actual);

+     CHECK_RESULT(expected, result);

  }

  END_TEST

  
@@ -265,14 +265,14 @@

  {

      uint32_t result;

      const char *input = "-123";

-     uint32_t expected = -123;

+     uint32_t expected = UINT32_MAX;

      char *endptr;

      errno_t error;

  

      result = strtouint32(input, &endptr, 10);

      error = errno;

  

-     EXPECT_UNSET_ERRNO(error);

+     CHECK_ERRNO(ERANGE, error);

      CHECK_ZERO_ENDPTR(endptr);

      CHECK_RESULT(expected, result);

  }
@@ -309,7 +309,7 @@

  

      CHECK_ERRNO(ERANGE, error);

      CHECK_ZERO_ENDPTR(endptr);

-     CHECK_RESULT(expected, actual);

+     CHECK_RESULT(expected, result);

  }

  END_TEST

  

file modified
+15
@@ -175,6 +175,20 @@

  }

  END_TEST

  

+ START_TEST(test_size_t_overflow)

+ {

+     fail_unless(!SIZE_T_OVERFLOW(1, 1), "unexpected overflow");

+     fail_unless(!SIZE_T_OVERFLOW(SIZE_T_MAX, 0), "unexpected overflow");

+     fail_unless(!SIZE_T_OVERFLOW(SIZE_T_MAX-10, 10), "unexpected overflow");

+     fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, 1), "overflow not detected");

+     fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, SIZE_T_MAX),

+                 "overflow not detected");

+     fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, ULLONG_MAX),

+                 "overflow not detected");

+     fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, -10), "overflow not detected");

+ }

+ END_TEST

+ 

  Suite *util_suite(void)

  {

      Suite *s = suite_create("util");
@@ -182,6 +196,7 @@

      TCase *tc_util = tcase_create("util");

  

      tcase_add_test (tc_util, test_diff_string_lists);

+     tcase_add_test (tc_util, test_size_t_overflow);

      tcase_set_timeout(tc_util, 60);

  

      suite_add_tcase (s, tc_util);

file modified
+3 -3
@@ -38,6 +38,7 @@

  

  #include "dhash.h"

  #include "util/util.h"

+ #include "util/strtonum.h"

  

  #define INITIAL_TABLE_SIZE 64

  #define PATHLEN (NAME_MAX + 14)
@@ -63,7 +64,7 @@

      char *p;

      char *e;

      char *endptr;

-     unsigned long num=0;

+     uint32_t num=0;

      errno_t error;

  

      ret = snprintf(path, PATHLEN, "/proc/%d/status", pid);
@@ -131,8 +132,7 @@

          } else {

              *e = '\0';

          }

-         errno = 0;

-         num = strtoul(p, &endptr, 10);

+         num = strtouint32(p, &endptr, 10);

          error = errno;

          if (error != 0) {

              DEBUG(1, ("strtol failed [%s].\n", strerror(error)));

file modified
+1 -1
@@ -51,7 +51,7 @@

  /* strtouint32 */

  uint32_t strtouint32(const char *nptr, char **endptr, int base)

  {

-     long long ret = 0;

+     unsigned long long ret = 0;

      errno = 0;

      ret = strtoull(nptr, endptr, base);

  

file modified
+9 -2
@@ -169,6 +169,11 @@

  #define OUT_OF_ID_RANGE(id, min, max) \

      (id == 0 || (min && (id < min)) || (max && (id > max)))

  

+ #define SIZE_T_MAX ((size_t) -1)

+ 

+ #define SIZE_T_OVERFLOW(current, add) \

+                         (((size_t)(add)) > (SIZE_T_MAX - ((size_t)(current))))

+ 

  static inline void

  safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter)

  {
@@ -202,12 +207,14 @@

      SAFEALIGN_SET_VALUE(dest, value, uint16_t, pctr)

  

  #define SAFEALIGN_COPY_UINT32_CHECK(dest, src, len, pctr) do { \

-     if ((*(pctr) + sizeof(uint32_t)) > (len)) return EINVAL; \

+     if ((*(pctr) + sizeof(uint32_t)) > (len) || \

+         SIZE_T_OVERFLOW(*(pctr), sizeof(uint32_t))) return EINVAL; \

      safealign_memcpy(dest, src, sizeof(uint32_t), pctr); \

  } while(0)

  

  #define SAFEALIGN_COPY_INT32_CHECK(dest, src, len, pctr) do { \

-     if ((*(pctr) + sizeof(int32_t)) > (len)) return EINVAL; \

+     if ((*(pctr) + sizeof(int32_t)) > (len) || \

+         SIZE_T_OVERFLOW(*(pctr), sizeof(int32_t))) return EINVAL; \

      safealign_memcpy(dest, src, sizeof(int32_t), pctr); \

  } while(0)

  

file modified
+1 -1
@@ -1,5 +1,5 @@

  # Primary version number

- m4_define([VERSION_NUMBER], [1.4.0])

+ m4_define([VERSION_NUMBER], [1.4.1])

  

  # If the PRERELEASE_VERSION_NUMBER is set, we'll append

  # it to the release tag when creating an RPM or SRPM