Diff for /embedaddon/sudo/plugins/sudoers/sssd.c between versions 1.1.1.1 and 1.1.1.4

version 1.1.1.1, 2012/10/09 09:29:52 version 1.1.1.4, 2014/06/15 16:12:54
Line 1 Line 1
 /*  /*
 * Copyright (c) 2003-2012 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2003-2013 Todd C. Miller <Todd.Miller@courtesan.com>
  * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>   * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
  *   *
  * This code is derived from software contributed by Aaron Spangler.   * This code is derived from software contributed by Aaron Spangler.
Line 21 Line 21
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/time.h>  #include <sys/time.h>
 #include <sys/param.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <stdio.h>  #include <stdio.h>
 #ifdef STDC_HEADERS  #ifdef STDC_HEADERS
Line 41 Line 40
 #ifdef HAVE_UNISTD_H  #ifdef HAVE_UNISTD_H
 # include <unistd.h>  # include <unistd.h>
 #endif /* HAVE_UNISTD_H */  #endif /* HAVE_UNISTD_H */
#if TIME_WITH_SYS_TIME#ifdef TIME_WITH_SYS_TIME
 # include <time.h>  # include <time.h>
 #endif  #endif
 #ifdef HAVE_DLOPEN  
 # include <dlfcn.h>  
 #else  
 # include "compat/dlfcn.h"  
 #endif  
 #include <ctype.h>  #include <ctype.h>
 #include <pwd.h>  #include <pwd.h>
 #include <grp.h>  #include <grp.h>
Line 59 Line 53
 #include "sudoers.h"  #include "sudoers.h"
 #include "parse.h"  #include "parse.h"
 #include "lbuf.h"  #include "lbuf.h"
   #include "sudo_dso.h"
 #include "sudo_debug.h"  #include "sudo_debug.h"
   
 /* SSSD <--> SUDO interface - do not change */  /* SSSD <--> SUDO interface - do not change */
Line 180  sudo_sss_filter_result(struct sudo_sss_handle *handle, Line 175  sudo_sss_filter_result(struct sudo_sss_handle *handle,
     debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD)      debug_decl(sudo_sss_filter_result, SUDO_DEBUG_SSSD)
   
     sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s",      sudo_debug_printf(SUDO_DEBUG_DEBUG, "in_res=%p, count=%u, act=%s",
        in_res, in_res->num_rules,        in_res, in_res ? in_res->num_rules : 0,
         act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE");          act == _SUDO_SSS_FILTER_EXCLUDE ? "EXCLUDE" : "INCLUDE");
   
     if (in_res == NULL)      if (in_res == NULL)
Line 212  sudo_sss_filter_result(struct sudo_sss_handle *handle, Line 207  sudo_sss_filter_result(struct sudo_sss_handle *handle,
         sudo_debug_printf(SUDO_DEBUG_DEBUG,          sudo_debug_printf(SUDO_DEBUG_DEBUG,
             "reallocating result: %p (count: %u -> %u)", out_res->rules,              "reallocating result: %p (count: %u -> %u)", out_res->rules,
             in_res->num_rules, l);              in_res->num_rules, l);
        out_res->rules = erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule));        if (l > 0) {
             out_res->rules =
                 erealloc3(out_res->rules, l, sizeof(struct sss_sudo_rule));
         } else {
             efree(out_res->rules);
             out_res->rules = NULL;
         }
     }      }
   
     out_res->num_rules = l;      out_res->num_rules = l;
Line 221  sudo_sss_filter_result(struct sudo_sss_handle *handle, Line 222  sudo_sss_filter_result(struct sudo_sss_handle *handle,
 }  }
   
 struct sudo_nss sudo_nss_sss = {  struct sudo_nss sudo_nss_sss = {
    &sudo_nss_sss,    { NULL, NULL },
    NULL, 
     sudo_sss_open,      sudo_sss_open,
     sudo_sss_close,      sudo_sss_close,
     sudo_sss_parse,      sudo_sss_parse,
Line 246  static int sudo_sss_open(struct sudo_nss *nss) Line 246  static int sudo_sss_open(struct sudo_nss *nss)
     handle = emalloc(sizeof(struct sudo_sss_handle));      handle = emalloc(sizeof(struct sudo_sss_handle));
   
     /* Load symbols */      /* Load symbols */
    handle->ssslib = dlopen(path, RTLD_LAZY);    handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
     if (handle->ssslib == NULL) {      if (handle->ssslib == NULL) {
        warningx(_("Unable to dlopen %s: %s"), path, dlerror());        warningx(U_("unable to load %s: %s"), path, sudo_dso_strerror());
        warningx(_("Unable to initialize SSS source. Is SSSD installed on your machine?"));        warningx(U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
   
    handle->fn_send_recv = dlsym(handle->ssslib, "sss_sudo_send_recv");    handle->fn_send_recv =
         sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv");
     if (handle->fn_send_recv == NULL) {      if (handle->fn_send_recv == NULL) {
        warningx(_("unable to find symbol \"%s\" in %s"), path,        warningx(U_("unable to find symbol \"%s\" in %s"), path,
            "sss_sudo_send_recv");             "sss_sudo_send_recv");
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
   
     handle->fn_send_recv_defaults =      handle->fn_send_recv_defaults =
        dlsym(handle->ssslib, "sss_sudo_send_recv_defaults");        sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults");
     if (handle->fn_send_recv_defaults == NULL) {      if (handle->fn_send_recv_defaults == NULL) {
        warningx(_("unable to find symbol \"%s\" in %s"), path,        warningx(U_("unable to find symbol \"%s\" in %s"), path,
            "sss_sudo_send_recv_defaults");             "sss_sudo_send_recv_defaults");
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
   
    handle->fn_free_result = dlsym(handle->ssslib, "sss_sudo_free_result");    handle->fn_free_result =
         sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result");
     if (handle->fn_free_result == NULL) {      if (handle->fn_free_result == NULL) {
        warningx(_("unable to find symbol \"%s\" in %s"), path,        warningx(U_("unable to find symbol \"%s\" in %s"), path,
            "sss_sudo_free_result");             "sss_sudo_free_result");
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
   
    handle->fn_get_values = dlsym(handle->ssslib, "sss_sudo_get_values");    handle->fn_get_values =
         sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values");
     if (handle->fn_get_values == NULL) {      if (handle->fn_get_values == NULL) {
        warningx(_("unable to find symbol \"%s\" in %s"), path,        warningx(U_("unable to find symbol \"%s\" in %s"), path,
            "sss_sudo_get_values");             "sss_sudo_get_values");
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
   
    handle->fn_free_values = dlsym(handle->ssslib, "sss_sudo_free_values");    handle->fn_free_values =
         sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values");
     if (handle->fn_free_values == NULL) {      if (handle->fn_free_values == NULL) {
        warningx(_("unable to find symbol \"%s\" in %s"), path,        warningx(U_("unable to find symbol \"%s\" in %s"), path,
            "sss_sudo_free_values");             "sss_sudo_free_values");
         debug_return_int(EFAULT);          debug_return_int(EFAULT);
     }      }
Line 306  static int sudo_sss_close(struct sudo_nss *nss) Line 310  static int sudo_sss_close(struct sudo_nss *nss)
   
     if (nss && nss->handle) {      if (nss && nss->handle) {
         handle = nss->handle;          handle = nss->handle;
        dlclose(handle->ssslib);        sudo_dso_unload(handle->ssslib);
         efree(nss->handle);
     }      }
   
     efree(nss->handle);  
     debug_return_int(0);      debug_return_int(0);
 }  }
   
Line 345  static int sudo_sss_setdefs(struct sudo_nss *nss) Line 348  static int sudo_sss_setdefs(struct sudo_nss *nss)
   
     if (sss_error == ENOENT) {      if (sss_error == ENOENT) {
         sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");          sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
        debug_return_int(-1);        debug_return_int(0);
     } else if(sss_error != 0) {      } else if(sss_error != 0) {
         sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);          sudo_debug_printf(SUDO_DEBUG_INFO, "sss_error=%u\n", sss_error);
         debug_return_int(-1);          debug_return_int(-1);
Line 466  sudo_sss_check_runas_user(struct sudo_sss_handle *hand Line 469  sudo_sss_check_runas_user(struct sudo_sss_handle *hand
             /* FALLTHROUGH */              /* FALLTHROUGH */
             sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH");              sudo_debug_printf(SUDO_DEBUG_DEBUG, "FALLTHROUGH");
         default:          default:
            if (strcasecmp(val, runas_pw->pw_name) == 0) {            if (userpw_matches(val, runas_pw->pw_name, runas_pw)) {
                 sudo_debug_printf(SUDO_DEBUG_DEBUG,                  sudo_debug_printf(SUDO_DEBUG_DEBUG,
                     "%s == %s (pw_name) => match", val, runas_pw->pw_name);                      "%s == %s (pw_name) => match", val, runas_pw->pw_name);
                 ret = true;                  ret = true;
Line 529  sudo_sss_check_runas_group(struct sudo_sss_handle *han Line 532  sudo_sss_check_runas_group(struct sudo_sss_handle *han
  * Walk through search results and return true if we have a runas match,   * Walk through search results and return true if we have a runas match,
  * else false.  RunAs info is optional.   * else false.  RunAs info is optional.
  */   */
static intstatic bool
 sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)  sudo_sss_check_runas(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
 {  {
    int ret;    bool ret;
     debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD);      debug_decl(sudo_sss_check_runas, SUDO_DEBUG_SSSD);
   
     if (rule == NULL)      if (rule == NULL)
         debug_return_int(false);         debug_return_bool(false);
   
     ret = sudo_sss_check_runas_user(handle, rule) != false &&      ret = sudo_sss_check_runas_user(handle, rule) != false &&
          sudo_sss_check_runas_group(handle, rule) != false;           sudo_sss_check_runas_group(handle, rule) != false;
   
    debug_return_int(ret);    debug_return_bool(ret);
 }  }
   
static intstatic bool
 sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)  sudo_sss_check_host(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
 {  {
     char **val_array, *val;      char **val_array, *val;
    int ret = false, i;    bool ret = false;
     int i;
     debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD);      debug_decl(sudo_sss_check_host, SUDO_DEBUG_SSSD);
   
     if (rule == NULL)      if (rule == NULL)
        debug_return_int(ret);        debug_return_bool(ret);
   
     /* get the values from the rule */      /* get the values from the rule */
     switch (handle->fn_get_values(rule, "sudoHost", &val_array))      switch (handle->fn_get_values(rule, "sudoHost", &val_array))
Line 561  sudo_sss_check_host(struct sudo_sss_handle *handle, st Line 565  sudo_sss_check_host(struct sudo_sss_handle *handle, st
         break;          break;
     case ENOENT:      case ENOENT:
         sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");          sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
        debug_return_int(false);        debug_return_bool(false);
     default:      default:
         sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0");          sudo_debug_printf(SUDO_DEBUG_INFO, "handle->fn_get_values(sudoHost): != 0");
        debug_return_int(ret);        debug_return_bool(ret);
     }      }
   
     /* walk through values */      /* walk through values */
Line 584  sudo_sss_check_host(struct sudo_sss_handle *handle, st Line 588  sudo_sss_check_host(struct sudo_sss_handle *handle, st
   
     handle->fn_free_values(val_array);      handle->fn_free_values(val_array);
   
    debug_return_int(ret);    debug_return_bool(ret);
 }  }
   
   /*
    * Look for netgroup specifcations in the sudoUser attribute and
    * if found, filter according to netgroup membership.
    *  returns:
    *   true -> netgroup spec found && netgroup member
    *  false -> netgroup spec found && not a member of netgroup
    *   true -> netgroup spec not found (filtered by SSSD already, netgroups are an exception)
    */
   static bool
   sudo_sss_filter_user_netgroup(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule)
   {
       bool ret = false, netgroup_spec_found = false;
       char **val_array, *val;
       int i;
       debug_decl(sudo_sss_filter_user_netgroup, SUDO_DEBUG_SSSD);
   
       if (!handle || !rule)
           debug_return_bool(ret);
   
       switch (handle->fn_get_values(rule, "sudoUser", &val_array)) {
           case 0:
               break;
           case ENOENT:
               sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
               debug_return_bool(ret);
           default:
               sudo_debug_printf(SUDO_DEBUG_INFO,
                   "handle->fn_get_values(sudoUser): != 0");
               debug_return_bool(ret);
       }
   
       for (i = 0; val_array[i] != NULL && !ret; ++i) {
           val = val_array[i];
           if (*val == '+') {
               netgroup_spec_found = true;
           }
           sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
           if (strcmp(val, "ALL") == 0 || netgr_matches(val, NULL, NULL, handle->pw->pw_name)) {
               ret = true;
               sudo_debug_printf(SUDO_DEBUG_DIAG,
                   "sssd/ldap sudoUser '%s' ... MATCH! (%s)",
                   val, handle->pw->pw_name);
               break;
           }
       }
       handle->fn_free_values(val_array);
       debug_return_bool(netgroup_spec_found ? ret : true);
   }
   
 static int  static int
 sudo_sss_result_filterp(struct sudo_sss_handle *handle,  sudo_sss_result_filterp(struct sudo_sss_handle *handle,
     struct sss_sudo_rule *rule, void *unused)      struct sss_sudo_rule *rule, void *unused)
Line 594  sudo_sss_result_filterp(struct sudo_sss_handle *handle Line 647  sudo_sss_result_filterp(struct sudo_sss_handle *handle
     (void)unused;      (void)unused;
     debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD);      debug_decl(sudo_sss_result_filterp, SUDO_DEBUG_SSSD);
   
    if (sudo_sss_check_host(handle, rule))    if (sudo_sss_check_host(handle, rule) &&
         sudo_sss_filter_user_netgroup(handle, rule))
         debug_return_int(1);          debug_return_int(1);
     else      else
         debug_return_int(0);          debug_return_int(0);
Line 612  sudo_sss_result_get(struct sudo_nss *nss, struct passw Line 666  sudo_sss_result_get(struct sudo_nss *nss, struct passw
         debug_return_ptr(NULL);          debug_return_ptr(NULL);
   
     sudo_debug_printf(SUDO_DEBUG_DIAG, "  username=%s", handle->pw->pw_name);      sudo_debug_printf(SUDO_DEBUG_DIAG, "  username=%s", handle->pw->pw_name);
    sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s", handle->domainname);    sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
         handle->domainname ? handle->domainname : "NULL");
   
     u_sss_result = f_sss_result = NULL;      u_sss_result = f_sss_result = NULL;
   
Line 659  sudo_sss_result_get(struct sudo_nss *nss, struct passw Line 714  sudo_sss_result_get(struct sudo_nss *nss, struct passw
                 *state |= _SUDO_SSS_STATE_HOSTMATCH;                  *state |= _SUDO_SSS_STATE_HOSTMATCH;
             }              }
         }          }
           sudo_debug_printf(SUDO_DEBUG_DEBUG,
               "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result,
               u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules);
       } else {
           sudo_debug_printf(SUDO_DEBUG_DEBUG,
               "u_sss_result=(%p, %u) => f_sss_result=NULL", u_sss_result,
               u_sss_result->num_rules);
     }      }
   
     sudo_debug_printf(SUDO_DEBUG_DEBUG,  
         "u_sss_result=(%p, %u) => f_sss_result=(%p, %u)", u_sss_result,  
         u_sss_result->num_rules, f_sss_result, f_sss_result->num_rules);  
   
     handle->fn_free_result(u_sss_result);      handle->fn_free_result(u_sss_result);
   
     debug_return_ptr(f_sss_result);      debug_return_ptr(f_sss_result);
Line 713  sudo_sss_check_bool(struct sudo_sss_handle *handle, st Line 771  sudo_sss_check_bool(struct sudo_sss_handle *handle, st
 }  }
   
 /*  /*
    * If a digest prefix is present, fills in struct sudo_digest
    * and returns a pointer to it, updating cmnd to point to the
    * command after the digest.
    */
   static struct sudo_digest *
   sudo_sss_extract_digest(char **cmnd, struct sudo_digest *digest)
   {
       char *ep, *cp = *cmnd;
       int digest_type = SUDO_DIGEST_INVALID;
       debug_decl(sudo_sss_check_command, SUDO_DEBUG_LDAP)
   
       /*
        * Check for and extract a digest prefix, e.g.
        * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
        */
       if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') {
           switch (cp[3]) {
           case '2':
               if (cp[4] == '2' && cp[5] == '4')
                   digest_type = SUDO_DIGEST_SHA224;
               else if (cp[4] == '5' && cp[5] == '6')
                   digest_type = SUDO_DIGEST_SHA256;
               break;
           case '3':
               if (cp[4] == '8' && cp[5] == '4')
                   digest_type = SUDO_DIGEST_SHA384;
               break;
           case '5':
               if (cp[4] == '1' && cp[5] == '2')
                   digest_type = SUDO_DIGEST_SHA512;
               break;
           }
           if (digest_type != SUDO_DIGEST_INVALID) {
               cp += 6;
               while (isblank((unsigned char)*cp))
                   cp++;
               if (*cp == ':') {
                   cp++;
                   while (isblank((unsigned char)*cp))
                       cp++;
                   ep = cp;
                   while (*ep != '\0' && !isblank((unsigned char)*ep))
                       ep++;
                   if (*ep != '\0') {
                       digest->digest_type = digest_type;
                       digest->digest_str = estrndup(cp, (size_t)(ep - cp));
                       cp = ep + 1;
                       while (isblank((unsigned char)*cp))
                           cp++;
                       *cmnd = cp;
                       sudo_debug_printf(SUDO_DEBUG_INFO,
                           "%s digest %s for %s",
                           digest_type == SUDO_DIGEST_SHA224 ? "sha224" :
                           digest_type == SUDO_DIGEST_SHA256 ? "sha256" :
                           digest_type == SUDO_DIGEST_SHA384 ? "sha384" :
                           "sha512", digest->digest_str, cp);
                       debug_return_ptr(digest);
                   }
               }
           }
       }
       debug_return_ptr(NULL);
   }
   
   /*
  * Walk through search results and return true if we have a command match,   * Walk through search results and return true if we have a command match,
  * false if disallowed and UNSPEC if not matched.   * false if disallowed and UNSPEC if not matched.
  */   */
Line 723  sudo_sss_check_command(struct sudo_sss_handle *handle, Line 846  sudo_sss_check_command(struct sudo_sss_handle *handle,
     char **val_array = NULL, *val;      char **val_array = NULL, *val;
     char *allowed_cmnd, *allowed_args;      char *allowed_cmnd, *allowed_args;
     int i, foundbang, ret = UNSPEC;      int i, foundbang, ret = UNSPEC;
       struct sudo_digest digest, *allowed_digest = NULL;
     debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD);      debug_decl(sudo_sss_check_command, SUDO_DEBUG_SSSD);
   
     if (rule == NULL)      if (rule == NULL)
Line 754  sudo_sss_check_command(struct sudo_sss_handle *handle, Line 878  sudo_sss_check_command(struct sudo_sss_handle *handle,
             continue;              continue;
         }          }
   
           /* check for sha-2 digest */
           allowed_digest = sudo_sss_extract_digest(&val, &digest);
   
         /* check for !command */          /* check for !command */
         if (*val == '!') {          if (*val == '!') {
             foundbang = true;              foundbang = true;
Line 769  sudo_sss_check_command(struct sudo_sss_handle *handle, Line 896  sudo_sss_check_command(struct sudo_sss_handle *handle,
             *allowed_args++ = '\0';              *allowed_args++ = '\0';
   
         /* check the command like normal */          /* check the command like normal */
        if (command_matches(allowed_cmnd, allowed_args)) {        if (command_matches(allowed_cmnd, allowed_args, NULL)) {
             /*              /*
              * If allowed (no bang) set ret but keep on checking.               * If allowed (no bang) set ret but keep on checking.
              * If disallowed (bang), exit loop.               * If disallowed (bang), exit loop.

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>