| 1 package freecs.auth; 2 3 import java.io.File ; 4 import java.io.FileInputStream ; 5 import java.net.InetAddress ; 6 import java.nio.channels.SelectionKey ; 7 import java.nio.channels.SocketChannel ; 8 import java.util.Properties ; 9 import java.util.StringTokenizer ; 10 import java.util.Vector ; 11 import java.util.regex.Matcher ; 12 import java.util.regex.Pattern ; 13 14 import freecs.Server; 15 import freecs.commands.AbstractCommand; 16 import freecs.content.Connection; 17 import freecs.content.ContentContainer; 18 import freecs.core.Group; 19 import freecs.core.GroupManager; 20 import freecs.core.Membership; 21 import freecs.core.MembershipManager; 22 import freecs.core.RequestReader; 23 import freecs.core.User; 24 import freecs.core.UserManager; 25 import freecs.interfaces.IReloadable; 26 import freecs.interfaces.IRequest; 27 import freecs.layout.TemplateSet; 28 import freecs.util.FileMonitor; 29 30 public class AuthManager implements IReloadable { 31 32 public static AuthManager instance = new AuthManager(); 33 private File configFile; 35 private long configLastModified; 36 37 private boolean ALLOW_UNREGISTERED_USERS=false; 38 public String USERNAME_REGEX = "^[a-z[A-Z[0-9[äöüÄÖÜß]]]]+$"; 39 40 public Pattern userNamePattern; 42 43 private IAuthenticator[] list; 44 45 48 private AuthManager() { 49 list = new IAuthenticator[0]; 50 } 51 52 57 public static File getDefaultConfigFile() { 58 return new File (Server.srv.getConfigDir(), "auth.properties"); 59 } 60 61 64 public static Properties parseConfigFile(File configFile) { 65 try { 66 FileInputStream in = new FileInputStream (configFile); 67 Properties props = new Properties (); 68 props.load (in); 69 in.close (); 70 return props; 71 } catch (Exception e) { 72 Server.log (null, "can't read authentication config from " + configFile + " (" + e.toString() + ")", Server.MSG_STATE, Server.LVL_MAJOR); 73 return null; 74 } 75 } 76 77 80 public void init() { 81 init(getDefaultConfigFile()); 82 } 83 84 88 public void init(File configFile) { 89 this.configFile = configFile; 90 configLastModified = configFile.lastModified(); 91 FileMonitor.getFileMonitor().addReloadable(this); 92 createAuthenticators(); 93 } 94 95 100 public void createAuthenticators() { 101 Properties props = parseConfigFile(configFile); 102 String allowUnregistered = props.getProperty("allowUnregisteredUsers", "false").toLowerCase(); 103 ALLOW_UNREGISTERED_USERS = ("true".equals(allowUnregistered) 104 || "1".equals(allowUnregistered) 105 || "yes".equals(allowUnregistered)); 106 USERNAME_REGEX = props.getProperty("usernameRegex", "^[a-z[A-Z[0-9[äöüÄÖÜß]]]]+$"); 107 userNamePattern = Pattern.compile(AuthManager.instance.USERNAME_REGEX); 108 String classNames = props.getProperty("authenticators", "NoAuthentication"); 109 Server.log(this, "creating new authenticators: " + classNames, Server.MSG_CONFIG, Server.LVL_MINOR); 110 StringTokenizer tok = new StringTokenizer (classNames, ","); 111 Vector tmpList = new Vector (); 112 while (tok.hasMoreTokens()) { 113 String element = tok.nextToken().trim(); 114 String additionalConfigPrefix = null; 115 if (element.indexOf(" ")!=-1) { 116 additionalConfigPrefix = element.substring(element.indexOf(" ")+1).trim(); 117 element = element.substring(0, element.indexOf(" ")); 118 } 119 String className = getClass().getPackage().getName() + "." + element; 120 IAuthenticator authObj = null; 121 try { 122 authObj = (IAuthenticator) Class.forName(className).newInstance(); 123 } catch (Exception ex) { 124 Server.log(this, "Can't load authentication class " + className + ": " + ex.toString(), Server.MSG_ERROR, Server.LVL_MAJOR); 125 continue; 126 } 127 try { 128 authObj.init(props, additionalConfigPrefix); 129 } catch (Exception ex1) { 130 Server.log(this, "Error initializing authentication class " + className + ": " + ex1.toString(), Server.MSG_ERROR, Server.LVL_MAJOR); 131 continue; 132 } 133 tmpList.add(authObj); 134 } 135 if (tmpList.size() == 0) { 136 tmpList.add(new NoAuthentication()); 137 Server.log(this, "No authentication class, starting without authentication", Server.MSG_ERROR, Server.LVL_MAJOR); 138 } 139 list = (IAuthenticator[]) tmpList.toArray(new IAuthenticator[0]); 140 } 141 142 146 public void shutdown() throws Exception { 147 for (int i = 0; i < list.length; i++) { 148 list[i].shutdown(); 149 } 150 } 151 152 156 public User loginUser(String username, String password, String cookie, IRequest req) throws Exception { 157 if (username == null || username.trim().length() < 1) 158 return null; 159 User u = null; 160 for (int i = 0; i < list.length; i++) { 161 if (u == null) { 162 u = list[i].loginUser(username, password, cookie, req); 163 } else { 164 u = list[i].loginUser(u, username, password, req); 165 } 166 if (u == null) { 167 return null; 168 } else if (u.getName() == null || "".equals(u.getName().trim())) { 169 Server.log (this, list[i].toString() + " returned an invalid userobject having no name!", Server.MSG_AUTH, Server.LVL_MAJOR); 170 return null; 171 } 172 } 173 if (u.isUnregistered 174 && !ALLOW_UNREGISTERED_USERS) 175 return null; 176 177 if (u.getColCode() == null 178 || AbstractCommand._isColorCodeValid(u.getColCode().trim().toLowerCase()) != 0) { 179 TemplateSet ts = Server.srv.templatemanager.getTemplateSet ("default"); 180 String templateset = req.getValue ("templateset"); 181 if (templateset != null) { 182 ts = Server.srv.templatemanager.getTemplateSet (templateset); 183 } 184 String col = ts.getMessageTemplate("constant.defaultColor"); 185 if (col == null) 186 col = AuthManager.instance.generateColCode(); 187 u.setColCode(col); 188 Server.log(Thread.currentThread(), this.toString() + "LOGIN set a newly generated colorcode for " + u.getName() + " to " + u.getColCode(), Server.MSG_AUTH, Server.LVL_VERBOSE); 189 } 190 String msList = (String ) u.getProperty("memberships"); 192 if (msList == null) 193 return u; 194 String [] msArr = msList.split(","); 195 for (int i = 0; i < msArr.length; i++) { 196 Membership cms = MembershipManager.instance.getMembership (msArr[i]); 197 if (cms==null) { 198 Server.log (this, "Membership for key " + msArr[i] + " hasn't been found", Server.MSG_STATE, Server.LVL_VERBOSE); 199 continue; 200 } 201 cms.add(u); 202 } 203 return u; 204 } 205 206 207 211 public void updateUsernamePattern(String pattern) { 212 userNamePattern = Pattern.compile(pattern); 213 } 214 215 224 public boolean isValidName(String name) { 225 Matcher m = userNamePattern.matcher(name); 226 return m.matches(); 227 } 228 229 public void logoutUser(User u) throws Exception { 230 for (int i = 0; i < list.length; i++) { 231 list[i].logoutUser(u); 232 } 233 } 234 235 public void doLogin(IRequest cReq, SelectionKey key, String cookie, ContentContainer c, TemplateSet ts, User u, boolean isHTTP11, RequestReader req) { 236 Connection conn = cReq.getConnectionObject(); 238 SocketChannel sc = (SocketChannel ) key.channel (); 239 InetAddress ia = sc.socket ().getInetAddress (); 240 241 String user = cReq.getValue ("user"); 243 if (user == null) 244 user = cReq.getValue ("username"); 245 String pwd = cReq.getValue ("password"); 246 String grp = cReq.getValue ("group"); 247 248 if (user == null || grp == null) { 250 c.setTemplate("login_missing"); 251 return; 252 } 253 254 grp = grp.toLowerCase(); 255 StringBuffer sb = new StringBuffer ("logIN - "); 256 if (Server.srv.USE_TOKENSTORE && !Server.srv.isTokenValid(cReq.getValue("token"), cookie)) { 257 sb.append ("invalid token: "); 258 sb.append (user); 259 sb.append ("@"); 260 sb.append (conn.toString()); 261 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 262 c.setTemplate ("login_missing"); 263 } else if (Server.srv.isBanned (cookie) || Server.srv.isBanned (user) || Server.srv.isBanned(conn)) { 264 sb.append ("user banned: "); 266 sb.append (user); 267 sb.append ("@"); 268 sb.append (conn.toString()); 269 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 270 c.setTemplate ("user_banned"); 271 } else { 272 short result = UserManager.mgr.tryLogin (user, pwd, grp, ts, req, u); 273 req.currPosition=RequestReader.EVAL_POST_LOGIN_RESULT; 274 if (result == UserManager.LOGIN_CANCELED) { 275 sb.append ("login timed out "); 276 sb.append (user); 277 sb.append ("@"); 278 sb.append (conn.toString()); 279 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 280 c.setTemplate("techerror"); 281 } else if (result == UserManager.USEREMAIL_BANED) { 282 sb.append ("user banned: (email-ban)"); 283 sb.append (user); 284 sb.append ("@"); 285 sb.append (conn.toString()); 286 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 287 c.setTemplate ("user_banned"); 288 } else if (result == UserManager.USERNAME_INVALID) { 289 sb.append ("username not valid ("); 290 sb.append (user); 291 sb.append (")"); 292 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 293 c.setTemplate("username_invalid"); 294 } else if (result == UserManager.TECHNICAL_ERROR) { 295 sb.append ("technical errors! Consult error-log."); 296 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 297 c.setTemplate ("techerror"); 298 } else if (result == UserManager.USERNAME_TOO_LONG) { 299 sb.append ("authentication failed: username longer than max-username-length ("); 300 sb.append (Server.srv.MAX_USERNAME_LENGTH); 301 sb.append (")@"); 302 sb.append (conn.toString()); 303 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 304 c.setTemplate("username_too_long"); 305 } else if (result == UserManager.LOGIN_BLOCKED) { 306 sb.append ("authentication failed: login-blocked Nick"); 307 sb.append (user); 308 sb.append ("@"); 309 sb.append (conn.toString()); 310 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 311 c.setTemplate ("user_banned"); 312 } else if (result == UserManager.USERNAME_NOT_ACTIVATED) { 313 sb.append ("authentication failed: username not activated"); 314 sb.append (user); 315 sb.append ("@"); 316 sb.append (conn.toString()); 317 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 318 c.setTemplate ("username_not_activated"); 319 } else if (result == UserManager.LOGIN_GROUP_LOCK) { 320 sb.append ("authentication failed: login-group locked"); 321 sb.append (user); 322 sb.append ("@"); 323 sb.append (conn.toString()); 324 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 325 c.setTemplate ("login_group_locked"); 326 } else if (result == UserManager.LOGIN_GROUP_BAN) { 327 sb.append ("authentication failed: user is banned from startgroup '"); 328 sb.append (grp); 329 sb.append ("' "); 330 sb.append (user); 331 sb.append ("@"); 332 sb.append (conn.toString()); 333 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 334 c.setTemplate ("login_group_banned"); 335 } else if (result == UserManager.LOGIN_OK) { 336 sb.append ("authentication succeeded: "); 337 sb.append (user); 338 sb.append ("@"); 339 sb.append (conn.toString()); 340 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 341 c.setTemplate ("frameset"); 342 } else if (result == UserManager.LOGIN_MISSING) { 343 sb.append ("login missing "); 344 sb.append (conn.toString()); 345 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_VERBOSE); 346 c.setTemplate ("login_missing"); 347 } else if (result == UserManager.MAX_USERS) { 348 sb.append ("max users reached: "); 349 sb.append (user); 350 sb.append ("@"); 351 sb.append (conn.toString()); 352 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 353 c.setTemplate ("too_many_users"); 354 } else if (result == UserManager.LOGIN_COOKIE_MISSING) { 355 sb.append ("no cookie: "); 356 sb.append (user); 357 sb.append ("@"); 358 sb.append (conn.toString ()); 359 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 360 c.setTemplate ("no_cookie"); 361 } else if (result == UserManager.LOGIN_GROUP_MISSING) { 362 sb.append ("no group-name given for login: "); 363 sb.append (user); 364 sb.append ("@"); 365 sb.append (conn.toString()); 366 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_VERBOSE); 367 c.setTemplate ("login_failed"); 368 } else if (result == UserManager.LOGIN_GROUP_NOSTART) { 369 sb.append ("invalid group '"); 370 sb.append (grp); 371 sb.append ("': "); 372 sb.append (user); 373 sb.append ("@"); 374 sb.append (conn.toString ()); 375 Server.log (this, sb.toString (), Server.MSG_AUTH, Server.LVL_MAJOR); 376 c.setTemplate ("login_failed"); 377 } else if (result == UserManager.LOGIN_COOKIE_DUPLICATE) { 378 sb.append ("cookie is present for another user "); 379 sb.append (user); 380 sb.append ("@"); 381 sb.append (conn.toString()); 382 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_VERBOSE); 383 c.setTemplate ("login_failed"); 384 } else if (result == UserManager.LOGIN_PRESENT) { 385 sb.append ("user is already logged in "); 386 sb.append (user); 387 sb.append (conn.toString()); 388 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 389 c.setTemplate ("user_present"); 390 } else if (result == UserManager.LOGIN_RELOAD && u != null) { 391 sb.append ("user hit reload "); 392 sb.append (user); 393 sb.append ("@"); 394 sb.append (conn.toString()); 395 Group g = u.getGroup (); 396 u.setHTTP11 (isHTTP11); 397 if (g != null) { 398 g.addUser (u); 399 c.setTemplate ("frameset"); 400 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_VERBOSE); 401 if (ts != null) 402 u.setTemplateSet (ts); 403 } else { 404 sb.append (" but group was null"); 405 g = GroupManager.mgr.getStartingGroup (grp); 406 if (g == null) { 407 sb.append (" and "); 408 sb.append (grp); 409 sb.append (" is not a starting-group"); 410 c.setTemplate ("login_failed"); 411 } else { 412 sb.append (" - joins group "); 413 sb.append (g.getRawName()); 414 g.addUser (u); 415 c.setTemplate ("frameset"); 416 if (ts != null) 417 u.setTemplateSet (ts); 418 } 419 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MAJOR); 420 } 421 } else { 422 sb.append ("authentication failed: "); 423 sb.append (user); 424 sb.append ("@"); 425 sb.append (conn.toString ()); 426 Server.log (this, sb.toString(), Server.MSG_AUTH, Server.LVL_MINOR); 427 c.setTemplate ("login_failed"); 428 } 429 } 430 } 431 432 436 private String generateColCode () { 437 int r = (int) Math.round(Math.random() * 255); 438 int g = (int) Math.round(Math.random() * 255); 439 int b = (int) Math.round(Math.random() * 255); 440 while ((r+g+b) > 432) { 441 if (r>0) r--; 442 if (g>0) g--; 443 if (b>0) b--; 444 } 445 StringBuffer sb = new StringBuffer (); 446 if (r < 16) 447 sb.append("0"); 448 sb.append (Integer.toHexString(r)); 449 if (g < 16) 450 sb.append("0"); 451 sb.append (Integer.toHexString(g)); 452 if (b < 16) 453 sb.append("0"); 454 sb.append (Integer.toHexString(b)); 455 return sb.toString(); 456 } 457 458 461 462 public File getFile() { 463 return configFile; 464 } 465 466 public boolean filePresent() { 467 return configFile.exists(); 468 } 469 470 public long lastModified() { 471 return configLastModified; 472 } 473 474 public void changed() { 475 configLastModified = configFile.lastModified(); 476 Server.log(this, "authconfig in " + configFile + " changed, reloading.", Server.MSG_CONFIG, Server.LVL_MINOR); 477 synchronized(this) { 478 try { 479 shutdown(); 481 } catch (Exception ex) { 482 } 483 createAuthenticators(); 485 } 486 } 487 488 public void removed() { 489 } 490 491 public void created() { 492 changed(); 493 } 494 495 496 } 497 | Popular Tags |