From 1f490c5aa0714c622b03fc2ec56909af7703ccab Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 16 Aug 2017 18:26:02 +0200 Subject: [*ldap*] Support new mapping features and fixNumeric switch --- .../org/openslx/satserver/util/LdapMapping.java | 44 +++++++++++ .../taskmanager/tasks/CreateLdapConfig.java | 59 +++++++++++---- .../org/openslx/taskmanager/tasks/LdapSearch.java | 87 ++++++++++++++-------- 3 files changed, 144 insertions(+), 46 deletions(-) create mode 100644 src/main/java/org/openslx/satserver/util/LdapMapping.java diff --git a/src/main/java/org/openslx/satserver/util/LdapMapping.java b/src/main/java/org/openslx/satserver/util/LdapMapping.java new file mode 100644 index 0000000..f734a1d --- /dev/null +++ b/src/main/java/org/openslx/satserver/util/LdapMapping.java @@ -0,0 +1,44 @@ +package org.openslx.satserver.util; + +import com.google.gson.annotations.Expose; + +public class LdapMapping +{ + @Expose + public String uid; // AD: sAMAccountName + @Expose + public String homemount; // AD: homeDirectory + @Expose + public String localhome; // AD: none, LDAP: homeDirectory + @Expose + public String posixAccount; // AD: user + @Expose + public String shadowAccount; // AD: user + @Expose + public String uidnumber; // AD: objectSid + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + if ( !Util.isEmpty( uid ) ) { + sb.append( "map.uid=" + uid + "\n" ); + } + if ( !Util.isEmpty( homemount ) ) { + sb.append( "map.homemount=" + homemount + "\n" ); + } + if ( !Util.isEmpty( localhome ) ) { + sb.append( "map.localhome=" + localhome + "\n" ); + } + if ( !Util.isEmpty( posixAccount ) ) { + sb.append( "map.posixAccount=" + posixAccount + "\n" ); + } + if ( !Util.isEmpty( shadowAccount ) ) { + sb.append( "map.shadowAccount=" + shadowAccount + "\n" ); + } + if ( !Util.isEmpty( uidnumber ) ) { + sb.append( "map.uidnumber=" + uidnumber + "\n" ); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/org/openslx/taskmanager/tasks/CreateLdapConfig.java b/src/main/java/org/openslx/taskmanager/tasks/CreateLdapConfig.java index 30f1935..208cd8d 100644 --- a/src/main/java/org/openslx/taskmanager/tasks/CreateLdapConfig.java +++ b/src/main/java/org/openslx/taskmanager/tasks/CreateLdapConfig.java @@ -2,6 +2,7 @@ package org.openslx.taskmanager.tasks; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -10,10 +11,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.log4j.Logger; import org.openslx.satserver.util.Archive; import org.openslx.satserver.util.Constants; import org.openslx.satserver.util.Exec; import org.openslx.satserver.util.Exec.ExecCallback; +import org.openslx.satserver.util.LdapMapping; import org.openslx.satserver.util.Template; import org.openslx.satserver.util.Util; import org.openslx.taskmanager.api.AbstractTask; @@ -22,7 +26,10 @@ import com.google.gson.annotations.Expose; public class CreateLdapConfig extends AbstractTask { + private static final Logger LOGGER = Logger.getLogger( CreateLdapConfig.class ); public static final String DEFAULT_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; + protected static final String[] ALLOWED_DIRS = + { "/tmp/", "/opt/openslx/configs/" }; @Expose private int moduleid = 0; @@ -52,6 +59,10 @@ public class CreateLdapConfig extends AbstractTask private String certificate; @Expose private boolean plainldap = false; + @Expose + private String fixnumeric = null; + @Expose + private LdapMapping mapping; // Share mode stuff @Expose @@ -88,16 +99,36 @@ public class CreateLdapConfig extends AbstractTask status.error = "Missing argument to task"; return false; } - if ( this.home == null ) - this.home = ""; - if ( this.binddn == null ) - this.binddn = ""; - if ( this.bindpw == null ) - this.bindpw = ""; - if ( this.certificate == null ) - this.certificate = ""; - if ( this.fingerprint == null ) - this.fingerprint = ""; + filename = FilenameUtils.normalize( filename ); + if ( !Util.startsWith( filename, ALLOWED_DIRS ) ) { + status.error = "Illegal target directory " + filename; + return false; + } + for ( Field field : CreateLdapConfig.class.getDeclaredFields() ) { + if ( field.isAnnotationPresent( Expose.class ) && field.getType().equals( String.class ) ) { + field.setAccessible( true ); + Object ret; + try { + ret = field.get( this ); + } catch ( IllegalArgumentException | IllegalAccessException e1 ) { + ret = null; + LOGGER.warn( "Cannot get field " + field.getName() ); + } + if ( ret == null ) { + try { + field.set( this, "" ); + } catch ( IllegalArgumentException | IllegalAccessException e ) { + LOGGER.warn( "Cannot set field " + field.getName() ); + } + } + } + } + if ( mapping == null ) { + mapping = new LdapMapping(); + } + if ( Util.isEmpty( mapping.homemount ) && !Util.isEmpty( this.homeattr ) ) { + mapping.homemount = this.homeattr; + } return true; } @@ -160,7 +191,7 @@ public class CreateLdapConfig extends AbstractTask } else if ( !this.certificate.isEmpty() && !this.certificate.equals( "false" ) ) { // Write out try { - FileUtils.writeStringToFile( caFile, this.certificate ); + FileUtils.writeStringToFile( caFile, this.certificate, StandardCharsets.UTF_8 ); } catch ( Exception e ) { status.error = "Could not write trusted certificate(s) to file " + caFile.getAbsolutePath(); return false; @@ -175,11 +206,12 @@ public class CreateLdapConfig extends AbstractTask + "bindpw=%s\n" + "base=%s\n" + "home=%s\n" - + "homeattr=%s\n" + "port=%s\n" + "fingerprint=%s\n" + "cabundle=%s\n" + "plainldap=%s\n" + + "fixnumeric=%s\n" + + "%s\n" + "[local]\n" + "port=%s\n" + "cert=%s\n" @@ -190,11 +222,12 @@ public class CreateLdapConfig extends AbstractTask this.bindpw, this.searchbase, this.home, - this.homeattr, this.adport, this.fingerprint, caPath, Boolean.toString( this.plainldap ), + this.fixnumeric == null ? "" : this.fixnumeric, + this.mapping.toString(), this.proxyport, certFile, keyFile ); diff --git a/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java b/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java index 63ce60a..f5e5f7a 100644 --- a/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java +++ b/src/main/java/org/openslx/taskmanager/tasks/LdapSearch.java @@ -9,6 +9,8 @@ import java.util.Random; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; +import org.openslx.satserver.util.LdapMapping; +import org.openslx.satserver.util.Util; import org.openslx.taskmanager.api.SystemCommandTask; import com.google.gson.annotations.Expose; @@ -30,12 +32,16 @@ public class LdapSearch extends SystemCommandTask private boolean plainldap = false; @Expose private String filter = null; + @Expose + private LdapMapping mapping = null; private String fifo = null; private boolean getDn = false; private volatile int userCount = 0; + + private volatile int userIdCount = 0; private Output status = new Output(); @@ -58,6 +64,31 @@ public class LdapSearch extends SystemCommandTask @Override protected String[] initCommandLine() { + if ( this.mapping == null ) + this.mapping = new LdapMapping(); + if ( this.plainldap ) { + if ( Util.isEmpty( mapping.posixAccount ) ) { + mapping.posixAccount = "posixAccount"; + } + if ( Util.isEmpty( mapping.uid ) ) { + mapping.uid = "uid"; + } + if ( Util.isEmpty( mapping.uidnumber ) ) { + mapping.uidnumber = "uidnumber"; + } + } else { + if ( Util.isEmpty( mapping.posixAccount ) ) { + mapping.posixAccount = "user"; + } + if ( Util.isEmpty( mapping.uid ) ) { + mapping.uid = "sAMAccountName"; + } + if ( Util.isEmpty( mapping.uidnumber ) ) { + mapping.uidnumber = "objectSid"; + } + } + mapping.uid = mapping.uid.toLowerCase(); + mapping.uidnumber = mapping.uidnumber.toLowerCase(); if ( !this.bindpw.isEmpty() ) { this.fifo = String.format( "/tmp/bwlp-%s-%s.ldap", System.currentTimeMillis(), new Random().nextInt() ); File pwFile = new File( this.fifo ); @@ -76,19 +107,15 @@ public class LdapSearch extends SystemCommandTask } String filter; if ( this.filter == null || this.filter.isEmpty() ) { - status.addMessage( "Trying to find 4 random AD users to verify everything is all right..." ); - if ( this.plainldap ) { - filter = "(&(objectClass=posixAccount)(uid=*))"; - } else { - filter = "(&(objectClass=user)(objectClass=person)(sAMAccountName=*))"; - } + status.addMessage( "Trying to find 4 random users to verify everything is all right..." ); + filter = "(&(objectClass=" + mapping.posixAccount + ")(" + mapping.uid + "=*)(" + mapping.uidnumber + "=*))"; } else { this.getDn = true; filter = this.filter; } - // As we don't care about the certificate here, you might want to put TLS_REQCERT never status.addMessage( "Using filter: " + filter ); + // As we don't care about the certificate here, you might want to put TLS_REQCERT never // in /etc/ldap/ldap.conf if ( this.bindpw.isEmpty() ) { return new String[] { @@ -130,38 +157,32 @@ public class LdapSearch extends SystemCommandTask if ( exitCode == 4 ) // Means size limit exceeded, ignore exitCode = 0; status.addMessage( "Exit code is " + exitCode ); - if ( exitCode == 0 && this.userCount < 4 && !this.getDn ) - status.addMessage( "Found less than 4 users. Are you sure you got the right credentials?" ); - return this.userCount >= 4 || ( this.getDn && status.dn != null ); + if ( exitCode == 0 && !this.getDn ) { + if ( this.userCount < 4 ) { + status.addMessage( "Found less than 4 users. Are you sure you got the right credentials?" ); + } + if ( this.userIdCount < 4 ) { + status.addMessage( "Found less than 4 user ids. Are you sure you got the right credentials?" ); + } + } + return ( this.userCount >= 4 && this.userIdCount >= 4 ) || ( this.getDn && status.dn != null ); } @Override protected void processStdOut( String line ) { - if ( this.plainldap ) { - if ( line.startsWith( "uid: " ) ) { - status.addMessage( "Found LDAP user " + line.substring( 5 ) + " :-)" ); - this.userCount++; - return; - } - if ( line.startsWith( "uid:: " ) ) { - status.addMessage( "Found LDAP user " + line.substring( 6 ) + " :-)" ); - this.userCount++; - return; - } - } else { - if ( line.startsWith( "sAMAccountName: " ) ) { - status.addMessage( "Found AD user " + line.substring( 16 ) + " :-)" ); - this.userCount++; - return; - } - if ( line.startsWith( "sAMAccountName:: " ) ) { - status.addMessage( "Found AD user " + line.substring( 17 ) + " :-)" ); - this.userCount++; - return; - } + String lower = line.toLowerCase(); + if ( lower.startsWith( mapping.uid + ":" ) ) { + status.addMessage( "Found " + line + " :-)" ); + this.userCount++; + return; + } + if ( lower.startsWith( mapping.uidnumber + ":" ) ) { + status.addMessage( "Found " + line + " :-)" ); + this.userIdCount++; + return; } - if ( line.startsWith( "dn: " ) ) { + if ( lower.startsWith( "dn: " ) ) { status.dn = line.substring( 4 ); return; } -- cgit v1.2.3-55-g7522