Skip to content
Permalink
Browse files Browse the repository at this point in the history
Protection against sql injection doesnt work with ? for table. Using …
…HTMLEscapeString instead
  • Loading branch information
micha-p committed Jan 25, 2015
1 parent e951aa2 commit 76db54e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 39 deletions.
17 changes: 9 additions & 8 deletions README.md
Expand Up @@ -7,13 +7,13 @@ Use your fantasy for best UX and choose high levels of abstraction and imaginati

## prepare

sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf create gotestdb
sudo mysql --defaults-file=/etc/mysql/debian.cnf -e "GRANT ALL PRIVILEGES ON gotestdb.* TO 'go_user'@'localhost' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;"
mysql -p"mypassword" -u go_user gotestdb -e 'create table posts (title varchar(64) default null, start date default null);'
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("hello","2015-01-01");'
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("more","2015-01-03");'
mysql -p"mypassword" -u go_user gotestdb -e 'insert into posts values("end","2015-01-23");'
mysql -p"mypassword" -u go_user gotestdb -B -e 'select * from posts;'
sudo mysqladmin --defaults-file=/etc/mysql/debian.cnf create galadb
sudo mysql --defaults-file=/etc/mysql/debian.cnf -e "GRANT ALL PRIVILEGES ON galadb.* TO 'galagopher'@'localhost' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;"
mysql -p"mypassword" -u galagopher galadb -e 'create table posts (title varchar(64) default null, start date default null);'
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("hello","2015-01-01");'
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("more","2015-01-03");'
mysql -p"mypassword" -u galagopher galadb -e 'insert into posts values("end","2015-01-23");'
mysql -p"mypassword" -u galagopher galadb -B -e 'select * from posts;'

## install

Expand All @@ -38,7 +38,8 @@ Use your fantasy for best UX and choose high levels of abstraction and imaginati

## perspectives

. output in tables
- output in tables
- menu line
- choice for different database drivers
- insert and edit records

Expand Down
32 changes: 20 additions & 12 deletions auth.go
@@ -1,4 +1,4 @@
/* no Credentials management needed
/* no session management needed
* Credentials are stored at user side using secure cookies
*
* credits:
Expand All @@ -16,25 +16,29 @@ var cookieHandler = securecookie.New(
securecookie.GenerateRandomKey(64),
securecookie.GenerateRandomKey(32))

func getCredentials(request *http.Request) (userName string, password string) {
if cookie, err := request.Cookie("Credentials"); err == nil {
func getCredentials(request *http.Request) (userName string, password string, host string, port string) {
if cookie, err := request.Cookie("Datasource"); err == nil {
cookieValue := make(map[string]string)
if err = cookieHandler.Decode("Credentials", cookie.Value, &cookieValue); err == nil {
if err = cookieHandler.Decode("Datasource", cookie.Value, &cookieValue); err == nil {
userName = cookieValue["user"]
password = cookieValue["passwd"]
host = cookieValue["host"]
port = cookieValue["port"]
}
}
return userName, password
return userName, password, host, port
}

func setCredentials(userName string, pw string, w http.ResponseWriter) {
func setCredentials( w http.ResponseWriter, userName string, pw string, host string, port string) {
value := map[string]string{
"user": userName,
"passwd": pw,
"host": host,
"port": port,
}
if encoded, err := cookieHandler.Encode("Credentials", value); err == nil {
if encoded, err := cookieHandler.Encode("Datasource", value); err == nil {
cookie := &http.Cookie{
Name: "Credentials",
Name: "Datasource",
Value: encoded,
Path: "/",
}
Expand All @@ -44,7 +48,7 @@ func setCredentials(userName string, pw string, w http.ResponseWriter) {

func clearCredentials(w http.ResponseWriter) {
cookie := &http.Cookie{
Name: "Credentials",
Name: "Datasource",
Value: "",
Path: "/",
MaxAge: -1,
Expand All @@ -55,8 +59,10 @@ func clearCredentials(w http.ResponseWriter) {
func loginHandler(w http.ResponseWriter, request *http.Request) {
user := request.FormValue("user")
pass := request.FormValue("password")
host := request.FormValue("host")
port := request.FormValue("port")
if user != "" && pass != "" {
setCredentials(user, pass, w)
setCredentials(w, user, pass, host, port)
}
http.Redirect(w, request, "/", 302)
}
Expand All @@ -69,8 +75,10 @@ func logoutHandler(w http.ResponseWriter, request *http.Request) {
const loginPage = `
<h1>Login</h1>
<form method="post" action="/login">
<label for="user">User name</label><input type="text" id="user" name="user">
<label for="password">Password</label><input type="password" id="password" name="password">
<label for="user">User name</label><input type="text" id="user" name="user"><br>
<label for="password">Password</label><input type="password" id="password" name="password"><br>
<label for="host">Host</label><input type="text" id="host" name="host" value="localhost"><br>
<label for="port">Port</label><input type="text" id="port" name="port" value="3306"><br>
<button type="submit">Login</button>
</form>
`
2 changes: 1 addition & 1 deletion aux.go
Expand Up @@ -21,7 +21,7 @@ func linkDeeper(cwd string, link string, name string) string {
}

// Compose dataSourceName from components and globals
func dsn(user string, pw string, db string) string {
func dsn(user string, pw string, host string, port string, db string) string {
return user + ":" + pw + "@tcp(" + host + ":" + port + ")/" + db
}

Expand Down
27 changes: 14 additions & 13 deletions dump.go
@@ -1,7 +1,7 @@
package main

/* TODO
* turn into generic functions
* turn into more generic functions for printing into tables
*/

import (
Expand All @@ -11,13 +11,14 @@ import (
"net/http"
"strconv"
"strings"
"text/template"
)

// Shows selection of databases at top level
func home(w http.ResponseWriter, r *http.Request) {

user, pw := getCredentials(r)
conn, err := sql.Open("mysql", dsn(user, pw, database))
user, pw, h , p := getCredentials(r)
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
checkY(err)
defer conn.Close()

Expand All @@ -41,9 +42,9 @@ func home(w http.ResponseWriter, r *http.Request) {
// Dump all tables of a database
func dumpdb(w http.ResponseWriter, r *http.Request, parray []string) {

user, pw := getCredentials(r)
user, pw, h, p := getCredentials(r)
database := parray[0]
conn, err := sql.Open("mysql", dsn(user, pw, database))
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
checkY(err)
defer conn.Close()

Expand All @@ -67,18 +68,18 @@ func dumpdb(w http.ResponseWriter, r *http.Request, parray []string) {
// Dump all records of a table, one per line
func dumptable(w http.ResponseWriter, r *http.Request, parray []string) {

user, pw := getCredentials(r)
user, pw, h, p := getCredentials(r)
database := parray[0]
table := parray[1]

conn, err := sql.Open("mysql", dsn(user, pw, database))
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
checkY(err)
defer conn.Close()

statement, err := conn.Prepare("select * from ?")
statement, err := conn.Prepare("select * from " + template.HTMLEscapeString(table))
checkY(err)

rows, err := statement.Query(table)
rows, err := statement.Query()
checkY(err)
defer rows.Close()

Expand Down Expand Up @@ -123,15 +124,15 @@ func dumprecord(w http.ResponseWriter, r *http.Request, parray []string) {
rec, err := strconv.Atoi(parray[2])
checkY(err)

user, pw := getCredentials(r)
conn, err := sql.Open("mysql", dsn(user, pw, database))
user, pw, h, p := getCredentials(r)
conn, err := sql.Open("mysql", dsn(user, pw, h, p, database))
checkY(err)
defer conn.Close()

statement, err := conn.Prepare("select * from ?")
statement, err := conn.Prepare("select * from " + template.HTMLEscapeString(table))
checkY(err)

rows, err := statement.Query(table)
rows, err := statement.Query()
checkY(err)
defer rows.Close()

Expand Down
8 changes: 3 additions & 5 deletions sqldump.go
Expand Up @@ -7,8 +7,6 @@ import (
)

var base_url = "http://localhost"
var host = "localhost"
var port = "3306"
var database = "information_schema"

func faviconHandler(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -38,10 +36,10 @@ func pathHandler(w http.ResponseWriter, r *http.Request) {
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
u, _ := getCredentials(r)
user , _ , host , port := getCredentials(r)

if u != "" {
fmt.Fprintln(w, "<h1>", u, "</h1>")
if user != "" {
fmt.Fprintln(w, "<p>", user + "@" + host + ":" + port, "</p>")
pathHandler(w, r)
} else {
loginPageHandler(w, r)
Expand Down

0 comments on commit 76db54e

Please sign in to comment.