~ubuntu-branches/ubuntu/oneiric/apparmor/oneiric-security

« back to all changes in this revision

Viewing changes to changehat/tomcat_apparmor/tomcat_5_5/src/com/novell/apparmor/catalina/valves/ChangeHatValve.java

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2011-04-27 10:38:07 UTC
  • mfrom: (5.1.118 natty)
  • Revision ID: james.westby@ubuntu.com-20110427103807-ym3rhwys6o84ith0
Tags: 2.6.1-2
debian/copyright: clarify for some full organization names.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ------------------------------------------------------------------
 
2
 *
 
3
 *    Copyright (C) 2002-2007 Novell/SUSE
 
4
 *
 
5
 *   This program is free software; you can redistribute it and/or
 
6
 *   modify it under the terms of version 2 of the GNU General Public
 
7
 *    License published by the Free Software Foundation.
 
8
 *
 
9
 * ------------------------------------------------------------------ */
 
10
 
 
11
package com.novell.apparmor.catalina.valves;
 
12
 
 
13
import com.novell.apparmor.JNIChangeHat;
 
14
import java.io.IOException;
 
15
import javax.servlet.ServletException;
 
16
import org.apache.catalina.Container;
 
17
import org.apache.catalina.valves.ValveBase;
 
18
import java.security.SecureRandom;
 
19
 
 
20
 
 
21
public final class ChangeHatValve extends ValveBase {
 
22
    // JNI interface class for AppArmor change_hat
 
23
    private static JNIChangeHat changehat_wrapper = new JNIChangeHat();
 
24
    private static SecureRandom randomNumberGenerator = null;
 
25
    private static String DEFAULT_HAT = "DEFAULT";
 
26
    private static int SERVLET_PATH_MEDIATION = 0;
 
27
    private static int URI_MEDIATION = 1;
 
28
 
 
29
    private int mediationType = ChangeHatValve.SERVLET_PATH_MEDIATION;
 
30
 
 
31
    /*
 
32
     *
 
33
     *  Property setter called during the parsing of the server.xml.
 
34
     *  If the <code>mediationType</code> is an attribute of the
 
35
     *  Valve definition for
 
36
     *  <code>com.novell.apparmor.catalina.valves.ChangeHatValve</code>
 
37
     *  then this setter will be called to set the value for this property.
 
38
     *
 
39
     *  @param type <b>URI|ServletPath<b>
 
40
     *
 
41
     *  Controls what granularity of security confinement when used with
 
42
     *  AppArmor change_hat(2). Either based upon <code>getServletPath()</code>
 
43
     *  or  <code>getRequestURI()</code> called against on the request.
 
44
     *
 
45
     */
 
46
    public void setMediationType( String type ) {
 
47
        if ( type.equalsIgnoreCase("URI") ) {
 
48
            this.mediationType = ChangeHatValve.URI_MEDIATION;
 
49
        } else if ( type.equalsIgnoreCase("servletPath") ) {
 
50
            this.mediationType = ChangeHatValve.SERVLET_PATH_MEDIATION;
 
51
        }
 
52
    }
 
53
 
 
54
    /*
 
55
     *
 
56
     * Return an int value representing the currently configured
 
57
     * <code>mediationType</code> for this instance.
 
58
     *
 
59
     */
 
60
    public int getMediationType() {
 
61
        return this.mediationType;
 
62
    }
 
63
 
 
64
 
 
65
    /*
 
66
     *
 
67
     * Return an instance of <code>SecureRandom</code> creating one if necessary
 
68
     *
 
69
     */
 
70
    SecureRandom getRndGen() {
 
71
        if ( ChangeHatValve.randomNumberGenerator == null) {
 
72
            ChangeHatValve.randomNumberGenerator =  new java.security.SecureRandom();
 
73
        }
 
74
        return ChangeHatValve.randomNumberGenerator;
 
75
    }
 
76
 
 
77
    /*
 
78
     *
 
79
     * Call to return a random cookie from the <code>SecureRandom</code> PRNG
 
80
     *
 
81
     */
 
82
    int getCookie() {
 
83
        SecureRandom rnd = getRndGen();
 
84
        if ( rnd == null ) {
 
85
            this.getContainer().getLogger().error(
 
86
                "[APPARMOR] can't initialize SecureRandom for cookie" +
 
87
                " generation for change_hat() call.");
 
88
            return 0;
 
89
        }
 
90
        return rnd.nextInt();
 
91
    }
 
92
 
 
93
 
 
94
    /*
 
95
     *
 
96
     * Call out to AppArmor change_hat(2) to change the security
 
97
     * context for the processing of the request by subsequent valves.
 
98
     * Returns to the current security context when processing is complete.
 
99
     * The security context that is chosen is govern by the
 
100
     * <code>mediationType</code> property - which can be set in the
 
101
     * <code>server.xml</code> file.
 
102
     *
 
103
     * @param request Request being processed
 
104
     * @param response Response being processed
 
105
     * @param context The valve context used to invoke the next valve
 
106
     *  in the current processing pipeline
 
107
     *
 
108
     * @exception IOException if an input/output error has occurred
 
109
     * @exception ServletException if a servlet error has occurred
 
110
     *
 
111
     */
 
112
    public void invoke( org.apache.catalina.connector.Request request,
 
113
                        org.apache.catalina.connector.Response response )
 
114
    throws IOException, ServletException {
 
115
 
 
116
        Container container = this.getContainer();
 
117
        int cookie, result;
 
118
        boolean inSubHat = false;
 
119
 
 
120
        container.getLogger().debug(this.getClass().toString() +
 
121
            "[APPARMOR] Request received [" + request.getInfo()
 
122
            + "]");
 
123
 
 
124
        String hatname = ChangeHatValve.DEFAULT_HAT;;
 
125
        if ( getMediationType() == ChangeHatValve.SERVLET_PATH_MEDIATION ) {
 
126
            hatname = request.getServletPath();
 
127
        } else if ( getMediationType() == ChangeHatValve.URI_MEDIATION ) {
 
128
            hatname = request.getRequestURI();
 
129
        }
 
130
 
 
131
       /*
 
132
        * Select the AppArmor container for this request:
 
133
        *
 
134
        *  1. try hat name from either URI or ServletPath
 
135
        *     (based on configuration)
 
136
        *
 
137
        *  2. try hat name of the defined DEFAULT_HAT
 
138
        *
 
139
        *  3. run in the current AppArmor context
 
140
        */
 
141
 
 
142
        cookie = getCookie();
 
143
        if ( hatname == null || "".equals(hatname) ) {
 
144
            hatname = ChangeHatValve.DEFAULT_HAT;
 
145
        }
 
146
        container.getLogger().debug("[APPARMOR] ChangeHat to [" + hatname
 
147
          + "] cookie [" + cookie + "]");
 
148
 
 
149
        result = changehat_wrapper.changehat_in(hatname, cookie);
 
150
 
 
151
        if ( result == JNIChangeHat.EPERM ) {
 
152
            container.getLogger().error("[APPARMOR] change_hat valve " +
 
153
              "configured but Tomcat process is not confined by an " +
 
154
              "AppArmor profile.");
 
155
            getNext().invoke(request, response);
 
156
        } else {
 
157
            if ( result == JNIChangeHat.EACCES ) {
 
158
            changehat_wrapper.changehat_out(cookie);
 
159
            result = changehat_wrapper.changehat_in(ChangeHatValve.DEFAULT_HAT,
 
160
                                                    cookie);
 
161
            if ( result != 0 ) {
 
162
                changehat_wrapper.changehat_out(cookie);
 
163
                container.getLogger().error("[APPARMOR] ChangeHat to [" + hatname
 
164
                  + "] failed. Running in parent context.");
 
165
            } else  {
 
166
                inSubHat = true;
 
167
            }
 
168
        } else if ( result != 0 ) {
 
169
            changehat_wrapper.changehat_out(cookie);
 
170
            container.getLogger().error("[APPARMOR] ChangeHat to [" + hatname
 
171
              + "] failed. Running in parent context.");
 
172
        } else {
 
173
            inSubHat = true;
 
174
        }
 
175
        getNext().invoke(request, response);
 
176
        if ( inSubHat ) changehat_wrapper.changehat_out(cookie);
 
177
        }
 
178
    }
 
179
}
 
180