~ubuntu-core-dev/ubuntu/maverick/eucalyptus/devel

« back to all changes in this revision

Viewing changes to .pc/20-brute-force-webui.patch/clc/modules/www/src/main/java/edu/ucsb/eucalyptus/admin/server/EucalyptusWebBackendImpl.java

  • Committer: Dustin Kirkland
  • Date: 2010-07-22 08:41:57 UTC
  • mfrom: (1050.1.19 ubuntu)
  • Revision ID: kirkland@x200-20100722084157-zh2p8dkawznvxxpn
Approving Dave Walker's merge of new upstream Eucalyptus 2.0 release.

Dustin Kirkland <kirkland@canonical.com>

* New major upstream version merge, 2.0 (r1211).
  - 01-wsdl-stubs.patch, debian/wsdl.md5sums: wsdl stubs updated.
  - 11-state-cleanup-memleakfix.patch: Removed, fixed upstream.
  - 21-eucalyptus-1.7-with-gwt-1.6.4.patch: New patch, allows 
    eucalyptus-1.7 to be built against gwt 1.6.4. Based on patch courtesy 
    of Dmitrii Zagorodnov, upstream. (LP: #597330)
* debian/eucalyptus-java-common.links: 
  - Changed symlink for groovy, point to groovy.all.jar, making compatiable 
    with groovy versions >1.7. (LP: #595421)
  - Added ant.jar & jetty-rewrite-handler.jar as they are now required.
* debian/control
  - & debian/build-jars: Added libjavassist-java and libjetty-extra-java as 
    build dependencies.
  - Added libjetty-extra-java as a dependency of eucalyptus-java-common
* The binary resulting jar's have been renamed from eucalyptus-*-1.6.2.jar
  to eucalyptus-*-main.jar:    
  - debian/eucalyptus-cc.upstart
  - debian/eucalyptus-cloud.install
  - debian/eucalyptus-common.eucalyptus.upstart
  - debian/eucalyptus-java-common.install
  - debian/eucalyptus-network.upstart
  - debian/eucalyptus-sc.install
  - debian/eucalyptus-walrus.install
* debian/eucalyptus-java-common.install: New upstream jars that have been
  installed:
  - eucalyptus-db-hsqldb-ext-main.jar
  - eucalyptus-component-main.jar
* debian/control:
  - Updated Standards Version to 3.8.4 (no change)
  - Updated the upstream Homepage to: http://open.eucalyptus.com/
  - Changed Vcs-Bzr to reflect new location of Ubuntu hosted development branch.
  - Made the Build Dependency of groovy and the binary eucalyptus-java-common
    package depend on version >=1.7.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*******************************************************************************
2
 
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
3
 
 * 
4
 
 *  This program is free software: you can redistribute it and/or modify
5
 
 *  it under the terms of the GNU General Public License as published by
6
 
 *  the Free Software Foundation, only version 3 of the License.
7
 
 * 
8
 
 * 
9
 
 *  This file is distributed in the hope that it will be useful, but WITHOUT
10
 
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 
 *  for more details.
13
 
 * 
14
 
 *  You should have received a copy of the GNU General Public License along
15
 
 *  with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 
 * 
17
 
 *  Please contact Eucalyptus Systems, Inc., 130 Castilian
18
 
 *  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
 
 *  if you need additional information or have any questions.
20
 
 * 
21
 
 *  This file may incorporate work covered under the following copyright and
22
 
 *  permission notice:
23
 
 * 
24
 
 *    Software License Agreement (BSD License)
25
 
 * 
26
 
 *    Copyright (c) 2008, Regents of the University of California
27
 
 *    All rights reserved.
28
 
 * 
29
 
 *    Redistribution and use of this software in source and binary forms, with
30
 
 *    or without modification, are permitted provided that the following
31
 
 *    conditions are met:
32
 
 * 
33
 
 *      Redistributions of source code must retain the above copyright notice,
34
 
 *      this list of conditions and the following disclaimer.
35
 
 * 
36
 
 *      Redistributions in binary form must reproduce the above copyright
37
 
 *      notice, this list of conditions and the following disclaimer in the
38
 
 *      documentation and/or other materials provided with the distribution.
39
 
 * 
40
 
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
 
 *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
 
 *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
 
 *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
 
 *    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
 
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
 
 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
 
 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
 
 *    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
 
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
 
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
 
 *    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
 
 *    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
 
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
 
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
 
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
 
 *    THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
 
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
 
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
 
 *    ANY SUCH LICENSES OR RIGHTS.
60
 
 *******************************************************************************/
61
 
/*
62
 
 *
63
 
 * Author: Dmitrii Zagorodnov dmitrii@cs.ucsb.edu
64
 
 */
65
 
 
66
 
package edu.ucsb.eucalyptus.admin.server;
67
 
 
68
 
import com.eucalyptus.auth.Debugging;
69
 
import com.eucalyptus.auth.Groups;
70
 
import com.eucalyptus.auth.UserInfo;
71
 
import com.eucalyptus.auth.Users;
72
 
import com.eucalyptus.auth.principal.User;
73
 
import com.eucalyptus.auth.util.Hashes;
74
 
import com.eucalyptus.component.Component;
75
 
import com.eucalyptus.component.Components;
76
 
import com.eucalyptus.component.Service;
77
 
import com.eucalyptus.component.ServiceConfiguration;
78
 
import com.eucalyptus.config.ClusterConfiguration;
79
 
import com.eucalyptus.config.Configuration;
80
 
import com.eucalyptus.system.BaseDirectory;
81
 
import com.eucalyptus.system.SubDirectory;
82
 
import com.eucalyptus.util.EucalyptusCloudException;
83
 
import com.google.gwt.user.client.rpc.SerializableException;
84
 
import com.google.gwt.user.client.rpc.SerializationException;
85
 
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
86
 
import com.google.gwt.user.server.rpc.UnexpectedException;
87
 
import edu.ucsb.eucalyptus.admin.client.CloudInfoWeb;
88
 
import edu.ucsb.eucalyptus.admin.client.ClusterInfoWeb;
89
 
import edu.ucsb.eucalyptus.admin.client.DownloadsWeb;
90
 
import edu.ucsb.eucalyptus.admin.client.EucalyptusWebBackend;
91
 
import edu.ucsb.eucalyptus.admin.client.SystemConfigWeb;
92
 
import edu.ucsb.eucalyptus.admin.client.StorageInfoWeb;
93
 
import edu.ucsb.eucalyptus.admin.client.UserInfoWeb;
94
 
import edu.ucsb.eucalyptus.admin.client.VmTypeWeb;
95
 
import edu.ucsb.eucalyptus.admin.client.WalrusInfoWeb;
96
 
 
97
 
import org.apache.commons.httpclient.HttpClient;
98
 
import org.apache.commons.httpclient.ProxyHost;
99
 
import org.apache.commons.httpclient.methods.GetMethod;
100
 
import org.apache.log4j.Logger;
101
 
import org.w3c.dom.Document;
102
 
import org.w3c.dom.NodeList;
103
 
 
104
 
import java.io.ByteArrayInputStream;
105
 
import java.io.File;
106
 
import java.io.FilenameFilter;
107
 
import java.io.InputStream;
108
 
import java.io.FileInputStream;
109
 
import java.io.IOException;
110
 
import java.net.MalformedURLException;
111
 
import java.util.ArrayList;
112
 
import java.util.Enumeration;
113
 
import java.util.HashMap;
114
 
import java.util.HashSet;
115
 
import java.util.List;
116
 
import java.util.Map;
117
 
import java.util.Properties;
118
 
import java.util.Set;
119
 
import javax.xml.parsers.DocumentBuilder;
120
 
import javax.xml.parsers.DocumentBuilderFactory;
121
 
import javax.xml.xpath.XPath;
122
 
import javax.xml.xpath.XPathConstants;
123
 
import javax.xml.xpath.XPathFactory;
124
 
 
125
 
public class EucalyptusWebBackendImpl extends RemoteServiceServlet implements EucalyptusWebBackend {
126
 
 
127
 
        private static Logger LOG = Logger.getLogger( EucalyptusWebBackendImpl.class );
128
 
        private static String PROPERTIES_FILE =  BaseDirectory.CONF.toString() + File.separator + "eucalyptus-web.properties";
129
 
        private static HashMap sessions = new HashMap();
130
 
        private static Properties props = new Properties();
131
 
        private static long session_timeout_ms = 1000 * 60 * 60 * 24 * 14L; /* 2 weeks (TODO: put into config?) */
132
 
        private static long pass_expiration_ms = 1000 * 60 * 60 * 24 * 365L; /* 1 year (TODO: put into config?) */
133
 
 
134
 
        /* parameters to be read from config file */
135
 
        private static String thanks_for_signup;
136
 
        private static String signup_request_subject;
137
 
        private static String signup_approval_subject;
138
 
        private static String signup_approval_header;
139
 
        private static String signup_approval_footer;
140
 
        private static String signup_rejection_subject;
141
 
        private static String signup_rejection_message;
142
 
        private static String password_recovery_message;
143
 
        private static String password_recovery_subject;
144
 
 
145
 
        /* if these are not in config file, we'll use admin's email */
146
 
        private static String signup_email;
147
 
        private static String reply_email;
148
 
        private boolean system_ready;
149
 
 
150
 
        private void load_props() throws SerializableException
151
 
        {
152
 
                FileInputStream fileInputStream = null;
153
 
                try {
154
 
                        fileInputStream = new FileInputStream(PROPERTIES_FILE);
155
 
                        props.load(fileInputStream);
156
 
                        props.setProperty("version", System.getProperty("euca.version"));
157
 
                        thanks_for_signup =         props.getProperty("thanks-for-signup");
158
 
                        signup_email =              props.getProperty("signup-email-address");
159
 
                        reply_email =               props.getProperty("reply-email-address");
160
 
                        signup_request_subject =    props.getProperty("signup-request-subject");
161
 
                        signup_approval_subject =   props.getProperty("signup-approval-subject");
162
 
                        signup_approval_header =    props.getProperty("signup-approval-header");
163
 
                        signup_approval_footer =    props.getProperty("signup-approval-footer");
164
 
                        signup_rejection_subject =  props.getProperty("signup-rejection-subject");
165
 
                        signup_rejection_message =  props.getProperty("signup-rejection-message");
166
 
                        password_recovery_message = props.getProperty("password-recovery-message");
167
 
                        password_recovery_subject = props.getProperty("password-recovery-subject");
168
 
 
169
 
                        if (thanks_for_signup==null) {
170
 
                                throw new SerializableException("Server configuration is missing 'thanks-for-signup' value");
171
 
                        }
172
 
                        if (signup_request_subject==null) {
173
 
                                throw new SerializableException("Server configuration is missing 'signup-request-subject' value");
174
 
                        }
175
 
                        if (signup_approval_subject==null) {
176
 
                                throw new SerializableException("Server configuration is missing 'signup-approval-subject' value");
177
 
                        }
178
 
                        if (signup_approval_header==null) {
179
 
                                throw new SerializableException("Server configuration is missing 'signup-approval-header' value");
180
 
                        }
181
 
                        if (signup_approval_footer==null) {
182
 
                                throw new SerializableException("Server configuration is missing 'signup-approval-footer' value");
183
 
                        }
184
 
                        if (signup_rejection_subject==null) {
185
 
                                throw new SerializableException("Server configuration is missing 'signup-rejection-subject' value");
186
 
                        }
187
 
                        if (signup_rejection_message==null) {
188
 
                                throw new SerializableException("Server configuration is missing 'signup-rejection-message' value");
189
 
                        }
190
 
                        if (password_recovery_message==null) {
191
 
                                throw new SerializableException("Server configuration is missing 'password-recovery-message' value");
192
 
                        }
193
 
                        if (password_recovery_subject==null) {
194
 
                                throw new SerializableException("Server configuration is missing 'password-recovery-subject' value");
195
 
                        }
196
 
                        system_ready = true;
197
 
                        if ( signup_email==null) {
198
 
                                try {
199
 
                                        signup_email = EucalyptusManagement.getAdminEmail();
200
 
                                } catch (Exception e) {
201
 
                                        signup_email = ""; /* signup will not work until admin email address is set */
202
 
                                        system_ready = false;
203
 
                                }
204
 
                        }
205
 
                        if (reply_email==null) {
206
 
                                reply_email = signup_email;
207
 
                        }
208
 
 
209
 
                } catch (IOException e) {
210
 
                        throw new SerializableException("Could not read server configuration");
211
 
                } catch (IllegalArgumentException e) {
212
 
                        throw new SerializableException("Malformed escape sequence in server configuration");
213
 
                } finally {
214
 
                        if(fileInputStream != null)
215
 
                                try {
216
 
                                        fileInputStream.close();
217
 
                                } catch (IOException e) {
218
 
                                        LOG.error(e);
219
 
                                }
220
 
                }
221
 
        }
222
 
 
223
 
        public String addUserRecord ( UserInfoWeb user )
224
 
        throws SerializableException
225
 
        {
226
 
                return addUserRecord(null, user);
227
 
        }
228
 
 
229
 
        private void notifyAdminOfSignup (UserInfoWeb user)
230
 
        throws SerializableException
231
 
        {
232
 
                try {
233
 
                        String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
234
 
                        String approve_link = http_eucalyptus + "?action=approve&user=" + user.getUserName();
235
 
                        String reject_link = http_eucalyptus + "?action=reject&user=" + user.getUserName();
236
 
 
237
 
                        String email_message =
238
 
                                "Someone has requested an account on the Eucalyptus system\n" +
239
 
                                "\n   Name:          " + user.getRealName() +
240
 
                                "\n   Username:      " + user.getUserName() +
241
 
                                "\n   Email address: " + user.getEmail() +
242
 
                                "\n   Telephone:     " + user.getTelephoneNumber() +
243
 
                                "\n   Affiliation:   " + user.getAffiliation() +
244
 
                                "\n   Project PI:    " + user.getProjectPIName() +
245
 
                                "\n   Project description: " +
246
 
                                "\n=====\n" + user.getProjectDescription() +
247
 
                                "\n=====\n\n" +
248
 
                                "To APPROVE this request, click on the following link:\n\n   " +
249
 
                                approve_link +
250
 
                                "\n\n" +
251
 
                                "To REJECT this request, click on the following link:\n\n   " +
252
 
                                reject_link +
253
 
                                "\n\n";
254
 
 
255
 
                        ServletUtils.sendMail( reply_email, signup_email,
256
 
                                        signup_request_subject + " (" + user.getEmail() + ")",
257
 
                                        email_message);
258
 
 
259
 
                } catch (Exception e) {
260
 
                        LOG.error ("Signup mailing problem: " + e.getMessage()); /* TODO: log properly */
261
 
                        throw new SerializableException ("Internal problem (failed to notify administrator by email)");
262
 
                }
263
 
        }
264
 
 
265
 
        public String addUserRecord(String sessionId, UserInfoWeb user)
266
 
        throws SerializableException
267
 
        {
268
 
                if (user==null) {
269
 
                        throw new SerializableException("Invalid RPC arguments");
270
 
                }
271
 
                if (user.getUserName().equalsIgnoreCase( "eucalyptus" )) {
272
 
                        throw new SerializableException("User 'eucalyptus' is not allowed");
273
 
                }
274
 
                // these two won't happen unless the user hacks the client side
275
 
                if ( user.getUserName().matches(".*[^\\w\\-\\.@]+.*") ) {
276
 
                        throw new SerializableException ("Invalid characters in the username");
277
 
                }
278
 
                if ( user.getUserName().length() < 1 || user.getUserName().length() > 30)
279
 
                {
280
 
                        throw new SerializableException ( "Invalid length of username" );
281
 
                }
282
 
 
283
 
                load_props(); /* get parameters from config file */
284
 
                boolean admin = false;
285
 
                try {
286
 
                        SessionInfo session = verifySession (sessionId);
287
 
                        UserInfoWeb requestingUser = verifyUser (session, session.getUserId(), true);
288
 
                        if ( !requestingUser.isAdministrator().booleanValue()) {
289
 
                                throw new SerializableException("Administrative privileges required");
290
 
                        } else {
291
 
                                admin = true;
292
 
                        }
293
 
                } catch (Exception e) { } /* that's OK, this was an anonymous request */
294
 
 
295
 
                /* add the user */
296
 
                long now = System.currentTimeMillis();
297
 
                user.setPasswordExpires( new Long(now + pass_expiration_ms) );
298
 
                EucalyptusManagement.addWebUser(user);
299
 
 
300
 
                String response;
301
 
                if (admin) {
302
 
                        /* enable the new user right away */
303
 
                        user.setApproved(true);
304
 
                        user.setEnabled(true);
305
 
                        response = notifyUserApproved(user);
306
 
                } else {
307
 
                        /* if anonymous, then notify admin */
308
 
                        user.setApproved(false);
309
 
                        user.setEnabled(false);
310
 
                        notifyAdminOfSignup (user);
311
 
                        response = thanks_for_signup;
312
 
                }
313
 
                EucalyptusManagement.commitWebUser(user);
314
 
 
315
 
                return response;
316
 
        }
317
 
 
318
 
        private String notifyUserRecovery(UserInfoWeb user)
319
 
        {
320
 
                try {
321
 
                        String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
322
 
                        String confirm_link = http_eucalyptus + "?action=recover"
323
 
                        + "&code=" + user.getConfirmationCode();
324
 
 
325
 
                        String email_message = password_recovery_message + "\n\n" +
326
 
                        confirm_link +
327
 
                        "\n";
328
 
 
329
 
                        ServletUtils.sendMail(reply_email, user.getEmail(),
330
 
                                        password_recovery_subject,
331
 
                                        email_message);
332
 
 
333
 
                } catch (Exception e) {
334
 
                        // TODO: log this using the proper procedure
335
 
                        LOG.error ("Password recovery mailing problem: " + e.getMessage());
336
 
                        LOG.error ("Confirmation code for user '" + user.getUserName()
337
 
                                        + "' and address " + user.getEmail()
338
 
                                        + " is " + user.getConfirmationCode());
339
 
 
340
 
                        return "Internal problem (failed to notify " + user.getEmail() + " by email)";
341
 
                }
342
 
                return "Notified '" + user.getUserName() + "' by email, thank you.";
343
 
        }
344
 
 
345
 
        public String recoverPassword ( UserInfoWeb web_user )
346
 
        throws SerializableException
347
 
        {
348
 
                if (web_user==null) {
349
 
                        throw new SerializableException("Invalid RPC arguments");
350
 
                }
351
 
 
352
 
                UserInfoWeb db_user;
353
 
                try {
354
 
                        /* try login first */
355
 
                        db_user = EucalyptusManagement.getWebUser(web_user.getUserName());
356
 
                } catch (Exception e) {
357
 
                        /* try email then */
358
 
                        db_user = EucalyptusManagement.getWebUserByEmail(web_user.getEmail());
359
 
                }
360
 
                db_user.setPassword (web_user.getPassword());
361
 
                EucalyptusManagement.commitWebUser(db_user);
362
 
                return notifyUserRecovery(db_user);
363
 
        }
364
 
 
365
 
        /* ensure the sessionId is (still) valid */
366
 
        public static SessionInfo verifySession (String sessionId)
367
 
        throws SerializableException
368
 
        {
369
 
                if (sessionId==null) {
370
 
                        throw new SerializableException("Invalid RPC arguments");
371
 
                }
372
 
                SessionInfo session = (SessionInfo)sessions.get(sessionId);
373
 
                if (session==null) {
374
 
                        throw new SerializableException("Earlier session not found");
375
 
                }
376
 
                final long now = System.currentTimeMillis();
377
 
                if ((now-session.getLastAccessed()) > session_timeout_ms) {
378
 
                        sessions.remove(sessionId);
379
 
                        throw new SerializableException("Earlier session expired");
380
 
                }
381
 
                session.setLastAccessed(System.currentTimeMillis());
382
 
                return session;
383
 
        }
384
 
 
385
 
        private static boolean isPasswordExpired (UserInfoWeb user) {
386
 
                final long now = System.currentTimeMillis();
387
 
                if ((now > 0) && (now >= user.getPasswordExpires().longValue())) {
388
 
                        return true;
389
 
                }
390
 
                return false;
391
 
        }
392
 
 
393
 
        /* ensure the user exists and valid */
394
 
        private static UserInfoWeb verifyUser (SessionInfo session, String userName, boolean verifyPasswordAge)
395
 
        throws SerializableException
396
 
        {
397
 
                UserInfoWeb user;
398
 
                if (userName==null) {
399
 
                        throw new SerializableException("Invalid RPC arguments: userIname is missing");
400
 
                }
401
 
                try {
402
 
                        user = EucalyptusManagement.getWebUser(userName);
403
 
                } catch (Exception e) {
404
 
                        if (session!=null) {
405
 
                                sessions.remove(session.getSessionId());
406
 
                        }
407
 
                        throw new SerializableException("Username '" + userName + "' not found");
408
 
                }
409
 
                if (!user.isApproved()) {
410
 
                        throw new SerializableException("User not approved yet");
411
 
                }
412
 
                if (!user.isEnabled()) {
413
 
                        throw new SerializableException("Disabled user account");
414
 
                }
415
 
                if (!user.isConfirmed()) {
416
 
                        throw new SerializableException("Unconfirmed account (click on the link in confirmation email)");
417
 
                }
418
 
                if (verifyPasswordAge) {
419
 
                        if (isPasswordExpired(user) && 
420
 
                                        !(user.isAdministrator() && user.getEmail().equalsIgnoreCase(UserInfo.BOGUS_ENTRY))) { // first-time config will catch that
421
 
                                throw new SerializableException("Password expired");
422
 
                        }
423
 
                }
424
 
                return user;
425
 
        }
426
 
 
427
 
        public String getNewSessionID (String userId, String md5Password)
428
 
        throws SerializableException
429
 
        {
430
 
                String sessionId = null;
431
 
                UserInfoWeb user;
432
 
 
433
 
                if (md5Password==null) {
434
 
                        throw new SerializableException("Invalid RPC arguments: password is missing");
435
 
                }
436
 
                // you can get a sessionId with an expired password so you can change it => false
437
 
                user = verifyUser (null, userId, false);
438
 
                if (!user.getPassword().equals( md5Password )) {
439
 
                        throw new SerializableException("Incorrect password");
440
 
                }
441
 
 
442
 
                sessionId = ServletUtils.genGUID();
443
 
                SessionInfo session = new SessionInfo(sessionId, userId, System.currentTimeMillis());
444
 
                session.setStartedOn(session.getLastAccessed());
445
 
                sessions.put(session.getSessionId(), session);
446
 
 
447
 
                return session.getSessionId();
448
 
        }
449
 
 
450
 
        private String notifyUserApproved(UserInfoWeb user)
451
 
        {
452
 
                String confString = " and confirmed";
453
 
                try {
454
 
                        if (!user.isConfirmed().booleanValue()) {
455
 
                                confString = "";
456
 
                                String http_eucalyptus = ServletUtils.getRequestUrl(getThreadLocalRequest());
457
 
                                String confirm_link = http_eucalyptus + "?action=confirm"
458
 
                                + "&code=" + user.getConfirmationCode();
459
 
 
460
 
                                String email_message = signup_approval_header + "\n\n" +
461
 
                                confirm_link +
462
 
                                "\n\n" + signup_approval_footer;
463
 
 
464
 
                                ServletUtils.sendMail(reply_email, user.getEmail(),
465
 
                                                signup_approval_subject,
466
 
                                                email_message);
467
 
                        }
468
 
                } catch (Exception e) {
469
 
                        // TODO: log this using the proper procedure
470
 
                        LOG.error ("Approval mailing problem: " + e.getMessage());
471
 
                        LOG.error ("Confirmation code for user " + user.getUserName()
472
 
                                        + " is " + user.getConfirmationCode());
473
 
 
474
 
                        return "Internal problem (failed to notify user " + user.getEmail() + " by email)";
475
 
                }
476
 
                return "User '" + user.getUserName() + "' was approved" + confString + ", thank you.";
477
 
        }
478
 
 
479
 
        private String notifyUserRejected(UserInfoWeb user)
480
 
        {
481
 
                try {
482
 
                        ServletUtils.sendMail(reply_email, user.getEmail(),
483
 
                                        signup_rejection_subject,
484
 
                                        signup_rejection_message);
485
 
 
486
 
                } catch (Exception e) {
487
 
                        LOG.error ("Rejection mailing problem: " + e.getMessage());
488
 
                        return "Internal problem (failed to notify user " + user.getEmail() + ")";
489
 
                }
490
 
                return "User '" + user.getUserName() + "' was rejected.";
491
 
        }
492
 
 
493
 
        public String performAction (String sessionId, String action, String param)
494
 
        throws SerializableException
495
 
        {
496
 
                load_props();
497
 
                if (action==null || param==null) {
498
 
                        throw new SerializableException("Invalid RPC arguments: action or param are missing");
499
 
                }
500
 
 
501
 
                /* these don't need a session */
502
 
                if (action.equals("recover") ||
503
 
                                action.equals("confirm")) {
504
 
                        UserInfoWeb user = EucalyptusManagement.getWebUserByCode(param);
505
 
                        String response;
506
 
 
507
 
                        if (action.equals("confirm")) {
508
 
                                if ( user != null ) {
509
 
                                  user.setConfirmed(true);
510
 
                                }
511
 
                                EucalyptusManagement.commitWebUser(user);
512
 
                                response = "Your account is now active.";
513
 
                        } else {
514
 
                                if(user != null) {
515
 
                              user.setPassword (user.getPassword());
516
 
                                  long now = System.currentTimeMillis();
517
 
                                  user.setPasswordExpires( new Long(now + pass_expiration_ms) );
518
 
                                  EucalyptusManagement.commitWebUser(user);
519
 
                                }
520
 
                                response = "Your password has been reset.";
521
 
                        }
522
 
                        return response;
523
 
                }
524
 
 
525
 
                final SessionInfo session = verifySession (sessionId);
526
 
                final UserInfoWeb user = verifyUser (session, session.getUserId(), true);
527
 
 
528
 
                String response = "Your `" + action + "` request succeeded."; /* generic response */
529
 
                if (action.equals("approve")
530
 
                                || action.equals("reject")
531
 
                                || action.equals ( "delete" )
532
 
                                || action.equals ( "disable" )
533
 
                                || action.equals ( "enable" )) {
534
 
                        String userName = param;
535
 
                        if (!user.isAdministrator()) {
536
 
                                throw new SerializableException("Administrative privileges required");
537
 
                        }
538
 
                        UserInfoWeb new_user = EucalyptusManagement.getWebUser(userName);
539
 
                        if (action.equals("approve")) {
540
 
                                new_user.setApproved(true);
541
 
                                new_user.setEnabled(true);
542
 
                                new_user.setConfirmed(false);
543
 
                                EucalyptusManagement.commitWebUser(new_user);
544
 
                                response = notifyUserApproved(new_user);
545
 
                        } else if (action.equals("reject")) {
546
 
                                EucalyptusManagement.deleteWebUser(new_user);
547
 
                                response = notifyUserRejected(new_user);
548
 
                        } else if (action.equals("delete")) {
549
 
                                EucalyptusManagement.deleteWebUser(new_user);
550
 
                                /* TODO: maybe tell the user that his account was deleted? */
551
 
                        } else if (action.equals("disable")) {
552
 
                                new_user.setEnabled(false);
553
 
                                EucalyptusManagement.commitWebUser(new_user);
554
 
                        } else if (action.equals("enable")) {
555
 
                                new_user.setEnabled(true);
556
 
                                EucalyptusManagement.commitWebUser(new_user);
557
 
                        }
558
 
                        response = "Request to " + action + " user '" + userName + "' succeeded.";
559
 
 
560
 
                } else if (action.equals("delete_image")
561
 
                                || action.equals("enable_image")
562
 
                                || action.equals("disable_image")) {
563
 
                        String imageId = param;
564
 
                        if (!user.isAdministrator()) {
565
 
                                throw new SerializableException("Administrative privileges required");
566
 
                        }
567
 
                        if (action.equals("delete_image")) {
568
 
                                EucalyptusManagement.deleteImage(imageId);
569
 
                        } else if (action.equals("disable_image")) {
570
 
                                EucalyptusManagement.disableImage(imageId);
571
 
                        } else if (action.equals("enable_image")) {
572
 
                                EucalyptusManagement.enableImage(imageId);
573
 
                        }
574
 
                        response = "Your request succeeded, thank you.";
575
 
 
576
 
                } else {
577
 
                        throw new SerializableException("Action '" + action + "' is not implemented.");
578
 
                }
579
 
 
580
 
                return response;
581
 
        }
582
 
 
583
 
        public void logoutSession(String sessionId)
584
 
        throws SerializableException
585
 
        {
586
 
                if (sessionId==null) {
587
 
                        throw new SerializableException("Invalid RPC arguments: sessionId is missing");
588
 
                }
589
 
                SessionInfo session = (SessionInfo)sessions.get(sessionId);
590
 
                if (session!=null) {
591
 
                        sessions.remove(sessionId);
592
 
                        SessionInfo old = (SessionInfo)sessions.get(sessionId);
593
 
                }
594
 
        }
595
 
 
596
 
        public List getUserRecord (String sessionId, String userId)
597
 
        throws SerializableException
598
 
        {
599
 
                SessionInfo session = verifySession (sessionId);
600
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
601
 
 
602
 
                List l = new ArrayList();
603
 
                if (userId==null) {
604
 
                        l.add(user);
605
 
                } else {
606
 
                        if (!user.isAdministrator()) {
607
 
                                throw new SerializableException("Only administrators can view users");
608
 
                        }
609
 
                        if (userId.equals("*")) {
610
 
                                l.addAll( EucalyptusManagement.getWebUsers(userId) ); /* NOTE: userId is currently ignored */
611
 
                        } else {
612
 
                                l.add(EucalyptusManagement.getWebUser(user.getUserName()));
613
 
                        }
614
 
                }
615
 
                return l;
616
 
        }
617
 
 
618
 
        public static UserInfoWeb getUserRecord (String sessionId) // a *static* getUserRecord, for ImageStoreService
619
 
        throws SerializableException
620
 
        {
621
 
                SessionInfo session = verifySession (sessionId);
622
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
623
 
                return user;
624
 
        }
625
 
 
626
 
        public List getImageInfo (String sessionId, String userId)
627
 
        throws SerializableException
628
 
        {
629
 
                SessionInfo session = verifySession (sessionId);
630
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
631
 
 
632
 
                /* TODO: right now userId parameter is ignored since we only have public images */
633
 
                return EucalyptusManagement.getWebImages(userId);
634
 
        }
635
 
 
636
 
        /* from here on down, all requests require users to be enabled, approved, and confirmed */
637
 
 
638
 
        public String getNewCert(String sessionId)
639
 
        throws SerializableException
640
 
        {
641
 
                /* perform full checks */
642
 
                SessionInfo session = verifySession (sessionId);
643
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
644
 
 
645
 
                return user.getToken();
646
 
        }
647
 
 
648
 
        public HashMap getProperties()
649
 
        throws SerializableException
650
 
        {
651
 
                load_props();
652
 
                HashMap h = new HashMap();
653
 
 
654
 
                for (Enumeration e = props.propertyNames(); e.hasMoreElements() ;) {
655
 
                        String key = (String)e.nextElement();
656
 
                        h.put(key, props.getProperty(key));
657
 
                }
658
 
                h.put("ready", system_ready);
659
 
 
660
 
                return h;
661
 
        }
662
 
 
663
 
        public String changePassword (String sessionId, String oldPassword, String newPassword )
664
 
        throws SerializableException
665
 
        {
666
 
                /* check everything except password expiration */
667
 
                SessionInfo session = verifySession (sessionId);
668
 
                // naturally, it is OK to change the password if it expired => false
669
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), false);
670
 
 
671
 
                /* check old password if the user is changing password voluntarily */
672
 
                if ( !isPasswordExpired((UserInfoWeb)user) ) {
673
 
                        if ( !oldPassword.equals(user.getPassword()) ) {
674
 
                                throw new SerializableException("Old password is incorrect");
675
 
                        }
676
 
                }
677
 
                user.setPassword( newPassword );
678
 
                final long now = System.currentTimeMillis();
679
 
                user.setPasswordExpires( new Long(now + pass_expiration_ms) );
680
 
                EucalyptusManagement.commitWebUser( user );
681
 
 
682
 
                return "Password has been changed";
683
 
        }
684
 
 
685
 
        public String updateUserRecord (String sessionId, UserInfoWeb newRecord )
686
 
        throws SerializableException
687
 
        {
688
 
                /* perform full checks */
689
 
                SessionInfo session = verifySession (sessionId);
690
 
                UserInfoWeb callerRecord = verifyUser (session, session.getUserId(), true);
691
 
                String userName = newRecord.getUserName();
692
 
                UserInfoWeb oldRecord;
693
 
                try {
694
 
                        oldRecord = EucalyptusManagement.getWebUser(userName);
695
 
                } catch (Exception e) {
696
 
                        throw new SerializableException("Username '" + userName + "' not found");
697
 
                }
698
 
                if (! callerRecord.isAdministrator()
699
 
                                &&  ! callerRecord.getUserName().equals(userName)) {
700
 
                        throw new SerializableException ("Operation restricted to owner and administrator");
701
 
                }
702
 
 
703
 
                // set expiration for admin setting password for the first time
704
 
                if (oldRecord.isAdministrator() && oldRecord.getEmail().equalsIgnoreCase(UserInfo.BOGUS_ENTRY)) {
705
 
                        long now = System.currentTimeMillis();
706
 
                        oldRecord.setPasswordExpires( new Long(now + pass_expiration_ms) );
707
 
                }
708
 
 
709
 
                /* TODO: Any checks? */
710
 
                oldRecord.setRealName (newRecord.getRealName());
711
 
                oldRecord.setEmail (newRecord.getEmail());
712
 
                oldRecord.setPassword (newRecord.getPassword());
713
 
                oldRecord.setTelephoneNumber (newRecord.getTelephoneNumber());
714
 
                oldRecord.setAffiliation (newRecord.getAffiliation());
715
 
                oldRecord.setProjectDescription (newRecord.getProjectDescription());
716
 
                oldRecord.setProjectPIName (newRecord.getProjectPIName());
717
 
                oldRecord.setAdministrator(newRecord.isAdministrator());
718
 
    oldRecord.setEnabled(newRecord.isEnabled( ));
719
 
 
720
 
                // once confirmed, cannot be unconfirmed; also, confirmation implies approval and enablement
721
 
                if (!oldRecord.isConfirmed() && newRecord.isConfirmed()) {
722
 
                        oldRecord.setConfirmed(true);
723
 
                        oldRecord.setEnabled(true);
724
 
                        oldRecord.setApproved(true);
725
 
                }
726
 
 
727
 
                EucalyptusManagement.commitWebUser( oldRecord );
728
 
 
729
 
                return "Account of user '" + userName + "' was updated";
730
 
        }
731
 
 
732
 
        public List<ClusterInfoWeb> getClusterList(String sessionId) throws SerializableException
733
 
        {
734
 
                SessionInfo session = verifySession (sessionId);
735
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
736
 
                try {
737
 
                        return RemoteInfoHandler.getClusterList();
738
 
                } catch ( EucalyptusCloudException e ) {
739
 
                        throw new SerializableException( e.getMessage( ) );
740
 
                }
741
 
        }
742
 
 
743
 
        public void setClusterList(String sessionId, List<ClusterInfoWeb> clusterList ) throws SerializableException
744
 
        {
745
 
                SessionInfo session = verifySession (sessionId);
746
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
747
 
                try {
748
 
                        RemoteInfoHandler.setClusterList( clusterList );
749
 
                } catch ( EucalyptusCloudException e ) {
750
 
                        throw new SerializableException( e.getMessage( ) );
751
 
                }
752
 
        }
753
 
 
754
 
        public List<StorageInfoWeb> getStorageList(String sessionId) throws SerializableException
755
 
        {
756
 
                SessionInfo session = verifySession (sessionId);
757
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
758
 
                try {
759
 
                        return RemoteInfoHandler.getStorageList();
760
 
                } catch(EucalyptusCloudException e) {
761
 
                        throw new SerializableException(e.getMessage());
762
 
                }
763
 
        }
764
 
 
765
 
        public void setStorageList(String sessionId, List<StorageInfoWeb> storageList ) throws SerializableException
766
 
        {
767
 
                SessionInfo session = verifySession (sessionId);
768
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
769
 
                try {
770
 
                        RemoteInfoHandler.setStorageList(storageList);
771
 
                } catch(EucalyptusCloudException e) {
772
 
                        throw new SerializableException(e.getMessage());
773
 
                }
774
 
        }
775
 
 
776
 
        public List<WalrusInfoWeb> getWalrusList(String sessionId) throws SerializableException
777
 
        {
778
 
                SessionInfo session = verifySession (sessionId);
779
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
780
 
                try {
781
 
                        return RemoteInfoHandler.getWalrusList();
782
 
                } catch(EucalyptusCloudException e) {
783
 
                        throw new SerializableException(e.getMessage());
784
 
                }
785
 
        }
786
 
 
787
 
        public void setWalrusList(String sessionId, List<WalrusInfoWeb> walrusList ) throws SerializableException
788
 
        {
789
 
                SessionInfo session = verifySession (sessionId);
790
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
791
 
 
792
 
                try {
793
 
                        RemoteInfoHandler.setWalrusList(walrusList);
794
 
                } catch(EucalyptusCloudException e) {
795
 
                        throw new SerializableException(e.getMessage());
796
 
                }
797
 
        }
798
 
 
799
 
        public SystemConfigWeb getSystemConfig( final String sessionId ) throws SerializableException
800
 
        {
801
 
                SessionInfo session = verifySession (sessionId);
802
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
803
 
 
804
 
                return EucalyptusManagement.getSystemConfig();
805
 
        }
806
 
 
807
 
        public void setSystemConfig( final String sessionId, final SystemConfigWeb systemConfig ) throws SerializableException
808
 
        {
809
 
                SessionInfo session = verifySession (sessionId);
810
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
811
 
 
812
 
                EucalyptusManagement.setSystemConfig(systemConfig);
813
 
        }
814
 
 
815
 
        public List<VmTypeWeb> getVmTypes( final String sessionId ) throws SerializableException
816
 
        {
817
 
                SessionInfo session = verifySession (sessionId);
818
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
819
 
 
820
 
                return RemoteInfoHandler.getVmTypes();
821
 
        }
822
 
 
823
 
        public void setVmTypes( final String sessionId, final List<VmTypeWeb> vmTypes ) throws SerializableException
824
 
        {
825
 
                SessionInfo session = verifySession (sessionId);
826
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
827
 
 
828
 
                RemoteInfoHandler.setVmTypes(vmTypes);
829
 
        }
830
 
 
831
 
        public CloudInfoWeb getCloudInfo(final String sessionId, final boolean setExternalHostPort) throws SerializableException
832
 
        {
833
 
                SessionInfo session = verifySession (sessionId);
834
 
                UserInfoWeb user = verifyUser (session, session.getUserId(), true);
835
 
 
836
 
                return EucalyptusManagement.getCloudInfo(setExternalHostPort);
837
 
        }
838
 
 
839
 
        private static List<DownloadsWeb> getDownloadsFromUrl(final String downloadsUrl) {
840
 
                List<DownloadsWeb> downloadsList = new ArrayList<DownloadsWeb>();
841
 
 
842
 
                HttpClient httpClient = new HttpClient();
843
 
                //support for http proxy
844
 
                if(System.getProperty("http.proxyHost") != null) {
845
 
                        String proxyHost = System.getProperty("http.proxyHost");
846
 
                        if(System.getProperty("http.proxyPort") != null) {
847
 
                                int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort"));
848
 
                                httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
849
 
                        } else {
850
 
                                httpClient.getHostConfiguration().setProxyHost(new ProxyHost(proxyHost));
851
 
                        }
852
 
                }
853
 
                GetMethod method = new GetMethod(downloadsUrl);
854
 
                Integer timeoutMs = new Integer(3 * 1000);
855
 
                method.getParams().setSoTimeout(timeoutMs);
856
 
 
857
 
                try {
858
 
                        httpClient.executeMethod(method);
859
 
                        String str = "";
860
 
                        InputStream in = method.getResponseBodyAsStream();
861
 
                        byte[] readBytes = new byte[1024];
862
 
                        int bytesRead = -1;
863
 
                        while((bytesRead = in.read(readBytes)) > 0) {
864
 
                                str += new String(readBytes, 0, bytesRead);
865
 
                        }
866
 
                        String entries[] = str.split("[\\r\\n]+");
867
 
                        for (int i=0; i<entries.length; i++) {
868
 
                                String entry[] = entries[i].split("\\t");
869
 
                                if (entry.length == 3) {
870
 
                                        downloadsList.add (new DownloadsWeb(entry[0], entry[1], entry[2]));
871
 
                                }
872
 
                        }
873
 
 
874
 
                } catch (MalformedURLException e) {
875
 
                        LOG.warn("Malformed URL exception: " + e.getMessage());
876
 
                        e.printStackTrace();
877
 
 
878
 
                } catch (IOException e) {
879
 
                        LOG.warn("I/O exception: " + e.getMessage());
880
 
                        e.printStackTrace();
881
 
 
882
 
                } finally {
883
 
                        method.releaseConnection();
884
 
                }
885
 
 
886
 
                return downloadsList;
887
 
        }
888
 
 
889
 
        public List<DownloadsWeb> getDownloads(final String sessionId, final String downloadsUrl) throws SerializableException {
890
 
                SessionInfo session = verifySession(sessionId);
891
 
                UserInfoWeb user = verifyUser(session, session.getUserId(), true);
892
 
                return getDownloadsFromUrl(downloadsUrl);
893
 
        }
894
 
 
895
 
        /**
896
 
         * Overridden to really throw Jetty RetryRequest Exception (as opposed to sending failure to client).
897
 
         *
898
 
         * @param caught the exception
899
 
         */
900
 
        protected void doUnexpectedFailure(Throwable caught)
901
 
        {
902
 
                throwIfRetryRequest(caught);
903
 
                super.doUnexpectedFailure(caught);
904
 
        }
905
 
        private static final String JETTY_RETRY_REQUEST_EXCEPTION = "org.mortbay.jetty.RetryRequest";
906
 
        /**
907
 
         * Throws the Jetty RetryRequest if found.
908
 
         *
909
 
         * @param caught the exception
910
 
         */
911
 
        protected void throwIfRetryRequest(Throwable caught)
912
 
        {
913
 
                if (caught instanceof UnexpectedException )
914
 
                {
915
 
                        caught = caught.getCause();
916
 
                }
917
 
 
918
 
                if (JETTY_RETRY_REQUEST_EXCEPTION.equals(caught.getClass().getName()))
919
 
                {
920
 
                        throw (RuntimeException)caught;
921
 
                }
922
 
        }
923
 
 
924
 
}