Ejemplo n.º 1
0
 /**
  * Set the hook as failed w/ the given message
  *
  * @param   string  $message    Error message or error format string
  * @param   mixed   ...$arg     Format string argument
  */
 private function fail($message)
 {
     $args = array_slice(func_get_args(), 1);
     $lastError = vsprintf($message, $args);
     Logger::debug($lastError);
     $this->lastError = $lastError;
 }
 /**
  * Set the filter and render it internally.
  *
  * @param  Filter $filter
  *
  * @return $this
  *
  * @throws ProgrammingError
  */
 public function setFilter(Filter $filter)
 {
     $this->filter = $filter;
     $this->query = $this->renderFilter($this->filter);
     Logger::debug('Rendered elasticsearch filter: %s', json_encode($this->query));
     return $this;
 }
Ejemplo n.º 3
0
 /**
  * Append the given log entry or nested inspection
  *
  * @throws  ProgrammingError            When called after erroring
  *
  * @param $entry    string|Inspection   A log entry or nested inspection
  */
 public function write($entry)
 {
     if (isset($this->error)) {
         throw new ProgrammingError('Inspection object used after error');
     }
     if ($entry instanceof Inspection) {
         $this->log[$entry->description] = $entry->toArray();
     } else {
         Logger::debug($entry);
         $this->log[] = $entry;
     }
 }
Ejemplo n.º 4
0
 /**
  * Resolve a macro based on the given object
  *
  * @param   string                      $macro      The macro to resolve
  * @param   MonitoredObject|stdClass    $object     The object used to resolve the macro
  *
  * @return  string                                  The new value or the macro if it cannot be resolved
  */
 public static function resolveMacro($macro, $object)
 {
     if (isset(self::$icingaMacros[$macro]) && isset($object->{self::$icingaMacros[$macro]})) {
         return $object->{self::$icingaMacros[$macro]};
     }
     try {
         $value = $object->{$macro};
     } catch (Exception $e) {
         $value = null;
         Logger::debug('Unable to resolve macro "%s". An error occured: %s', $macro, $e);
     }
     return $value !== null ? $value : $macro;
 }
Ejemplo n.º 5
0
 /**
  * Create and return a new navigation item for the given configuration
  *
  * @param   string              $name
  * @param   array|ConfigObject  $properties
  *
  * @return  NavigationItem
  *
  * @throws  InvalidArgumentException    If the $properties argument is neither an array nor a ConfigObject
  */
 public function createItem($name, $properties)
 {
     if ($properties instanceof ConfigObject) {
         $properties = $properties->toArray();
     } elseif (!is_array($properties)) {
         throw new InvalidArgumentException('Argument $properties must be of type array or ConfigObject');
     }
     $itemType = isset($properties['type']) ? String::cname($properties['type'], '-') : 'NavigationItem';
     if (!empty(static::$types) && isset(static::$types[$itemType])) {
         return new static::$types[$itemType]($name, $properties);
     }
     $item = null;
     foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
         $classPath = 'Icinga\\Module\\' . ucfirst($module->getName()) . '\\' . static::NAVIGATION_NS . '\\' . $itemType;
         if (class_exists($classPath)) {
             $item = new $classPath($name, $properties);
             break;
         }
     }
     if ($item === null) {
         $classPath = 'Icinga\\' . static::NAVIGATION_NS . '\\' . $itemType;
         if (class_exists($classPath)) {
             $item = new $classPath($name, $properties);
         }
     }
     if ($item === null) {
         Logger::debug('Failed to find custom navigation item class %s for item %s. Using base class NavigationItem now', $itemType, $name);
         $item = new NavigationItem($name, $properties);
         static::$types[$itemType] = 'Icinga\\Web\\Navigation\\NavigationItem';
     } elseif (!$item instanceof NavigationItem) {
         throw new ProgrammingError('Class %s must inherit from NavigationItem', $classPath);
     } else {
         static::$types[$itemType] = $classPath;
     }
     return $item;
 }
Ejemplo n.º 6
0
 protected function sendCommand(IcingaApiCommand $command)
 {
     Logger::debug('Sending Icinga command "%s" to the API "%s:%u"', $command->getEndpoint(), $this->getHost(), $this->getPort());
     $response = RestRequest::post($this->getUriFor($command->getEndpoint()))->authenticateWith($this->getUsername(), $this->getPassword())->sendJson()->noStrictSsl()->setPayload($command->getData())->send();
     if (isset($response['error'])) {
         throw new CommandTransportException('Can\'t send external Icinga command: %u %s', $response['error'], $response['status']);
     }
     $result = array_pop($response['results']);
     if ($result['code'] < 200 || $result['code'] >= 300) {
         throw new CommandTransportException('Can\'t send external Icinga command: %u %s', $result['code'], $result['status']);
     }
     if ($command->hasNext()) {
         $this->sendCommand($command->getNext());
     }
 }
Ejemplo n.º 7
0
 /**
  * Write the command to the Icinga command file on the remote host
  *
  * @param   IcingaCommand   $command
  * @param   int|null        $now
  *
  * @throws  ConfigurationError
  * @throws  TransportException
  */
 public function send(IcingaCommand $command, $now = null)
 {
     if (!isset($this->path)) {
         throw new ConfigurationError('Can\'t send external Icinga Command. Path to the remote command file is missing');
     }
     if (!isset($this->host)) {
         throw new ConfigurationError('Can\'t send external Icinga Command. Remote host is missing');
     }
     $commandString = $this->renderer->render($command, $now);
     Logger::debug('Sending external Icinga command "%s" to the remote command file "%s:%u%s"', $commandString, $this->host, $this->port, $this->path);
     $ssh = sprintf('ssh -o BatchMode=yes -p %u', $this->port);
     // -o BatchMode=yes for disabling interactive authentication methods
     if (isset($this->user)) {
         $ssh .= sprintf(' -l %s', escapeshellarg($this->user));
     }
     if (isset($this->privateKey)) {
         $ssh .= sprintf(' -o StrictHostKeyChecking=no -i %s', escapeshellarg($this->privateKey));
     }
     $ssh .= sprintf(' %s "echo %s > %s" 2>&1', escapeshellarg($this->host), escapeshellarg($commandString), escapeshellarg($this->path));
     exec($ssh, $output, $status);
     if ($status !== 0) {
         throw new TransportException('Can\'t send external Icinga command: %s', implode(' ', $output));
     }
 }
Ejemplo n.º 8
0
 /**
  * Add a sort rule for this query
  *
  * If called without a specific column, the repository's defaul sort rules will be applied.
  * This notifies the repository about each column being required as filter column.
  *
  * @param   string  $field          The name of the column by which to sort the query's result
  * @param   string  $direction      The direction to use when sorting (asc or desc, default is asc)
  * @param   bool    $ignoreDefault  Whether to ignore any default sort rules if $field is given
  *
  * @return  $this
  */
 public function order($field = null, $direction = null, $ignoreDefault = false)
 {
     $sortRules = $this->getSortRules();
     if ($field === null) {
         // Use first available sort rule as default
         if (empty($sortRules)) {
             // Return early in case of no sort defaults and no given $field
             return $this;
         }
         $sortColumns = reset($sortRules);
         if (!array_key_exists('columns', $sortColumns)) {
             $sortColumns['columns'] = array(key($sortRules));
         }
         if ($direction !== null || !array_key_exists('order', $sortColumns)) {
             $sortColumns['order'] = $direction ?: static::SORT_ASC;
         }
     } else {
         $alias = $this->repository->reassembleQueryColumnAlias($this->target, $field) ?: $field;
         if (!$ignoreDefault && array_key_exists($alias, $sortRules)) {
             $sortColumns = $sortRules[$alias];
             if (!array_key_exists('columns', $sortColumns)) {
                 $sortColumns['columns'] = array($alias);
             }
             if ($direction !== null || !array_key_exists('order', $sortColumns)) {
                 $sortColumns['order'] = $direction ?: static::SORT_ASC;
             }
         } else {
             $sortColumns = array('columns' => array($alias), 'order' => $direction);
         }
     }
     $baseDirection = strtoupper($sortColumns['order']) === static::SORT_DESC ? static::SORT_DESC : static::SORT_ASC;
     foreach ($sortColumns['columns'] as $column) {
         list($column, $specificDirection) = $this->splitOrder($column);
         if ($this->hasLimit() && $this->repository->providesValueConversion($this->target, $column)) {
             Logger::debug('Cannot order by column "%s" in repository "%s". The query is' . ' limited and applies value conversion rules on the column', $column, $this->repository->getName());
             continue;
         }
         try {
             $this->query->order($this->repository->requireFilterColumn($this->target, $column, $this), $specificDirection ?: $baseDirection);
         } catch (QueryException $_) {
             Logger::info('Cannot order by column "%s" in repository "%s"', $column, $this->repository->getName());
         }
     }
     return $this;
 }
Ejemplo n.º 9
0
 /**
  * Create or return an instance of a given hook
  *
  * TODO: Should return some kind of a hook interface
  *
  * @param   string  $name   One of the predefined hook names
  * @param   string  $key    The identifier of a specific subtype
  *
  * @return  mixed
  */
 public static function createInstance($name, $key)
 {
     $name = self::normalizeHookName($name);
     if (!self::has($name, $key)) {
         return null;
     }
     if (isset(self::$instances[$name][$key])) {
         return self::$instances[$name][$key];
     }
     $class = self::$hooks[$name][$key];
     if (!class_exists($class)) {
         throw new ProgrammingError('Erraneous hook implementation, class "%s" does not exist', $class);
     }
     try {
         $instance = new $class();
     } catch (Exception $e) {
         Logger::debug('Hook "%s" (%s) (%s) failed, will be unloaded: %s', $name, $key, $class, $e->getMessage());
         // TODO: Persist unloading for "some time" or "current session"
         unset(self::$hooks[$name][$key]);
         return null;
     }
     self::assertValidHook($instance, $name);
     self::$instances[$name][$key] = $instance;
     return $instance;
 }
Ejemplo n.º 10
0
 /**
  * Detect installed modules from every path provided in modulePaths
  *
  * @param   array   $availableDirs      Installed modules location
  *
  * @return $this
  */
 public function detectInstalledModules(array $availableDirs = null)
 {
     $modulePaths = $availableDirs !== null ? $availableDirs : $this->modulePaths;
     foreach ($modulePaths as $basedir) {
         $canonical = realpath($basedir);
         if ($canonical === false) {
             Logger::warning('Module path "%s" does not exist', $basedir);
             continue;
         }
         if (!is_dir($canonical)) {
             Logger::error('Module path "%s" is not a directory', $canonical);
             continue;
         }
         if (!is_readable($canonical)) {
             Logger::error('Module path "%s" is not readable', $canonical);
             continue;
         }
         if (($dh = opendir($canonical)) !== false) {
             while (($file = readdir($dh)) !== false) {
                 if ($file[0] === '.') {
                     continue;
                 }
                 if (is_dir($canonical . '/' . $file)) {
                     if (!array_key_exists($file, $this->installedBaseDirs)) {
                         $this->installedBaseDirs[$file] = $canonical . '/' . $file;
                     } else {
                         Logger::debug('Module "%s" already exists in installation path "%s" and is ignored.', $canonical . '/' . $file, $this->installedBaseDirs[$file]);
                     }
                 }
             }
             closedir($dh);
         }
     }
     ksort($this->installedBaseDirs);
     return $this;
 }
Ejemplo n.º 11
0
 /**
  * Prepare and establish a connection with the LDAP server
  *
  * @return  resource        A LDAP link identifier
  *
  * @throws  LdapException   In case the connection is not possible
  */
 protected function prepareNewConnection()
 {
     if ($this->encryption === static::STARTTLS || $this->encryption === static::LDAPS) {
         $this->prepareTlsEnvironment();
     }
     $hostname = $this->hostname;
     if ($this->encryption === static::LDAPS) {
         $hostname = 'ldaps://' . $hostname;
     }
     $ds = ldap_connect($hostname, $this->port);
     // Usage of ldap_rename, setting LDAP_OPT_REFERRALS to 0 or using STARTTLS requires LDAPv3.
     // If this does not work we're probably not in a PHP 5.3+ environment as it is VERY
     // unlikely that the server complains about it by itself prior to a bind request
     ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
     // Not setting this results in "Operations error" on AD when using the whole domain as search base
     ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
     if ($this->encryption === static::STARTTLS) {
         if ($this->encryptionSuccess = @ldap_start_tls($ds)) {
             Logger::debug('LDAP STARTTLS succeeded');
         } else {
             Logger::error('LDAP STARTTLS failed: %s', ldap_error($ds));
             // ldap_start_tls seems to corrupt the connection though if I understand
             // https://tools.ietf.org/html/rfc4511#section-4.14.2 correctly, this shouldn't happen
             $ds = ldap_connect($hostname, $this->port);
             ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
             ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
         }
     } elseif ($this->encryption === static::LDAPS) {
         $this->encryptionSuccess = true;
     }
     return $ds;
 }
Ejemplo n.º 12
0
 /**
  * Parse the given value based on the ASN.1 standard (GeneralizedTime) and return its timestamp representation
  *
  * @param   string|null     $value
  *
  * @return  int
  */
 protected function retrieveGeneralizedTime($value)
 {
     if ($value === null) {
         return $value;
     }
     if (($dateTime = DateTime::createFromFormat('YmdHis.uO', $value)) !== false || ($dateTime = DateTime::createFromFormat('YmdHis.uZ', $value)) !== false || ($dateTime = DateTime::createFromFormat('YmdHis.u', $value)) !== false || ($dateTime = DateTime::createFromFormat('YmdHis', $value)) !== false || ($dateTime = DateTime::createFromFormat('YmdHi', $value)) !== false || ($dateTime = DateTime::createFromFormat('YmdH', $value)) !== false) {
         return $dateTime->getTimeStamp();
     } else {
         Logger::debug(sprintf('Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) in repository "%s".', $value, $this->getName()));
     }
 }
Ejemplo n.º 13
0
 /**
  * Perform a LDAP search and return the result
  *
  * @param   LdapQuery   $query
  * @param   array       $attributes     An array of the required attributes
  * @param   int         $attrsonly      Should be set to 1 if only attribute types are wanted
  * @param   int         $sizelimit      Enables you to limit the count of entries fetched
  * @param   int         $timelimit      Sets the number of seconds how long is spend on the search
  * @param   int         $deref
  *
  * @return  resource|bool               A search result identifier or false on error
  *
  * @throws  LogicException              If the LDAP query search scope is unsupported
  */
 public function ldapSearch(LdapQuery $query, array $attributes = null, $attrsonly = 0, $sizelimit = 0, $timelimit = 0, $deref = LDAP_DEREF_NEVER)
 {
     $queryString = (string) $query;
     $baseDn = $query->getBase() ?: $this->getDn();
     $scope = $query->getScope();
     if (Logger::getInstance()->getLevel() === Logger::DEBUG) {
         // We're checking the level by ourself to avoid rendering the ldapsearch commandline for nothing
         $starttlsParam = $this->encryption === static::STARTTLS ? ' -ZZ' : '';
         $ldapUrl = ($this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://') . $this->hostname . ($this->port ? ':' . $this->port : '');
         if ($this->bound) {
             $bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -W' : '');
         }
         if ($deref === LDAP_DEREF_NEVER) {
             $derefName = 'never';
         } elseif ($deref === LDAP_DEREF_ALWAYS) {
             $derefName = 'always';
         } elseif ($deref === LDAP_DEREF_SEARCHING) {
             $derefName = 'search';
         } else {
             // $deref === LDAP_DEREF_FINDING
             $derefName = 'find';
         }
         Logger::debug("Issueing LDAP search. Use '%s' to reproduce.", sprintf('ldapsearch -P 3%s -H "%s"%s -b "%s" -s "%s" -z %u -l %u -a "%s"%s%s%s', $starttlsParam, $ldapUrl, $bindParams, $baseDn, $scope, $sizelimit, $timelimit, $derefName, $attrsonly ? ' -A' : '', $queryString ? ' "' . $queryString . '"' : '', $attributes ? ' "' . join('" "', $attributes) . '"' : ''));
     }
     switch ($scope) {
         case LdapQuery::SCOPE_SUB:
             $function = 'ldap_search';
             break;
         case LdapQuery::SCOPE_ONE:
             $function = 'ldap_list';
             break;
         case LdapQuery::SCOPE_BASE:
             $function = 'ldap_read';
             break;
         default:
             throw new LogicException('LDAP scope %s not supported by ldapSearch', $scope);
     }
     return @$function($this->getConnection(), $baseDn, $queryString, $attributes, $attrsonly, $sizelimit, $timelimit, $deref);
 }
Ejemplo n.º 14
0
 /**
  * Return the distinguished name for the given uid or gid
  *
  * @param   string  $name
  *
  * @return  string
  */
 protected function persistUserName($name)
 {
     try {
         $userDn = $this->ds->select()->from($this->userClass, array())->where($this->userNameAttribute, $name)->setBase($this->userBaseDn)->setUsePagedResults(false)->fetchDn();
         if ($userDn) {
             return $userDn;
         }
         $groupDn = $this->ds->select()->from($this->groupClass, array())->where($this->groupNameAttribute, $name)->setBase($this->groupBaseDn)->setUsePagedResults(false)->fetchDn();
         if ($groupDn) {
             return $groupDn;
         }
     } catch (LdapException $_) {
         // pass
     }
     Logger::debug('Unable to persist uid or gid "%s" in repository "%s". No DN found.', $name, $this->getName());
     return $name;
 }
Ejemplo n.º 15
0
 /**
  * @return string
  */
 public function __toString()
 {
     try {
         $select = (string) $this->getSelectQuery();
         return $this->getIsSubQuery() ? '(' . $select . ')' : $select;
     } catch (Exception $e) {
         Logger::debug('Failed to render DbQuery. An error occured: %s', $e);
         return '';
     }
 }
Ejemplo n.º 16
0
 /**
  * Send the request
  *
  * @return  mixed
  *
  * @throws  Exception
  */
 public function send()
 {
     $defaults = array('host' => 'localhost', 'path' => '/');
     $url = array_merge($defaults, parse_url($this->uri));
     if (isset($url['port'])) {
         $url['host'] .= sprintf(':%u', $url['port']);
     }
     if (isset($url['query'])) {
         $url['path'] .= sprintf('?%s', $url['query']);
     }
     $headers = array("{$this->method} {$url['path']} HTTP/1.1", "Host: {$url['host']}", "Content-Type: {$this->contentType}", 'Accept: application/json', 'Expect:');
     $ch = curl_init();
     $options = array(CURLOPT_URL => $this->uri, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_PROXY => '', CURLOPT_CUSTOMREQUEST => $this->method, CURLOPT_RETURNTRANSFER => true);
     // Record cURL command line for debugging
     $curlCmd = array('curl', '-s', '-X', $this->method, '-H', escapeshellarg('Accept: application/json'));
     if ($this->strictSsl) {
         $options[CURLOPT_SSL_VERIFYHOST] = 2;
         $options[CURLOPT_SSL_VERIFYPEER] = true;
     } else {
         $options[CURLOPT_SSL_VERIFYHOST] = false;
         $options[CURLOPT_SSL_VERIFYPEER] = false;
         $curlCmd[] = '-k';
     }
     if ($this->hasBasicAuth) {
         $options[CURLOPT_USERPWD] = sprintf('%s:%s', $this->username, $this->password);
         $curlCmd[] = sprintf('-u %s:%s', escapeshellarg($this->username), escapeshellarg($this->password));
     }
     if (!empty($this->payload)) {
         $payload = $this->serializePayload($this->payload, $this->contentType);
         $options[CURLOPT_POSTFIELDS] = $payload;
         $curlCmd[] = sprintf('-d %s', escapeshellarg($payload));
     }
     $options[CURLOPT_HTTPHEADER] = $headers;
     $stream = null;
     if (Logger::getInstance()->getLevel() === Logger::DEBUG) {
         $stream = fopen('php://temp', 'w');
         $options[CURLOPT_VERBOSE] = true;
         $options[CURLOPT_STDERR] = $stream;
     }
     curl_setopt_array($ch, $options);
     Logger::debug('Executing %s %s', implode(' ', $curlCmd), escapeshellarg($this->uri));
     $result = curl_exec($ch);
     if ($result === false) {
         throw new Exception(curl_error($ch));
     }
     curl_close($ch);
     if (is_resource($stream)) {
         rewind($stream);
         Logger::debug(stream_get_contents($stream));
         fclose($stream);
     }
     $response = @json_decode($result, true);
     if ($response === null) {
         if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
             throw new Exception(json_last_error_msg());
         } else {
             switch (json_last_error()) {
                 case JSON_ERROR_DEPTH:
                     $msg = 'The maximum stack depth has been exceeded';
                     break;
                 case JSON_ERROR_CTRL_CHAR:
                     $msg = 'Control character error, possibly incorrectly encoded';
                     break;
                 case JSON_ERROR_STATE_MISMATCH:
                     $msg = 'Invalid or malformed JSON';
                     break;
                 case JSON_ERROR_SYNTAX:
                     $msg = 'Syntax error';
                     break;
                 case JSON_ERROR_UTF8:
                     $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
                     break;
                 default:
                     $msg = 'An error occured when parsing a JSON string';
             }
             throw new Exception($msg);
         }
     }
     return $response;
 }
Ejemplo n.º 17
0
 /**
  * Remove session cookies
  */
 protected function clearCookies()
 {
     if (ini_get('session.use_cookies')) {
         Logger::debug('Clear session cookie');
         $params = session_get_cookie_params();
         setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
     }
 }
Ejemplo n.º 18
0
 /**
  * Write the command to the Icinga command file on the remote host
  *
  * @param   IcingaCommand   $command
  * @param   int|null        $now
  *
  * @throws  ConfigurationError
  * @throws  CommandTransportException
  */
 public function send(IcingaCommand $command, $now = null)
 {
     if (!isset($this->path)) {
         throw new ConfigurationError('Can\'t send external Icinga Command. Path to the remote command file is missing');
     }
     if (!isset($this->host)) {
         throw new ConfigurationError('Can\'t send external Icinga Command. Remote host is missing');
     }
     $commandString = $this->renderer->render($command, $now);
     Logger::debug('Sending external Icinga command "%s" to the remote command file "%s:%u%s"', $commandString, $this->host, $this->port, $this->path);
     return $this->sendCommandString($commandString);
 }
Ejemplo n.º 19
0
 /**
  * Return the form for the given type of navigation item
  *
  * @param   string  $type
  *
  * @return  Form
  */
 protected function getItemForm($type)
 {
     $className = StringHelper::cname($type, '-') . 'Form';
     $form = null;
     foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
         $classPath = 'Icinga\\Module\\' . ucfirst($module->getName()) . '\\' . static::FORM_NS . '\\' . $className;
         if (class_exists($classPath)) {
             $form = new $classPath();
             break;
         }
     }
     if ($form === null) {
         $classPath = 'Icinga\\' . static::FORM_NS . '\\' . $className;
         if (class_exists($classPath)) {
             $form = new $classPath();
         }
     }
     if ($form === null) {
         Logger::debug('Failed to find custom navigation item form %s for item %s. Using form NavigationItemForm now', $className, $type);
         $form = new NavigationItemForm();
     } elseif (!$form instanceof NavigationItemForm) {
         throw new ProgrammingError('Class %s must inherit from NavigationItemForm', $classPath);
     }
     return $form;
 }
Ejemplo n.º 20
0
 /**
  * Return the groups the given user is a member of
  *
  * @param   User    $user
  *
  * @return  array
  */
 public function getMemberships(User $user)
 {
     if ($this->groupClass === 'posixGroup') {
         // Posix group only uses simple user name
         $userDn = $user->getUsername();
     } else {
         // LDAP groups use the complete DN
         if (($userDn = $user->getAdditional('ldap_dn')) === null) {
             $userQuery = $this->ds->select()->from($this->userClass)->where($this->userNameAttribute, $user->getUsername())->setBase($this->userBaseDn)->setUsePagedResults(false);
             if ($this->userFilter) {
                 $userQuery->where(new Expression($this->userFilter));
             }
             if (($userDn = $userQuery->fetchDn()) === null) {
                 return array();
             }
         }
     }
     $groupQuery = $this->ds->select()->from($this->groupClass, array($this->groupNameAttribute))->where($this->groupMemberAttribute, $userDn)->setBase($this->groupBaseDn);
     if ($this->groupFilter) {
         $groupQuery->where(new Expression($this->groupFilter));
     }
     Logger::debug('Fetching groups for user %s using filter %s.', $user->getUsername(), $groupQuery->__toString());
     $groups = array();
     foreach ($groupQuery as $row) {
         $groups[] = $row->{$this->groupNameAttribute};
     }
     Logger::debug('Fetched %d groups: %s.', count($groups), join(', ', $groups));
     return $groups;
 }
Ejemplo n.º 21
0
 /**
  * Create or return an instance of a given hook
  *
  * TODO: Should return some kind of a hook interface
  *
  * @param   string  $name   One of the predefined hook names
  * @param   string  $key    The identifier of a specific subtype
  *
  * @return  mixed
  */
 public static function createInstance($name, $key)
 {
     if (!self::has($name, $key)) {
         return null;
     }
     if (isset(self::$instances[$name][$key])) {
         return self::$instances[$name][$key];
     }
     $class = self::$hooks[$name][$key];
     try {
         $instance = new $class();
     } catch (Exception $e) {
         Logger::debug('Hook "%s" (%s) (%s) failed, will be unloaded: %s', $name, $key, $class, $e->getMessage());
         // TODO: Persist unloading for "some time" or "current session"
         unset(self::$hooks[$name][$key]);
         return null;
     }
     self::assertValidHook($instance, $name);
     self::$instances[$name][$key] = $instance;
     return $instance;
 }
Ejemplo n.º 22
0
 /**
  * Write the command to the local Icinga command file
  *
  * @param   IcingaCommand   $command
  * @param   int|null        $now
  *
  * @throws  ConfigurationError
  * @throws  CommandTransportException
  */
 public function send(IcingaCommand $command, $now = null)
 {
     if (!isset($this->path)) {
         throw new ConfigurationError('Can\'t send external Icinga Command. Path to the local command file is missing');
     }
     $commandString = $this->renderer->render($command, $now);
     Logger::debug('Sending external Icinga command "%s" to the local command file "%s"', $commandString, $this->path);
     try {
         $file = new File($this->path, $this->openMode);
         $file->fwrite($commandString . "\n");
     } catch (Exception $e) {
         $message = $e->getMessage();
         if ($e instanceof RuntimeException && ($pos = strrpos($message, ':')) !== false) {
             // Assume RuntimeException thrown by SplFileObject in the format: __METHOD__ . "({$filename}): Message"
             $message = substr($message, $pos + 1);
         }
         throw new CommandTransportException('Can\'t send external Icinga command to the local command file "%s": %s', $this->path, $message);
     }
 }
Ejemplo n.º 23
0
 /**
  * Clean up the given attributes and return them as simple object
  *
  * Applies column aliases, aggregates multi-value attributes as array and sets null for each missing attribute.
  *
  * @param   array   $attributes
  * @param   array   $requestedFields
  *
  * @return  object
  */
 public function cleanupAttributes($attributes, array $requestedFields)
 {
     // In case the result contains attributes with a differing case than the requested fields, it is
     // necessary to create another array to map attributes case insensitively to their requested counterparts.
     // This does also apply the virtual alias handling. (Since an LDAP server does not handle such)
     $loweredFieldMap = array();
     foreach ($requestedFields as $name => $alias) {
         $loweredFieldMap[strtolower($name)] = is_string($alias) ? $alias : $name;
     }
     $cleanedAttributes = array();
     for ($i = 0; $i < $attributes['count']; $i++) {
         $attribute_name = $attributes[$i];
         if ($attributes[$attribute_name]['count'] === 1) {
             $attribute_value = $attributes[$attribute_name][0];
         } else {
             $attribute_value = array();
             for ($j = 0; $j < $attributes[$attribute_name]['count']; $j++) {
                 $attribute_value[] = $attributes[$attribute_name][$j];
             }
         }
         $requestedAttributeName = isset($loweredFieldMap[strtolower($attribute_name)]) ? $loweredFieldMap[strtolower($attribute_name)] : $attribute_name;
         $cleanedAttributes[$requestedAttributeName] = $attribute_value;
     }
     // The result may not contain all requested fields, so populate the cleaned
     // result with the missing fields and their value being set to null
     foreach ($requestedFields as $name => $alias) {
         if (!is_string($alias)) {
             $alias = $name;
         }
         if (!array_key_exists($alias, $cleanedAttributes)) {
             $cleanedAttributes[$alias] = null;
             Logger::debug('LDAP query result does not provide the requested field "%s"', $name);
         }
     }
     return (object) $cleanedAttributes;
 }
 /**
  * Extract and return one or more objects from the given data
  *
  * @param   array   $objectPath
  * @param   array   $fields
  * @param   array   $data
  *
  * @param   object|array
  */
 protected function extractObject(array $objectPath, array $fields, array $data)
 {
     if (!$this->isAssociative($data)) {
         $values = array();
         foreach ($data as $value) {
             if (is_array($value)) {
                 $objectValue = $this->extractObject($objectPath, $fields, $value);
                 if (is_array($objectValue)) {
                     $values = array_merge($values, $objectValue);
                 } elseif ($objectValue !== null) {
                     $values[] = $objectValue;
                 }
             } else {
                 Logger::debug('Expected non-scalar value but got "%s" instead', $value);
             }
         }
         return $values;
     }
     $object = array_shift($objectPath);
     if (isset($data[$object])) {
         if (!is_array($data[$object])) {
             Logger::debug('Expected non-scalar value but got "%s" instead', $data[$object]);
         } elseif (!empty($objectPath)) {
             return $this->extractObject($objectPath, $fields, $data[$object]);
         } elseif ($this->isAssociative($data[$object])) {
             $properties = array();
             foreach ($fields as $alias => $field) {
                 if (isset($field['object_path'])) {
                     $properties[$alias] = $this->extractObject($field['object_path'], $field['fields'], $data[$object]);
                 } else {
                     $properties[$alias] = $this->extractScalar($field, $data[$object]);
                 }
             }
             return (object) $properties;
         } else {
             $objects = array();
             foreach ($data[$object] as $objectData) {
                 $properties = array();
                 foreach ($fields as $alias => $field) {
                     if (isset($field['object_path'])) {
                         $properties[$alias] = $this->extractObject($field['object_path'], $field['fields'], $objectData);
                     } else {
                         $properties[$alias] = $this->extractScalar($field, $objectData);
                     }
                 }
                 $objects[] = (object) $properties;
             }
             return $objects;
         }
     }
 }
Ejemplo n.º 25
0
 /**
  * Prepare and establish a connection with the LDAP server
  *
  * @return  resource        A positive LDAP link identifier
  *
  * @throws  LdapException   In case the connection is not possible
  */
 protected function prepareNewConnection()
 {
     if ($this->encryption === static::STARTTLS || $this->encryption === static::LDAPS) {
         $this->prepareTlsEnvironment();
     }
     $hostname = $this->hostname;
     if ($this->encryption === static::LDAPS) {
         $hostname = 'ldaps://' . $hostname;
     }
     $ds = ldap_connect($hostname, $this->port);
     try {
         $this->capabilities = $this->discoverCapabilities($ds);
         $this->discoverySuccess = true;
     } catch (LdapException $e) {
         Logger::debug($e);
         Logger::warning('LADP discovery failed, assuming default LDAP capabilities.');
         $this->capabilities = new Capability();
         // create empty default capabilities
         $this->discoverySuccess = false;
     }
     if ($this->encryption === static::STARTTLS) {
         $force_tls = false;
         if ($this->capabilities->hasStartTls()) {
             if (@ldap_start_tls($ds)) {
                 Logger::debug('LDAP STARTTLS succeeded');
             } else {
                 Logger::error('LDAP STARTTLS failed: %s', ldap_error($ds));
                 throw new LdapException('LDAP STARTTLS failed: %s', ldap_error($ds));
             }
         } elseif ($force_tls) {
             throw new LdapException('STARTTLS is required but not announced by %s', $this->hostname);
         } else {
             Logger::warning('LDAP STARTTLS enabled but not announced');
         }
     }
     // ldap_rename requires LDAPv3:
     if ($this->capabilities->hasLdapV3()) {
         if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
             throw new LdapException('LDAPv3 is required');
         }
     } else {
         // TODO: remove this -> FORCING v3 for now
         ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
         Logger::warning('No LDAPv3 support detected');
     }
     // Not setting this results in "Operations error" on AD when using the whole domain as search base
     ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
     // ldap_set_option($ds, LDAP_OPT_DEREF, LDAP_DEREF_NEVER);
     return $ds;
 }