java/eJabberd-auth/src/cz/frantovo/ejabberd/auth/EJabberdAuth.java
author František Kučera <franta-hg@frantovo.cz>
Mon, 10 Mar 2014 12:20:26 +0100
changeset 26 5d23fa316c1c
permissions -rw-r--r--
eJabberd-auth: ověřování uživatelů proti SQL databázi
     1 /**
     2  * SQL-DK
     3  * Copyright © 2014 František Kučera (frantovo.cz)
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, either version 3 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License
    16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 package cz.frantovo.ejabberd.auth;
    19 
    20 import java.io.DataInputStream;
    21 import java.io.DataOutputStream;
    22 import java.io.FileInputStream;
    23 import java.io.FileOutputStream;
    24 import java.io.IOException;
    25 import java.io.InputStream;
    26 import java.io.OutputStream;
    27 import java.io.PrintStream;
    28 import java.sql.Connection;
    29 import java.sql.DriverManager;
    30 import java.sql.PreparedStatement;
    31 import java.sql.ResultSet;
    32 import java.sql.SQLException;
    33 import java.util.Properties;
    34 
    35 /**
    36  *
    37  * @author Ing. František Kučera (frantovo.cz)
    38  */
    39 public class EJabberdAuth {
    40 
    41 	public static final String NASTAVENÍ_DB_URL = "db.url";
    42 	public static final String NASTAVENÍ_DB_JMÉNO = "db.jmeno";
    43 	public static final String NASTAVENÍ_DB_HESLO = "db.heslo";
    44 	public static final String NASTAVENÍ_DOMÉNA = "domena";
    45 	public static final String NASTAVENÍ_LOG = "log";
    46 	public static final String VÝCHOZÍ_LOG = "/tmp/eJabberd-auth.log";
    47 	private static final int ANO = 1;
    48 	private static final int NE = 0;
    49 	private final DataInputStream in;
    50 	private final DataOutputStream out;
    51 	private final PrintStream err;
    52 	private final String našeDoména;
    53 	private final String dbUrl;
    54 	private final String dbJméno;
    55 	private final String dbHeslo;
    56 
    57 	public static void main(String[] args) throws IOException, ChybaZápisuVýsledku, ChybaČteníVstupu {
    58 
    59 		try (FileInputStream nastaveníFis = new FileInputStream(args[0])) {
    60 
    61 			Properties nastavení = new Properties();
    62 			nastavení.load(nastaveníFis);
    63 
    64 			try (FileOutputStream err = new FileOutputStream(nastavení.getProperty(NASTAVENÍ_LOG, VÝCHOZÍ_LOG))) {
    65 				EJabberdAuth a = new EJabberdAuth(System.in, System.out, err, nastavení);
    66 				a.start();
    67 			}
    68 		}
    69 	}
    70 
    71 	public EJabberdAuth(InputStream in, OutputStream out, OutputStream err, Properties nastavení) {
    72 		this.in = new DataInputStream(in);
    73 		this.out = new DataOutputStream(out);
    74 		this.err = new PrintStream(err);
    75 
    76 		this.našeDoména = nastavení.getProperty(NASTAVENÍ_DOMÉNA);
    77 		this.dbUrl = nastavení.getProperty(NASTAVENÍ_DB_URL);
    78 		this.dbJméno = nastavení.getProperty(NASTAVENÍ_DB_JMÉNO);
    79 		this.dbHeslo = nastavení.getProperty(NASTAVENÍ_DB_HESLO);
    80 	}
    81 
    82 	public void start() throws ChybaZápisuVýsledku, ChybaČteníVstupu {
    83 		while (true) {
    84 			String text = načtiText();
    85 			zpracuj(text);
    86 		}
    87 	}
    88 
    89 	private Connection getDB() throws SQLException {
    90 		return DriverManager.getConnection(dbUrl, dbJméno, dbHeslo);
    91 	}
    92 
    93 	private String načtiText() throws ChybaČteníVstupu {
    94 		try {
    95 			short délka = in.readShort();
    96 			byte[] bajty = new byte[délka];
    97 			in.read(bajty);
    98 			return new String(bajty);
    99 		} catch (Exception e) {
   100 			throw new ChybaČteníVstupu(e);
   101 		}
   102 	}
   103 
   104 	private void zpracuj(String text) throws ChybaZápisuVýsledku {
   105 
   106 		String[] prvky = text.split(":");
   107 
   108 		final String operace;
   109 		final String uživatel;
   110 		final String doména;
   111 		final String heslo;
   112 
   113 		if (prvky.length < 3) {
   114 			zapišVýsledek(NE);
   115 			err.println("Chybný počet parametrů: " + prvky.length);
   116 		} else {
   117 			operace = prvky[0];
   118 			uživatel = prvky[1];
   119 			doména = prvky[2];
   120 			heslo = (prvky.length > 3) ? prvky[3] : null;
   121 
   122 			err.println(operace + ":" + uživatel + ":" + doména + (heslo == null ? "" : ":*"));
   123 
   124 			switch (operace) {
   125 				case "auth":
   126 					ověřHeslo(uživatel, doména, heslo);
   127 					break;
   128 				case "isuser":
   129 					ověřExistenci(uživatel, doména);
   130 					break;
   131 				case "setpass":
   132 				case "tryregister":
   133 				case "removeuser":
   134 				case "removeuser3":
   135 				default:
   136 					zapišVýsledek(NE);
   137 			}
   138 		}
   139 	}
   140 
   141 	private void zapišVýsledek(int výsledek) throws ChybaZápisuVýsledku {
   142 		try {
   143 			err.println("výsledek: " + výsledek);
   144 
   145 			out.writeShort(2);
   146 			out.writeShort(výsledek);
   147 			out.flush();
   148 		} catch (Exception e) {
   149 			throw new ChybaZápisuVýsledku(e);
   150 		}
   151 	}
   152 
   153 	private void ověřHeslo(String uživatel, String doména, String heslo) throws ChybaZápisuVýsledku {
   154 		if (ověřDoménu(doména)) {
   155 
   156 			try (Connection db = getDB()) {
   157 				try (PreparedStatement ps = db.prepareStatement("SELECT over_heslo(?,?)")) {
   158 					int i = 1;
   159 					ps.setString(i++, uživatel);
   160 					ps.setString(i++, heslo);
   161 					try (ResultSet rs = ps.executeQuery()) {
   162 						rs.next();
   163 						int výsledek = rs.getBoolean(1) ? ANO : NE;
   164 						zapišVýsledek(výsledek);
   165 					}
   166 				}
   167 			} catch (SQLException e) {
   168 				logujSQLException(e);
   169 				zapišVýsledek(NE);
   170 			}
   171 
   172 		} else {
   173 			zapišVýsledek(NE);
   174 		}
   175 	}
   176 
   177 	private void ověřExistenci(String uživatel, String doména) throws ChybaZápisuVýsledku {
   178 		if (ověřDoménu(doména)) {
   179 
   180 			try (Connection db = getDB()) {
   181 				try (PreparedStatement ps = db.prepareStatement("SELECT over_existenci_uzivatele(?)")) {
   182 					int i = 1;
   183 					ps.setString(i++, uživatel);
   184 					try (ResultSet rs = ps.executeQuery()) {
   185 						rs.next();
   186 						int výsledek = rs.getBoolean(1) ? ANO : NE;
   187 						zapišVýsledek(výsledek);
   188 					}
   189 				}
   190 			} catch (SQLException e) {
   191 				logujSQLException(e);
   192 				zapišVýsledek(NE);
   193 			}
   194 
   195 		} else {
   196 			zapišVýsledek(NE);
   197 		}
   198 	}
   199 
   200 	private boolean ověřDoménu(String doména) {
   201 		return našeDoména.equalsIgnoreCase(doména);
   202 	}
   203 
   204 	private void logujSQLException(SQLException e) {
   205 		err.println("-- SQLException:");
   206 		e.printStackTrace(err);
   207 		err.println("-- SQLException");
   208 	}
   209 }