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