Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/impl/sql/conn/GenericAuthorizer.java


1   /*
2   
3      Derby - Class org.apache.derby.impl.sql.conn.GenericAuthorizer
4   
5      Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.impl.sql.conn;
22  
23  import org.apache.derby.iapi.reference.Property;
24  import org.apache.derby.iapi.util.IdUtil;
25  import org.apache.derby.iapi.util.StringUtil;
26  import org.apache.derby.iapi.services.sanity.SanityManager;
27  import org.apache.derby.iapi.error.StandardException;
28  import org.apache.derby.iapi.sql.conn.Authorizer;
29  import org.apache.derby.iapi.reference.SQLState;
30  import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
31  import org.apache.derby.iapi.services.property.PropertyUtil;
32  import org.apache.derby.iapi.services.property.PersistentSet;
33  import org.apache.derby.catalog.types.RoutineAliasInfo;
34  import java.util.Properties;
35  
36  class GenericAuthorizer
37  implements Authorizer
38  {
39    //
40    //Enumerations for user access levels.
41    private static final int NO_ACCESS = 0;
42    private static final int READ_ACCESS = 1;
43    private static final int FULL_ACCESS = 2;
44    
45    //
46    //Configurable userAccessLevel - derived from Database level
47    //access control lists + database boot time controls.
48    private int userAccessLevel;
49  
50    //
51    //Connection's readOnly status
52      boolean readOnlyConnection;
53  
54    private final LanguageConnectionContext lcc;
55    
56    private final String authorizationId; //the userName after parsing by IdUtil 
57    
58    GenericAuthorizer(String authorizationId, 
59                   LanguageConnectionContext lcc,
60                     boolean sqlConnection)
61       throws StandardException
62    {
63      this.lcc = lcc;
64      this.authorizationId = authorizationId;
65  
66      //we check the access level only if this is coming from a sql
67      //connection, not internal logSniffer or StageTrunc db connection
68      if(sqlConnection)
69        refresh();
70    }
71  
72    /*
73      Return true if the connection must remain readOnly
74      */
75    private boolean connectionMustRemainReadOnly()
76    {
77      if (lcc.getDatabase().isReadOnly() ||
78        (userAccessLevel==READ_ACCESS))
79        return true;
80      else
81        return false;
82    }
83  
84    /**
85      @see Authorizer#authorize
86      @exception StandardException Thrown if the operation is not allowed
87     */
88    public void authorize(int operation) throws StandardException
89    {
90      int sqlAllowed = lcc.getStatementContext().getSQLAllowed();
91  
92      switch (operation)
93      {
94      case Authorizer.SQL_ARBITARY_OP:
95      case Authorizer.SQL_CALL_OP:
96        if (sqlAllowed == RoutineAliasInfo.NO_SQL)
97          throw externalRoutineException(operation, sqlAllowed);
98        break;
99      case Authorizer.SQL_SELECT_OP:
100       if (sqlAllowed > RoutineAliasInfo.READS_SQL_DATA)
101         throw externalRoutineException(operation, sqlAllowed);
102       break;
103 
104     // SQL write operations
105     case Authorizer.SQL_WRITE_OP:
106     case Authorizer.PROPERTY_WRITE_OP:
107       if (isReadOnlyConnection())
108         throw StandardException.newException(SQLState.AUTH_WRITE_WITH_READ_ONLY_CONNECTION);
109       if (sqlAllowed > RoutineAliasInfo.MODIFIES_SQL_DATA)
110         throw externalRoutineException(operation, sqlAllowed);
111       break;
112 
113     // SQL DDL operations
114     case Authorizer.JAR_WRITE_OP:
115     case Authorizer.SQL_DDL_OP:
116        if (isReadOnlyConnection())
117         throw StandardException.newException(SQLState.AUTH_DDL_WITH_READ_ONLY_CONNECTION);
118 
119       if (sqlAllowed > RoutineAliasInfo.MODIFIES_SQL_DATA)
120         throw externalRoutineException(operation, sqlAllowed);
121       break;
122 
123     default:
124       if (SanityManager.DEBUG)
125         SanityManager.THROWASSERT("Bad operation code "+operation);
126     }
127   }
128 
129   private static StandardException externalRoutineException(int operation, int sqlAllowed) {
130 
131     String sqlState;
132     if (sqlAllowed == RoutineAliasInfo.READS_SQL_DATA)
133       sqlState = SQLState.EXTERNAL_ROUTINE_NO_MODIFIES_SQL;
134     else if (sqlAllowed == RoutineAliasInfo.CONTAINS_SQL)
135     {
136       switch (operation)
137       {
138       case Authorizer.SQL_WRITE_OP:
139       case Authorizer.PROPERTY_WRITE_OP:
140       case Authorizer.JAR_WRITE_OP:
141       case Authorizer.SQL_DDL_OP:
142         sqlState = SQLState.EXTERNAL_ROUTINE_NO_MODIFIES_SQL;
143         break;
144       default:
145         sqlState = SQLState.EXTERNAL_ROUTINE_NO_READS_SQL;
146         break;
147       }
148     }
149     else
150       sqlState = SQLState.EXTERNAL_ROUTINE_NO_SQL;
151 
152     return StandardException.newException(sqlState);
153   }
154   
155 
156   /**
157     @see Authorizer#getAuthorizationId
158     */
159   public String getAuthorizationId()
160   {
161     return authorizationId;
162   }
163 
164   private void getUserAccessLevel() throws StandardException
165   {
166     userAccessLevel = NO_ACCESS;
167     if (userOnAccessList(Property.FULL_ACCESS_USERS_PROPERTY))
168       userAccessLevel = FULL_ACCESS;
169 
170     if (userAccessLevel == NO_ACCESS &&
171       userOnAccessList(Property.READ_ONLY_ACCESS_USERS_PROPERTY))
172       userAccessLevel = READ_ACCESS;
173 
174     if (userAccessLevel == NO_ACCESS)
175       userAccessLevel = getDefaultAccessLevel();
176   }
177 
178   private int getDefaultAccessLevel() throws StandardException
179   {
180     PersistentSet tc = lcc.getTransactionExecute();
181     String modeS = (String)
182       PropertyUtil.getServiceProperty(
183                   tc,
184                   Property.DEFAULT_CONNECTION_MODE_PROPERTY);
185     if (modeS == null)
186       return FULL_ACCESS;
187     else if(StringUtil.SQLEqualsIgnoreCase(modeS, Property.NO_ACCESS))
188       return NO_ACCESS;
189     else if(StringUtil.SQLEqualsIgnoreCase(modeS, Property.READ_ONLY_ACCESS))
190       return READ_ACCESS;
191     else if(StringUtil.SQLEqualsIgnoreCase(modeS, Property.FULL_ACCESS))
192       return FULL_ACCESS;
193     else
194     {
195       if (SanityManager.DEBUG)
196         SanityManager.THROWASSERT("Invalid value for property "+
197                       Property.DEFAULT_CONNECTION_MODE_PROPERTY+
198                       " "+
199                       modeS);
200        return FULL_ACCESS;
201     }
202   }
203 
204   private boolean userOnAccessList(String listName) throws StandardException
205   {
206     PersistentSet tc = lcc.getTransactionExecute();
207     String listS = (String)
208       PropertyUtil.getServiceProperty(tc, listName);
209     return IdUtil.idOnList(authorizationId,listS);
210   }
211 
212   /**
213     @see Authorizer#isReadOnlyConnection
214    */
215   public boolean isReadOnlyConnection()
216   {
217     return readOnlyConnection;
218   }
219 
220   /**
221     @see Authorizer#isReadOnlyConnection
222     @exception StandardException Thrown if the operation is not allowed
223    */
224   public void setReadOnlyConnection(boolean on, boolean authorize)
225      throws StandardException
226   {
227     if (authorize && !on) {
228       if (connectionMustRemainReadOnly())
229         throw StandardException.newException(SQLState.AUTH_CANNOT_SET_READ_WRITE);
230     }
231     readOnlyConnection = on;
232   }
233 
234   /**
235     @see Authorizer#refresh
236     @exception StandardException Thrown if the operation is not allowed
237     */
238   public void refresh() throws StandardException
239   {
240     getUserAccessLevel();
241     if (!readOnlyConnection)
242       readOnlyConnection = connectionMustRemainReadOnly();
243 
244     // Is a connection allowed.
245     if (userAccessLevel == NO_ACCESS)
246       throw StandardException.newException(SQLState.AUTH_DATABASE_CONNECTION_REFUSED);
247   }
248 }