001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.runtime.api.login; 023 024import java.io.IOException; 025import java.io.ObjectInputStream; 026import java.io.ObjectOutputStream; 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033import javax.security.auth.Subject; 034import javax.security.auth.callback.CallbackHandler; 035import javax.security.auth.login.AppConfigurationEntry; 036import javax.security.auth.login.LoginContext; 037import javax.security.auth.login.LoginException; 038import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag; 039 040import org.nuxeo.common.xmap.annotation.XNode; 041import org.nuxeo.common.xmap.annotation.XNodeList; 042import org.nuxeo.common.xmap.annotation.XObject; 043import org.nuxeo.runtime.api.LoginModuleWrapper; 044 045/** 046 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 047 */ 048@XObject("domain") 049public class SecurityDomain implements Serializable { 050 051 private static final long serialVersionUID = 5770889355854831093L; 052 053 @XNode("@name") 054 private String name; 055 056 private transient AppConfigurationEntry[] entries; 057 058 public SecurityDomain() { 059 } 060 061 public SecurityDomain(String name) { 062 this.name = name; 063 } 064 065 public SecurityDomain(String name, AppConfigurationEntry[] entries) { 066 this.name = name; 067 this.entries = entries; 068 } 069 070 public String getName() { 071 return name; 072 } 073 074 public AppConfigurationEntry[] getAppConfigurationEntries() { 075 return entries; 076 } 077 078 public void setAppConfigurationEntries(AppConfigurationEntry[] entries) { 079 this.entries = entries; 080 } 081 082 @XNodeList(value = "login-module", type = ArrayList.class, componentType = LoginModuleDescriptor.class) 083 public void setEntries(List<LoginModuleDescriptor> descriptors) { 084 entries = new AppConfigurationEntry[descriptors.size()]; 085 int i = 0; 086 for (LoginModuleDescriptor descriptor : descriptors) { 087 LoginModuleControlFlag flag = null; 088 if (descriptor.flag == null) { 089 flag = LoginModuleControlFlag.OPTIONAL; 090 } else if ("optional".equals(descriptor.flag)) { 091 flag = LoginModuleControlFlag.OPTIONAL; 092 } else if ("sufficient".equals(descriptor.flag)) { 093 flag = LoginModuleControlFlag.SUFFICIENT; 094 } else if ("required".equals(descriptor.flag)) { 095 flag = LoginModuleControlFlag.REQUIRED; 096 } else if ("requisite".equals(descriptor.flag)) { 097 flag = LoginModuleControlFlag.REQUISITE; 098 } 099 descriptor.options.put(LoginModuleWrapper.DELEGATE_CLASS_KEY, descriptor.code); 100 entries[i++] = new AppConfigurationEntry(LoginModuleWrapper.class.getName(), flag, descriptor.options); 101 } 102 } 103 104 public LoginContext login(Subject subject) throws LoginException { 105 LoginContext ctx = new LoginContext(name, subject); 106 ctx.login(); 107 return ctx; 108 } 109 110 public LoginContext login(CallbackHandler handler) throws LoginException { 111 LoginContext ctx = new LoginContext(name, handler); 112 ctx.login(); 113 return ctx; 114 } 115 116 public LoginContext login(Subject subject, CallbackHandler handler) throws LoginException { 117 LoginContext ctx = new LoginContext(name, subject, handler); 118 ctx.login(); 119 return ctx; 120 } 121 122 public LoginContext login(String username, Object credentials) throws LoginException { 123 CredentialsCallbackHandler handler = new CredentialsCallbackHandler(username, credentials); 124 LoginContext ctx = new LoginContext(name, handler); 125 ctx.login(); 126 return ctx; 127 } 128 129 public static String controlFlagToString(LoginModuleControlFlag flag) { 130 if (flag == LoginModuleControlFlag.OPTIONAL) { 131 return "optional"; 132 } else if (flag == LoginModuleControlFlag.REQUIRED) { 133 return "required"; 134 } else if (flag == LoginModuleControlFlag.REQUISITE) { 135 return "requisite"; 136 } else if (flag == LoginModuleControlFlag.SUFFICIENT) { 137 return "sufficient"; 138 } 139 throw new IllegalArgumentException("Not a supported LoginModuleControlFlag: " + flag); 140 } 141 142 public static LoginModuleControlFlag controlFlagFromString(String flag) { 143 if (flag == null) { 144 return LoginModuleControlFlag.OPTIONAL; 145 } else if ("optional".equals(flag)) { 146 return LoginModuleControlFlag.OPTIONAL; 147 } else if ("sufficient".equals(flag)) { 148 return LoginModuleControlFlag.SUFFICIENT; 149 } else if ("required".equals(flag)) { 150 return LoginModuleControlFlag.REQUIRED; 151 } else if ("requisite".equals(flag)) { 152 return LoginModuleControlFlag.REQUISITE; 153 } 154 throw new IllegalArgumentException("Not a supported LoginModuleControlFlag: " + flag); 155 } 156 157 @SuppressWarnings("unchecked") 158 private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { 159 in.defaultReadObject(); 160 // read app config entries 161 int size = in.readInt(); 162 entries = new AppConfigurationEntry[size]; 163 for (int i = 0; i < size; i++) { 164 String name = (String) in.readObject(); 165 String ctrlFlag = (String) in.readObject(); 166 LoginModuleControlFlag flag = controlFlagFromString(ctrlFlag); 167 Map<String, ?> opts = (Map<String, ?>) in.readObject(); 168 entries[i] = new AppConfigurationEntry(name, flag, opts); 169 } 170 } 171 172 private void writeObject(ObjectOutputStream out) throws IOException { 173 out.defaultWriteObject(); 174 // write app config entries 175 if (entries == null) { 176 out.writeInt(0); 177 } else { 178 out.writeInt(entries.length); 179 for (AppConfigurationEntry entry : entries) { 180 out.writeObject(entry.getLoginModuleName()); 181 out.writeObject(controlFlagToString(entry.getControlFlag())); 182 Map<String, ?> opts = entry.getOptions(); 183 if (!(opts instanceof Serializable)) { 184 opts = new HashMap<String, Object>(opts); 185 } 186 out.writeObject(opts); 187 } 188 } 189 } 190 191}