View Javadoc

1   // ========================================================================
2   // Authors : Van den Broeke Iris, Deville Daniel, Dubois Roger, Greg Wilkins
3   // Copyright (c) 2001 Deville Daniel. All rights reserved.
4   // Permission to use, copy, modify and distribute this software
5   // for non-commercial or commercial purposes and without fee is
6   // hereby granted provided that this copyright notice appears in
7   // all copies.
8   // ========================================================================
9   
10  package org.mortbay.jetty.security;
11  
12  import java.io.BufferedReader;
13  import java.io.IOException;
14  import java.io.InputStreamReader;
15  import java.net.InetAddress;
16  import java.net.UnknownHostException;
17  import java.security.Principal;
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.HashSet;
21  import java.util.Map;
22  import java.util.StringTokenizer;
23  
24  import javax.servlet.ServletException;
25  import javax.servlet.http.HttpServletRequest;
26  import javax.servlet.http.HttpServletResponse;
27  
28  import org.mortbay.jetty.Handler;
29  import org.mortbay.jetty.HttpConnection;
30  import org.mortbay.jetty.HttpHeaders;
31  import org.mortbay.jetty.Request;
32  import org.mortbay.jetty.Response;
33  import org.mortbay.jetty.handler.ContextHandler;
34  import org.mortbay.log.Log;
35  import org.mortbay.log.Logger;
36  import org.mortbay.resource.Resource;
37  import org.mortbay.util.StringUtil;
38  import org.mortbay.util.URIUtil;
39  
40  /* ------------------------------------------------------------ */
41  /**
42   * Handler to authenticate access using the Apache's .htaccess files.
43   * 
44   * @author Van den Broeke Iris
45   * @author Deville Daniel
46   * @author Dubois Roger
47   * @author Greg Wilkins
48   * @author Konstantin Metlov
49   * 
50   */
51  public class HTAccessHandler extends SecurityHandler
52  {
53      private Handler protegee;
54      private static Logger log=Log.getLogger(HTAccessHandler.class.getName());
55  
56      String _default=null;
57      String _accessFile=".htaccess";
58  
59      transient HashMap _htCache=new HashMap();
60      
61      /**
62       * DummyPrincipal
63       *
64       * For use when there is no user realm configured.
65       */
66      class DummyPrincipal implements Principal
67      {
68          private String _userName;
69  
70          public DummyPrincipal(String name) 
71          {
72              _userName=name;
73          }
74  
75          public String getName()
76          {
77              return _userName;
78          }
79  
80          public String toString()
81          {
82              return getName();
83          }        
84      }
85  
86  
87      /* ------------------------------------------------------------ */
88      /**
89       * {@inheritDoc}
90       * 
91       * @see org.mortbay.jetty.Handler#handle(java.lang.String,
92       *      javax.servlet.http.HttpServletRequest,
93       *      javax.servlet.http.HttpServletResponse, int)
94       */
95      public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
96      {
97          Request base_request=(request instanceof Request)?(Request)request:HttpConnection.getCurrentConnection().getRequest();
98          Response base_response=(response instanceof Response)?(Response)response:HttpConnection.getCurrentConnection().getResponse();
99  
100         String pathInContext=target;
101 
102         String user=null;
103         String password=null;
104         boolean IPValid=true;
105 
106         if (log.isDebugEnabled())
107             log.debug("HTAccessHandler pathInContext="+pathInContext,null,null);
108 
109         String credentials=request.getHeader(HttpHeaders.AUTHORIZATION);
110 
111         if (credentials!=null)
112         {
113             credentials=credentials.substring(credentials.indexOf(' ')+1);
114             credentials=B64Code.decode(credentials,StringUtil.__ISO_8859_1);
115             int i=credentials.indexOf(':');
116             user=credentials.substring(0,i);
117             password=credentials.substring(i+1);
118 
119             if (log.isDebugEnabled())
120                 log.debug("User="+user+", password="+"******************************".substring(0,password.length()),null,null);
121         }
122 
123         HTAccess ht=null;
124 
125         try
126         {
127             Resource resource=null;
128             String directory=pathInContext.endsWith("/")?pathInContext:URIUtil.parentPath(pathInContext);
129 
130             // Look for htAccess resource
131             while (directory!=null)
132             {
133                 String htPath=directory+_accessFile;
134                 resource=((ContextHandler)getProtegee()).getResource(htPath);
135                 if (log.isDebugEnabled())
136                     log.debug("directory="+directory+" resource="+resource,null,null);
137 
138                 if (resource!=null&&resource.exists()&&!resource.isDirectory())
139                     break;
140                 resource=null;
141                 directory=URIUtil.parentPath(directory);
142             }
143 
144             boolean haveHtAccess=true;
145 
146             // Try default directory
147             if (resource==null&&_default!=null)
148             {
149                 resource=Resource.newResource(_default);
150                 if (!resource.exists()||resource.isDirectory())
151                     haveHtAccess=false;
152             }
153             if (resource==null)
154                 haveHtAccess=false;
155 
156             // prevent access to htaccess files
157             if (pathInContext.endsWith(_accessFile)
158                 // extra security
159                 ||pathInContext.endsWith(_accessFile+"~")||pathInContext.endsWith(_accessFile+".bak"))
160             {
161                 response.sendError(HttpServletResponse.SC_FORBIDDEN);
162                 base_request.setHandled(true);
163                 return;
164             }
165 
166             if (haveHtAccess)
167             {
168                 if (log.isDebugEnabled())
169                     log.debug("HTACCESS="+resource,null,null);
170 
171                 ht=(HTAccess)_htCache.get(resource);
172                 if (ht==null||ht.getLastModified()!=resource.lastModified())
173                 {
174                     ht=new HTAccess(resource);
175                     _htCache.put(resource,ht);
176                     if (log.isDebugEnabled())
177                         log.debug("HTCache loaded "+ht,null,null);
178                 }
179 
180                 // See if there is a config problem
181                 if (ht.isForbidden())
182                 {
183                     log.warn("Mis-configured htaccess: "+ht,null,null);
184                     response.sendError(HttpServletResponse.SC_FORBIDDEN);
185                     base_request.setHandled(true);
186                     return;
187                 }
188 
189                 // first see if we need to handle based on method type
190                 Map methods=ht.getMethods();
191                 if (methods.size()>0&&!methods.containsKey(request.getMethod()))
192                 {
193                     callWrappedHandler(target,request,response,dispatch);
194                     return; // Nothing to check
195                 }
196 
197                 // Check the accesss
198                 int satisfy=ht.getSatisfy();
199 
200                 // second check IP address
201                 IPValid=ht.checkAccess("",request.getRemoteAddr());
202                 if (log.isDebugEnabled())
203                     log.debug("IPValid = "+IPValid,null,null);
204 
205                 // If IP is correct and satify is ANY then access is allowed
206                 if (IPValid==true&&satisfy==HTAccess.ANY)
207                 {
208                     callWrappedHandler(target,request,response,dispatch);
209                     return;
210                 }
211                 
212                 // If IP is NOT correct and satify is ALL then access is
213                 // forbidden
214                 if (IPValid==false&&satisfy==HTAccess.ALL)
215                 {
216                     response.sendError(HttpServletResponse.SC_FORBIDDEN);
217                     base_request.setHandled(true);
218                     return;
219                 }
220 
221                 // set required page
222                 if (!ht.checkAuth(user,password,getUserRealm(),base_request))
223                 {
224                     log.debug("Auth Failed",null,null);
225                     response.setHeader(HttpHeaders.WWW_AUTHENTICATE,"basic realm="+ht.getName());
226                     response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
227                     base_response.complete();
228                     base_request.setHandled(true);
229                     return;
230                 }
231 
232                 // set user
233                 if (user!=null)
234                 {
235                     base_request.setAuthType(Constraint.__BASIC_AUTH);
236                     base_request.setUserPrincipal(getPrincipal(user, getUserRealm()));
237                 }
238             }
239             
240             callWrappedHandler(target,request,response,dispatch);
241         }
242         catch (Exception ex)
243         {
244             log.warn("Exception",ex);
245             if (ht!=null)
246             {
247                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
248                 base_request.setHandled(true);
249             }
250         }
251     }
252     
253     /* ------------------------------------------------------------ */
254     /**
255      */
256     private void callWrappedHandler(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
257     {
258     	Handler handler=getHandler();
259         if (handler!=null)
260             handler.handle(target,request,response,dispatch);
261     }
262 
263     /* ------------------------------------------------------------ */
264     /** Get a Principal matching the user.
265      * If there is no user realm, and therefore we are using a
266      * htpassword file instead, then just return a dummy Principal.
267      * @param user
268      * @param realm
269      * @return
270      */
271     public Principal getPrincipal (String user, UserRealm realm)
272     {
273         if (realm==null)
274             return new DummyPrincipal(user);
275         
276         return realm.getPrincipal(user);
277     }
278     /* ------------------------------------------------------------ */
279     /**
280      * set functions for the following .xml administration statements.
281      * 
282      * <Call name="addHandler"> <Arg> <New
283      * class="org.mortbay.http.handler.HTAccessHandler"> <Set
284      * name="Default">./etc/htaccess</Set> <Set name="AccessFile">.htaccess</Set>
285      * </New> </Arg> </Call>
286      * 
287      */
288     public void setDefault(String dir)
289     {
290         _default=dir;
291     }
292 
293     /* ------------------------------------------------------------ */
294     public void setAccessFile(String anArg)
295     {
296         if (anArg==null)
297             _accessFile=".htaccess";
298         else
299             _accessFile=anArg;
300     }
301 
302     /* ------------------------------------------------------------ */
303     /* ------------------------------------------------------------ */
304     /* ------------------------------------------------------------ */
305     private static class HTAccess
306     {
307         // private boolean _debug = false;
308         static final int ANY=0;
309         static final int ALL=1;
310         static final String USER="user";
311         static final String GROUP="group";
312         static final String VALID_USER="valid-user";
313 
314         /* ------------------------------------------------------------ */
315         String _userFile;
316         Resource _userResource;
317         HashMap _users=null;
318         long _userModified;
319 
320         /* ------------------------------------------------------------ */
321         String _groupFile;
322         Resource _groupResource;
323         HashMap _groups=null;
324         long _groupModified;
325 
326         int _satisfy=0;
327         String _type;
328         String _name;
329         HashMap _methods=new HashMap();
330         HashSet _requireEntities=new HashSet();
331         String _requireName;
332         int _order;
333         ArrayList _allowList=new ArrayList();
334         ArrayList _denyList=new ArrayList();
335         long _lastModified;
336         boolean _forbidden=false;
337 
338         /* ------------------------------------------------------------ */
339         public HTAccess(Resource resource)
340         {
341             BufferedReader htin=null;
342             try
343             {
344                 htin=new BufferedReader(new InputStreamReader(resource.getInputStream()));
345                 parse(htin);
346                 _lastModified=resource.lastModified();
347 
348                 if (_userFile!=null)
349                 {
350                     _userResource=Resource.newResource(_userFile);
351                     if (!_userResource.exists())
352                     {
353                         _forbidden=true;
354                         log.warn("Could not find ht user file: "+_userFile,null,null);
355                     }
356                     else if (log.isDebugEnabled())
357                         log.debug("user file: "+_userResource,null,null);
358                 }
359 
360                 if (_groupFile!=null)
361                 {
362                     _groupResource=Resource.newResource(_groupFile);
363                     if (!_groupResource.exists())
364                     {
365                         _forbidden=true;
366                         log.warn("Could not find ht group file: "+_groupResource,null,null);
367                     }
368                     else if (log.isDebugEnabled())
369                         log.debug("group file: "+_groupResource,null,null);
370                 }
371             }
372             catch (IOException e)
373             {
374                 _forbidden=true;
375                 log.warn("LogSupport.EXCEPTION",e);
376             }
377         }
378 
379         /* ------------------------------------------------------------ */
380         public boolean isForbidden()
381         {
382             return _forbidden;
383         }
384 
385         /* ------------------------------------------------------------ */
386         public HashMap getMethods()
387         {
388             return _methods;
389         }
390 
391         /* ------------------------------------------------------------ */
392         public long getLastModified()
393         {
394             return _lastModified;
395         }
396 
397         /* ------------------------------------------------------------ */
398         public Resource getUserResource()
399         {
400             return _userResource;
401         }
402 
403         /* ------------------------------------------------------------ */
404         public Resource getGroupResource()
405         {
406             return _groupResource;
407         }
408 
409         /* ------------------------------------------------------------ */
410         public int getSatisfy()
411         {
412             return (_satisfy);
413         }
414 
415         /* ------------------------------------------------------------ */
416         public String getName()
417         {
418             return _name;
419         }
420 
421         /* ------------------------------------------------------------ */
422         public String getType()
423         {
424             return _type;
425         }
426 
427         /* ------------------------------------------------------------ */
428         public boolean checkAccess(String host, String ip)
429         {
430             String elm;
431             boolean alp=false;
432             boolean dep=false;
433 
434             // if no allows and no deny defined, then return true
435             if (_allowList.size()==0&&_denyList.size()==0)
436                 return (true);
437 
438             // looping for allows
439             for (int i=0; i<_allowList.size(); i++)
440             {
441                 elm=(String)_allowList.get(i);
442                 if (elm.equals("all"))
443                 {
444                     alp=true;
445                     break;
446                 }
447                 else
448                 {
449                     char c=elm.charAt(0);
450                     if (c>='0'&&c<='9')
451                     {
452                         // ip
453                         if (ip.startsWith(elm))
454                         {
455                             alp=true;
456                             break;
457                         }
458                     }
459                     else
460                     {
461                         // hostname
462                         if (host.endsWith(elm))
463                         {
464                             alp=true;
465                             break;
466                         }
467                     }
468                 }
469             }
470 
471             // looping for denies
472             for (int i=0; i<_denyList.size(); i++)
473             {
474                 elm=(String)_denyList.get(i);
475                 if (elm.equals("all"))
476                 {
477                     dep=true;
478                     break;
479                 }
480                 else
481                 {
482                     char c=elm.charAt(0);
483                     if (c>='0'&&c<='9')
484                     { // ip
485                         if (ip.startsWith(elm))
486                         {
487                             dep=true;
488                             break;
489                         }
490                     }
491                     else
492                     { // hostname
493                         if (host.endsWith(elm))
494                         {
495                             dep=true;
496                             break;
497                         }
498                     }
499                 }
500             }
501 
502             if (_order<0) // deny,allow
503                 return !dep||alp;
504             // mutual failure == allow,deny
505             return alp&&!dep;
506         }
507 
508         /* ------------------------------------------------------------ */
509         public boolean checkAuth(String user, String pass, UserRealm realm, Request request)
510         {
511             if (_requireName==null)
512                 return true;
513 
514             // Authenticate with realm
515 
516             Principal principal=realm==null?null:realm.authenticate(user,pass,request);
517             if (principal==null)
518             {
519                 // Have to authenticate the user with the password file
520                 String code=getUserCode(user);
521                 String salt=code!=null?code.substring(0,2):user;
522                 String cred=(user!=null&&pass!=null)?UnixCrypt.crypt(pass,salt):null;
523                 if (code==null||(code.equals("")&&!pass.equals(""))||!code.equals(cred))
524                     return false;
525             }
526 
527             if (_requireName.equalsIgnoreCase(USER))
528             {
529                 if (_requireEntities.contains(user))
530                     return true;
531             }
532             else if (_requireName.equalsIgnoreCase(GROUP))
533             {
534                 ArrayList gps=getUserGroups(user);
535                 if (gps!=null)
536                     for (int g=gps.size(); g-->0;)
537                         if (_requireEntities.contains(gps.get(g)))
538                             return true;
539             }
540             else if (_requireName.equalsIgnoreCase(VALID_USER))
541             {
542                 return true;
543             }
544 
545             return false;
546         }
547 
548         /* ------------------------------------------------------------ */
549         public boolean isAccessLimited()
550         {
551             if (_allowList.size()>0||_denyList.size()>0)
552                 return true;
553             else
554                 return false;
555         }
556 
557         /* ------------------------------------------------------------ */
558         public boolean isAuthLimited()
559         {
560             if (_requireName!=null)
561                 return true;
562             else
563                 return false;
564         }
565 
566         /* ------------------------------------------------------------ */
567         private String getUserCode(String user)
568         {
569             if (_userResource==null)
570                 return null;
571 
572             if (_users==null||_userModified!=_userResource.lastModified())
573             {
574                 if (log.isDebugEnabled())
575                     log.debug("LOAD "+_userResource,null,null);
576                 _users=new HashMap();
577                 BufferedReader ufin=null;
578                 try
579                 {
580                     ufin=new BufferedReader(new InputStreamReader(_userResource.getInputStream()));
581                     _userModified=_userResource.lastModified();
582                     String line;
583                     while ((line=ufin.readLine())!=null)
584                     {
585                         line=line.trim();
586                         if (line.startsWith("#"))
587                             continue;
588                         int spos=line.indexOf(':');
589                         if (spos<0)
590                             continue;
591                         String u=line.substring(0,spos).trim();
592                         String p=line.substring(spos+1).trim();
593                         _users.put(u,p);
594                     }
595                 }
596                 catch (IOException e)
597                 {
598                     log.warn("LogSupport.EXCEPTION",e);
599                 }
600                 finally
601                 {
602                     try
603                     {
604                         if (ufin!=null)
605                             ufin.close();
606                     }
607                     catch (IOException e2)
608                     {
609                         log.warn("LogSupport.EXCEPTION",e2);
610                     }
611                 }
612             }
613 
614             return (String)_users.get(user);
615         }
616 
617         /* ------------------------------------------------------------ */
618         private ArrayList getUserGroups(String group)
619         {
620             if (_groupResource==null)
621                 return null;
622 
623             if (_groups==null||_groupModified!=_groupResource.lastModified())
624             {
625                 if (log.isDebugEnabled())
626                     log.debug("LOAD "+_groupResource,null,null);
627 
628                 _groups=new HashMap();
629                 BufferedReader ufin=null;
630                 try
631                 {
632                     ufin=new BufferedReader(new InputStreamReader(_groupResource.getInputStream()));
633                     _groupModified=_groupResource.lastModified();
634                     String line;
635                     while ((line=ufin.readLine())!=null)
636                     {
637                         line=line.trim();
638                         if (line.startsWith("#")||line.length()==0)
639                             continue;
640 
641                         StringTokenizer tok=new StringTokenizer(line,": \t");
642 
643                         if (!tok.hasMoreTokens())
644                             continue;
645                         String g=tok.nextToken();
646                         if (!tok.hasMoreTokens())
647                             continue;
648                         while (tok.hasMoreTokens())
649                         {
650                             String u=tok.nextToken();
651                             ArrayList gl=(ArrayList)_groups.get(u);
652                             if (gl==null)
653                             {
654                                 gl=new ArrayList();
655                                 _groups.put(u,gl);
656                             }
657                             gl.add(g);
658                         }
659                     }
660                 }
661                 catch (IOException e)
662                 {
663                     log.warn("LogSupport.EXCEPTION",e);
664                 }
665                 finally
666                 {
667                     try
668                     {
669                         if (ufin!=null)
670                             ufin.close();
671                     }
672                     catch (IOException e2)
673                     {
674                         log.warn("LogSupport.EXCEPTION",e2);
675                     }
676                 }
677             }
678 
679             return (ArrayList)_groups.get(group);
680         }
681 
682         /* ------------------------------------------------------------ */
683         public String toString()
684         {
685             StringBuffer buf=new StringBuffer();
686 
687             buf.append("AuthUserFile=");
688             buf.append(_userFile);
689             buf.append(", AuthGroupFile=");
690             buf.append(_groupFile);
691             buf.append(", AuthName=");
692             buf.append(_name);
693             buf.append(", AuthType=");
694             buf.append(_type);
695             buf.append(", Methods=");
696             buf.append(_methods);
697             buf.append(", satisfy=");
698             buf.append(_satisfy);
699             if (_order<0)
700                 buf.append(", order=deny,allow");
701             else if (_order>0)
702                 buf.append(", order=allow,deny");
703             else
704                 buf.append(", order=mutual-failure");
705 
706             buf.append(", Allow from=");
707             buf.append(_allowList);
708             buf.append(", deny from=");
709             buf.append(_denyList);
710             buf.append(", requireName=");
711             buf.append(_requireName);
712             buf.append(" ");
713             buf.append(_requireEntities);
714 
715             return buf.toString();
716         }
717 
718         /* ------------------------------------------------------------ */
719         private void parse(BufferedReader htin) throws IOException
720         {
721             String line;
722             while ((line=htin.readLine())!=null)
723             {
724                 line=line.trim();
725                 if (line.startsWith("#"))
726                     continue;
727                 else if (line.startsWith("AuthUserFile"))
728                 {
729                     _userFile=line.substring(13).trim();
730                 }
731                 else if (line.startsWith("AuthGroupFile"))
732                 {
733                     _groupFile=line.substring(14).trim();
734                 }
735                 else if (line.startsWith("AuthName"))
736                 {
737                     _name=line.substring(8).trim();
738                 }
739                 else if (line.startsWith("AuthType"))
740                 {
741                     _type=line.substring(8).trim();
742                 }
743                 // else if (line.startsWith("<Limit")) {
744                 else if (line.startsWith("<Limit"))
745                 {
746                     int limit=line.length();
747                     int endp=line.indexOf('>');
748                     StringTokenizer tkns;
749 
750                     if (endp<0)
751                         endp=limit;
752                     tkns=new StringTokenizer(line.substring(6,endp));
753                     while (tkns.hasMoreTokens())
754                     {
755                         _methods.put(tkns.nextToken(),Boolean.TRUE);
756                     }
757 
758                     while ((line=htin.readLine())!=null)
759                     {
760                         line=line.trim();
761                         if (line.startsWith("#"))
762                             continue;
763                         else if (line.startsWith("satisfy"))
764                         {
765                             int pos1=7;
766                             limit=line.length();
767                             while ((pos1<limit)&&(line.charAt(pos1)<=' '))
768                                 pos1++;
769                             int pos2=pos1;
770                             while ((pos2<limit)&&(line.charAt(pos2)>' '))
771                                 pos2++;
772                             String l_string=line.substring(pos1,pos2);
773                             if (l_string.equals("all"))
774                                 _satisfy=1;
775                             else if (l_string.equals("any"))
776                                 _satisfy=0;
777                         }
778                         else if (line.startsWith("require"))
779                         {
780                             int pos1=7;
781                             limit=line.length();
782                             while ((pos1<limit)&&(line.charAt(pos1)<=' '))
783                                 pos1++;
784                             int pos2=pos1;
785                             while ((pos2<limit)&&(line.charAt(pos2)>' '))
786                                 pos2++;
787                             _requireName=line.substring(pos1,pos2).toLowerCase();
788                             if (USER.equals(_requireName))
789                                 _requireName=USER;
790                             else if (GROUP.equals(_requireName))
791                                 _requireName=GROUP;
792                             else if (VALID_USER.equals(_requireName))
793                                 _requireName=VALID_USER;
794 
795                             pos1=pos2+1;
796                             if (pos1<limit)
797                             {
798                                 while ((pos1<limit)&&(line.charAt(pos1)<=' '))
799                                     pos1++;
800 
801                                 tkns=new StringTokenizer(line.substring(pos1));
802                                 while (tkns.hasMoreTokens())
803                                 {
804                                     _requireEntities.add(tkns.nextToken());
805                                 }
806                             }
807 
808                         }
809                         else if (line.startsWith("order"))
810                         {
811                             if (log.isDebugEnabled())
812                                 log.debug("orderline="+line+"order="+_order,null,null);
813                             if (line.indexOf("allow,deny")>0)
814                             {
815                                 log.debug("==>allow+deny",null,null);
816                                 _order=1;
817                             }
818                             else if (line.indexOf("deny,allow")>0)
819                             {
820                                 log.debug("==>deny,allow",null,null);
821                                 _order=-1;
822                             }
823                             else if (line.indexOf("mutual-failure")>0)
824                             {
825                                 log.debug("==>mutual",null,null);
826                                 _order=0;
827                             }
828                             else
829                             {
830                             }
831                         }
832                         else if (line.startsWith("allow from"))
833                         {
834                             int pos1=10;
835                             limit=line.length();
836                             while ((pos1<limit)&&(line.charAt(pos1)<=' '))
837                                 pos1++;
838                             if (log.isDebugEnabled())
839                                 log.debug("allow process:"+line.substring(pos1),null,null);
840                             tkns=new StringTokenizer(line.substring(pos1));
841                             while (tkns.hasMoreTokens())
842                             {
843                                 _allowList.add(tkns.nextToken());
844                             }
845                         }
846                         else if (line.startsWith("deny from"))
847                         {
848                             int pos1=9;
849                             limit=line.length();
850                             while ((pos1<limit)&&(line.charAt(pos1)<=' '))
851                                 pos1++;
852                             if (log.isDebugEnabled())
853                                 log.debug("deny process:"+line.substring(pos1),null,null);
854 
855                             tkns=new StringTokenizer(line.substring(pos1));
856                             while (tkns.hasMoreTokens())
857                             {
858                                 _denyList.add(tkns.nextToken());
859                             }
860                         }
861                         else if (line.startsWith("</Limit>"))
862                             break;
863                     }
864                 }
865             }
866         }
867     }
868 
869     /**
870      * Getter for property protegee.
871      * 
872      * @return Returns the protegee.
873      */
874     protected Handler getProtegee()
875     {
876         return this.protegee;
877     }
878 
879     /**
880      * Setter for property protegee.
881      * 
882      * @param protegee
883      *            The protegee to set.
884      */
885     public void setProtegee(Handler protegee)
886     {
887         this.protegee=protegee;
888     }
889 
890 }