DokuWiki

It's better when it's simple

Инструменты пользователя

Инструменты сайта


ru:tips:ipacl

Этот небольшой модуль (mod) позволяет вам настраивать права доступа зависящие не только от имени пользователя и группы, но и от того откуда этот пользователь подключается. Инструкции по установке, приведенные ниже, относятся к версии 2005-07-13 DokuWiki. Я буду стараться обновлять их для всех последующих версий, но «в идеале» я бы хотел увидеть эту функциональность вошедшей в основную систему.

Как это работает?

Работа модуля достаточно проста. Используйте ACL для того, чтобы добавить новое правило для отдельного IP или для целой сети. Привожу пример:

*     %192.168.1.0/24  1   # Это правило дает любому клиенту из сети 192.168.1.0/255.255.255.0 право на чтение всего wiki.
start %192.168.2.10    2   # Это правило дает клиенту с IP 192.168.2.10 право на редактирование домашней статьи.

В настоящий момент я не изменял существующую панель управления ACL для того, чтобы включить новый тип элементов, поэтому все эти правила добавляются точно также, как вы добавляете новых пользователей. Просто добавьте перед IP символ '%', выберите необходимые права доступа и разделы wiki. Все остальное работает точно также как и раньше.

Моя система ищет все элементы начинающиеся с % и пытается сравнить с ip-адресом, с которого подсоединился пользователь. Если элемент не содержит /xx на конце, то производиться точное сравнение с ip-адресом. Если на конце присутствует маска (как в примере выше), то будет сравниваться только часть ip-адреса, соответствующая маске. Таким образом элемент 192.168.1.0/30 позволит доступ 192.168.1.0, 192.168.1.1, 192.168.1.2 и 192.168.1.3, и никому больше. Более подробно о маске подсети написано в статье Subnetwork_mask.

Я все еще не слишком хорошо протестировал, но до сих пор все работало замечательно. Если вы обнаружите какие-либо проблемы с моим модулем, или у вас есть какие-либо советы, пожелания или потребности, можете написать мне по адресу max [at] mxserve [dot] net.

Install Instructions

The whole mod makes only 2 changes to inc/auth.php. Most of this code is actually a copy of the code that is used to check username and group access, I simply modified it to make it work with IPs.

  1. On line 307 (or somewhere around that), change this:
          //we did this already
          //looks like there is something wrong with the ACL
          //break here
          return $perm;

    to this:

          //we did this already
          //looks like there is something wrong with the ACL
          //break here
          //return $perm;
          break;
  2. After this line (should be 310):
          }while(1); //this should never loop endless

    add the following code:

      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // IP ACL Mod - Max Khitrov <max@mxserve.net>
      // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
      // First we get the IP of the client
      $user_ip = $_SERVER[REMOTE_ADDR];
     
      // Take all ACL entries that begin with % and see if they can be matched to
      // the client's ip (exact match first, namespace second).
      $matches = preg_grep('/^'.$id.'\s+(%[0-9\.\/]+)\s+/',$AUTH_ACL);
      if(count($matches)){
        foreach($matches as $match){
        	$match = preg_replace('/#.*$/','',$match); //ignore comments
        	if ($match == '')
        		continue;
     
        	$acl = preg_split('/\s+/',$match);
        	$acl[1] = substr($acl[1], 1, strlen($acl[1]) - 1);
     
        	if (strpos($acl[1], '/') === false) {
        		// This is an exact IP entry, see if it matches the user IP
        		if ($user_ip == $acl[1])
        			$perm = $acl[2];
        	} else {
        		// This is a network entry
        		$ip = preg_split('/\//',$acl[1]);
     
        		if ((ip2long($user_ip) & ~(pow(2, 32-$ip[1])-1)) == (ip2long($ip[0]) & ~(pow(2, 32-$ip[1])-1)))
        			$perm = $acl[2];
        	}
     
        	if($perm > -1){
          	//we had a match - return it
          	return $perm;
        	}
        }
      }
     
      $ns    = getNS($id);
      if($ns){
        $path = $ns.':\*';
      }else{
        $path = '\*'; //root document
      }
     
      do{
        $matches = preg_grep('/^'.$path.'\s+(%[0-9\.\/]+)\s+/',$AUTH_ACL);
        if(count($matches)){
          foreach($matches as $match){
            $match = preg_replace('/#.*$/','',$match); //ignore comments
            if ($match == '')
        			continue;
     
            $acl   = preg_split('/\s+/',$match);
            if($acl[2] > AUTH_DELETE) $acl[2] = AUTH_DELETE; //no admins in the ACL!
     
            $acl[1] = substr($acl[1], 1, strlen($acl[1]) - 1);
     
    	    	if (strpos($acl[1], '/') === false) {
    	    		// This is an exact IP entry, see if it matches the user IP
    	    		if ($user_ip == $acl[1])
    	    			if($acl[2] > $perm)
    	    				$perm = $acl[2];
    	    	} else {
    	    		// This is a network entry
    	    		$ip = preg_split('/\//',$acl[1]);
     
    	    		if ((ip2long($user_ip) & ~(pow(2, 32-$ip[1])-1)) == (ip2long($ip[0]) & ~(pow(2, 32-$ip[1])-1)))
    	    			if($acl[2] > $perm)
    	    				$perm = $acl[2];
    	    	}
          }
          //we had a match - return it
          return $perm;
        }
     
        //get next higher namespace
        $ns   = getNS($ns);
     
        if($path != '\*'){
          $path = $ns.':\*';
          if($path == ':\*') $path = '\*';
        }else{
          //we did this already
          //looks like there is something wrong with the ACL
          //break here
          return $perm;
        }
      }while(1); //this should never loop endless
     
      // ~~~~~~~~~~~~~~
      // END IP ACL Mod
      // ~~~~~~~~~~~~~~

Install Instructions for the 2006-03-09b release

In function auth_aclcheck, around line 321, immediately following the «do{» line, insert the code shown below.

It's slightly tricky to set up the permissions, because the main loop is trying to validate your identity (typically «@ALL») and your IP address at the same time. The upshot is that to get wiki-wide access you have to specify your IP-based permissions in acl.auth.php for every namespace, not just «*». Otherwise, if you have something like:

somenamespace:*	@ALL	0

It will override something like:

*     %192.168.1.1 1  # This IP gets read access to the whole wiki

That means you won't get read access in «somenamespace», even if you're at IP 192.168.1.1.

Here's the code to insert after the «do{».

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // IP ACL Mod - Max Khitrov <max@mxserve.net>
  // Modified by Scott Gilbertson to work with a newer DokuWiki version
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // First we get the IP of the client
  $user_ip = $_SERVER[REMOTE_ADDR];
 
  // Take all ACL entries that begin with % and see if they can be matched to
  // the client's ip (exact match first, namespace second).
  $matches = preg_grep('/^'.$path.'\s+(%[0-9\.\/]+)\s+/',$AUTH_ACL);
  if(count($matches)){
    foreach($matches as $match){
    	$match = preg_replace('/#.*$/','',$match); //ignore comments
    	if ($match == '')
    		continue;
    	$acl = preg_split('/\s+/',$match);
    	$acl[1] = substr($acl[1], 1, strlen($acl[1]) - 1);
    	if (strpos($acl[1], '/') === false) {
    		// This is an exact IP entry, see if it matches the user IP
    		if ($user_ip == $acl[1]) {
    			$perm = $acl[2];
                }
    	} else {
    		// This is a network entry
    		$ip = preg_split('/\//',$acl[1]);
 
    		if ((ip2long($user_ip) & ~(pow(2, 32-$ip[1])-1)) == (ip2long($ip[0]) & ~(pow(2, 32-$ip[1])-1))) {
    			$perm = $acl[2];
                }
    	}
 
    	if($perm > -1){
      	//we had a match - return it
      	return $perm;
    	}
    }
  }
 
    $matches = preg_grep('/^'.$path.'\s+(%[0-9\.\/]+)\s+/',$AUTH_ACL);
    if(count($matches)){
      foreach($matches as $match){
        $match = preg_replace('/#.*$/','',$match); //ignore comments
        if ($match == '')
    			continue;
 
        $acl   = preg_split('/\s+/',$match);
        if($acl[2] > AUTH_DELETE) $acl[2] = AUTH_DELETE; //no admins in the ACL!
 
        $acl[1] = substr($acl[1], 1, strlen($acl[1]) - 1);
 
	    	if (strpos($acl[1], '/') === false) {
	    		// This is an exact IP entry, see if it matches the user IP
	    		if ($user_ip == $acl[1])
	    			if($acl[2] > $perm)
	    				$perm = $acl[2];
	    	} else {
	    		// This is a network entry
	    		$ip = preg_split('/\//',$acl[1]);
 
	    		if ((ip2long($user_ip) & ~(pow(2, 32-$ip[1])-1)) == (ip2long($ip[0]) & ~(pow(2,32-$ip[1])-1)))
	    			if($acl[2] > $perm)
	    				$perm = $acl[2];
	    	}
      }
      //we had a match - return it
      //return $perm;
    }
 
  // ~~~~~~~~~~~~~~
  // END IP ACL Mod
  // ~~~~~~~~~~~~~~

Another (simpler) approach

If you don't need netmask support, but you can live with simpler class-network granularity, this approach might work for you. Here, every user automatically is member of four additional groups, based on his IP address. If he accesses for example from IP 123.45.67.89, he is by default member of following groups as well:

  • ip:123
  • ip:123.45
  • ip:123.45.67
  • ip:123.45.67.89

This means, if you want to give rights (only) to users from Apple, you would use the ACL Plugin to set the rights for the group «ip:17

To patch the 2007-06-26 version of dokuwiki, replace the lines 363-372 of inc/auth.php with the following code:

  // --- patch to allow IP-Based access rights (replaces original lines 363-372) ----
  //add ALL group
  $groups[] = '@ALL';
  //add IP-based groups:
  $ip = explode('.',$_SERVER["REMOTE_ADDR"]);
  $groups[] = '@ip%3a' . $ip[0] . '%2e' . $ip[1] . '%2e' . $ip[2] . '%2e' . $ip[3]; # Full Address
  $groups[] = '@ip%3a' . $ip[0] . '%2e' . $ip[1] . '%2e' . $ip[2]; # Class C
  $groups[] = '@ip%3a' . $ip[0] . '%2e' . $ip[1]; # Class B
  $groups[] = '@ip%3a' . $ip[0]; # Class A
  if ($user){
    //add User
    $groups[] = $user;
  }
  //build regexp
  $regexp   = join('|',$groups);
  // --- End of Patch  ----

Please mail emarks, suggestions etc. to bihler [at] iai [dot] uni [dash] bonn [dot] de.

ru/tips/ipacl.txt · Последнее изменение: 2009-12-03 15:32 — 93.91.4.119

Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki