--- /dev/null
+module DDNS.Server
+ ( ensureWeHaveKeypair
+ , ensureWeHaveDB
+ )
+ where
+
+import Control.Monad
+import Control.Monad.Trans
+import DDNS.DBInfo
+import DDNS.Utils
+import Data.Time.Clock
+import qualified Database.HDBC as RAW
+import qualified Database.HDBC.Sqlite3 as RAW
+import Database.HaskellDB
+import Database.HaskellDB.DBSpec
+import Database.HaskellDB.HDBC.SQLite3
+import OpenSSL.EVP.PKey
+import OpenSSL.PEM
+import OpenSSL.RSA
+import OpenSSL.X509 as X509
+import System.Console.Haskeline
+import System.Directory
+import System.FilePath
+import System.IO
+import System.Posix.Files
+import System.Posix.Uname
+
+ensureWeHaveKeypair :: FilePath -> IO (SomeKeyPair, X509)
+ensureWeHaveKeypair lsdir
+ = do let keyFile = lsdir </> "server.key"
+ certFile = lsdir </> "server.cert"
+ keyExi <- doesFileExist keyFile
+ cerExi <- doesFileExist certFile
+ if keyExi && cerExi then
+ do key <- flip readPrivateKey PwNone =<< readFile keyFile
+ cert <- readX509 =<< readFile certFile
+ return (key, cert)
+ else
+ do fqdn <- runInputT defaultSettings $
+ do defaultFqdn <- liftM uNodeName $ liftIO uname
+ fqdn <- getInputLine ("What's your FQDN? (default: " ++ defaultFqdn ++ "): ")
+ case trim fqdn of
+ Just s -> return s
+ _ -> return defaultFqdn
+
+ putStrLn "Generating RSA keypair..."
+ key <- generateRSAKey 1024 3 Nothing
+ withFile keyFile WriteMode $ \ h ->
+ writePKCS8PrivateKey key Nothing >>= hPutStr h
+ setFileMode keyFile ownerReadMode
+ putStrLn ("Wrote " ++ keyFile)
+
+ cert <- newX509
+ X509.setVersion cert 2
+ X509.setSerialNumber cert 1
+ X509.setIssuerName cert [("CN", fqdn)]
+ X509.setSubjectName cert [("CN", fqdn)]
+ X509.setNotBefore cert =<< liftM (addUTCTime (-1)) getCurrentTime
+ X509.setNotAfter cert =<< liftM (addUTCTime (20 * 365 * 24 * 60 * 60)) getCurrentTime
+ X509.setPublicKey cert key
+ X509.signX509 cert key Nothing
+ withFile certFile WriteMode $ \ h ->
+ writeX509 cert >>= hPutStr h
+ putStrLn ("Wrote " ++ certFile)
+
+ return (fromKeyPair key, cert)
+
+type WithDB a = (Database -> IO a) -> IO a
+
+ensureWeHaveDB :: FilePath -> IO (WithDB a)
+ensureWeHaveDB lsdir
+ = do let dbFile = lsdir </> "server.db"
+ dbExist <- doesFileExist dbFile
+ unless dbExist $
+ do sqliteConnect dbFile $ \ db ->
+ dbSpecToDatabase db dbinfo
+
+ rawCon <- RAW.connectSqlite3 dbFile
+ mapM_ (\ sql -> RAW.run rawCon sql []) indexDeclarations
+ RAW.commit rawCon
+ RAW.disconnect rawCon
+ return $ sqliteConnect dbFile