Initial import

This commit is contained in:
Eirik Alderslyst Nygaard 2007-02-13 20:57:45 +00:00
parent 63a12324f4
commit 8ab4673bd5
11 changed files with 866 additions and 0 deletions

3
Makefile Normal file
View File

@ -0,0 +1,3 @@
SUBDIR= psqldbadm psqluseradm
.include <bsd.subdir.mk>

19
README Normal file
View File

@ -0,0 +1,19 @@
PSQL-adm tools.
Disallow usage and create as default settings for newly created databases, done
in template1:
REVOKE USAGE ON SCHEMA public FROM public;
REVOKE CREATE ON SCHEMA public FROM public;
For every newly created database a schema with the same name as the specified
owner will be created, and the owner will have full authorization over it.
Two databases are used to keep information related to whom owns a user or
database, their structure can be found in tables.sql.
Database information is for now hardcoded into 'psqluseradm/psql.config.h', and
if you change that info you must recompile for them to take effect.
The dbname and dbuser must start with the username of the caller.
- Eirik Nygaard <eirikald@pvv.ntnu.no>

3
TODO Normal file
View File

@ -0,0 +1,3 @@
* Add PQclear(res) all over the place
* Split out common parts from psql-[user|db]adm
* Learn english

13
psqldbadm/Makefile Normal file
View File

@ -0,0 +1,13 @@
.PATH: ${.CURDIR} ${.CURDIR}/../psqluseradm/
CFLAGS= -I/usr/local/include
LDFLAGS=-L/usr/local/lib -lpq
PROG= psql-dbadm
SRCS= psql-dbadm.c psqladm.c
NO_MAN= true
WARNS?= 6
.include <bsd.prog.mk>

323
psqldbadm/psql-dbadm.c Normal file
View File

@ -0,0 +1,323 @@
/*-
* Copyright (c) 2005 Eirik A. Nygaard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include <pwd.h>
#include <libpq-fe.h>
#include "../psqluseradm/psql.config.h"
#include "../psqluseradm/psqladm.h"
#define ACTION_ADD 1
#define ACTION_DELETE 2
#define ACTION_EDIT 3
#define ACTION_LIST 4
PGconn *pgconn;
void usage(void);
int createdatabase(char *dbname, char *owner, uid_t uid, char *encoding);
int verify_owner(char *dbname, uid_t uid);
void listdatabases(uid_t uid);
int dropdatabase(char *dbname);
char *first_dbuser(uid_t uid);
void create_schema(char *name, char *owner, PGconn *conn);
int
main(int argc, char **argv)
{
uid_t uid;
int action = 0, c;
char *dbname = NULL, *owner = NULL;
char _dbname[1024], _owner[1024];
char *encoding, _encoding[1024];
while ((c = getopt(argc, argv, "hadlu:o:E:")) != -1) {
switch (c) {
case 'h':
usage();
exit(1);
case 'a':
action = ACTION_ADD;
break;
case 'd':
action = ACTION_DELETE;
break;
case 'e':
action = ACTION_EDIT;
break;
case 'l':
action = ACTION_LIST;
break;
case 'u':
dbname = optarg;
break;
case 'o':
owner = optarg;
break;
case 'E':
encoding = optarg;
break;
default:
fprintf(stderr, "Unknown argument: '%c'\n", c);
usage();
exit(1);
}
}
argc -= optind;
argv += optind;
if (!dbname && argc > 0) {
dbname = argv[0];
argc--;
argv++;
}
if (!owner && argc > 0) {
owner = argv[0];
argc--;
argv++;
}
if (!dbname &&
(action == ACTION_ADD || action == ACTION_EDIT || action == ACTION_DELETE)) {
usage();
errx(1, "Specify dbname!");
}
if (action == 0) {
usage();
errx(1, "No action specified!");
}
uid = get_cred();
pgconn = db_connect(PSQL_USER, PSQL_PASSWORD, PSQL_DBNAME, PSQL_HOST);
/* verify input */
if (dbname && !verifystr(dbname, STR_TYPE_NAME))
errx(1, "Invalid dbname input");
if (owner && !verifystr(owner, STR_TYPE_NAME))
errx(1, "Invalid owner input");
if (encoding && !verifystr(encoding, STR_TYPE_NAME))
errx(1, "Invalid encoding input");
if (dbname) {
struct passwd *passwd;
if (strlen(dbname) > 1000)
errx(1, "Too long dbname");
PQescapeString(_dbname, dbname, MIN(strlen(dbname), sizeof(_dbname)));
passwd = getpwuid(uid);
if (!passwd)
errx(1, "Unable to get login info");
if (!verify_startwith(dbname, passwd->pw_name))
errx(1, "Your database must start with your username");
}
if (!owner) {
if ((owner = first_dbuser(uid)) == NULL)
errx(1, "You must create a database user first");
printf("Defaulting to '%s' as dbowner!\n", owner);
}
if (encoding) {
PQescapeString(_encoding, encoding, MIN(strlen(encoding), sizeof(_encoding)));
encoding = _encoding;
}
if (strlen(owner) > 1000)
errx(1, "Too long owner name");
PQescapeString(_owner , owner, MIN(strlen(owner), sizeof(_owner)));
switch (action) {
case ACTION_ADD:
fprintf(stderr, "Creating database %s... ", _dbname);
if (createdatabase(_dbname, _owner, uid, encoding) != 0)
errx(1, "Unable to add new user");
break;
case ACTION_DELETE:
if (!verify_owner(_dbname, uid))
errx(1, "You are not the owner for that dbuser.");
fprintf(stderr, "Deleting user... ");
dropdatabase(dbname);
break;
case ACTION_EDIT:
if (!verify_owner(_dbname, uid))
errx(1, "You are not the owner for that dbuser.");
fprintf(stderr, "Editing user... nothing to do here, sorry!\n");
break;
case ACTION_LIST:
listdatabases(uid);
}
return(0);
}
void
usage(void)
{
fprintf(stderr, "psql-dbadm [-h] [-a] [-d] [-l] [-E encoding] [dbname [owner]]\n");
fprintf(stderr, "\t-h: This help screen\n");
fprintf(stderr, "\t-a: Create a new database\n");
fprintf(stderr, "\t-d: Drop a database\n");
fprintf(stderr, "\t-l: List your databases\n");
fprintf(stderr, "\t-E encoding: Specify encoding when you create a database\n");
}
int
createdatabase(char *dbname, char *owner, uid_t uid, char *encoding)
{
char query[1024];
int nfields;
PGresult *res;
PGconn *newpgconn;
snprintf(query, sizeof(query), "SELECT id FROM psqldbadm WHERE dbname = '%s'", dbname);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "Could not execute query: '%s': %s", query, PQerrorMessage(pgconn));
nfields = PQntuples(res);
if (nfields > 0)
errx(1, "A database with that name already exists");
snprintf(query, sizeof(query), "CREATE DATABASE %s OWNER = %s ",
dbname, owner);
if (encoding) {
char enc[1024];
snprintf(enc, sizeof(enc), " ENCODING '%s'", encoding);
strncat(query, enc, sizeof(query) - strlen(query));
}
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to add info db: %s", PQerrorMessage(pgconn));
snprintf(query, sizeof(query), "INSERT INTO psqldbadm (uid, dbname, owner) " \
"VALUES(%d, '%s', '%s')",
uid, dbname, owner);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to add database: %s", PQerrorMessage(pgconn));
snprintf(query, sizeof(query), "GRANT ALL ON DATABASE %s TO %s", dbname, owner);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to grant owner access to database: %s", PQerrorMessage(pgconn));
printf("done!\n");
newpgconn = db_connect(PSQL_USER, PSQL_PASSWORD, (const char *)dbname, PSQL_HOST);
create_schema(owner, owner, newpgconn);
return(0);
}
void
create_schema(char *name, char *owner, PGconn *conn)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "CREATE SCHEMA %s AUTHORIZATION %s", name, owner);
res = PQexec(conn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to create user schema: %s", PQerrorMessage(conn));
}
void
listdatabases(uid_t uid)
{
char query[1024];
PGresult *res;
int i, nfields;
snprintf(query, sizeof(query), "SELECT dbname, owner, ts FROM psqldbadm WHERE uid = %d", uid);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "unable to list databases: %s: %s", query, PQerrorMessage(pgconn));
nfields = PQnfields(res);
printf("%-15s %-15s %-15s\n", "DB", "DBowner", "Created");
for (i = 0; i < PQntuples(res); i++) {
/* XXX: Format timestamp... */
printf("%-15s %-15s %-15s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1),
PQgetvalue(res, i, 2));
}
if (PQntuples(res) == 0)
printf("You don't have any databases...\n");
}
int
dropdatabase(char *dbname)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "DROP DATABASE %s", dbname);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to drop database: %s: %s", query, PQerrorMessage(pgconn));
snprintf(query, sizeof(query), "DELETE FROM psqldbadm WHERE dbname = '%s'", dbname);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to delete info database: %s: %s", query, PQerrorMessage(pgconn));
printf("done!\n");
return(0);
}
int
verify_owner(char *dbname, uid_t uid)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "SELECT id FROM psqldbadm " \
"WHERE dbname = '%s' AND uid = %d",
dbname, uid);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "verify query failed: %s: %s", query, PQerrorMessage(pgconn));
if (PQntuples(res) > 0)
return(1);
return(0);
}
char *
first_dbuser(uid_t uid)
{
char query[1024];
char *owner;
PGresult *res;
snprintf(query, sizeof(query), "SELECT username FROM psqluseradm WHERE uid = %d LIMIT 1", uid);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "could not find first dbuser: %s: %s", query, PQerrorMessage(pgconn));
if (PQntuples(res) == 0)
return(NULL);
owner = PQgetvalue(res, 0, 0);
return(owner);
}

11
psqluseradm/Makefile Normal file
View File

@ -0,0 +1,11 @@
CFLAGS= -I/usr/local/include
LDFLAGS=-L/usr/local/lib -lpq
PROG= psql-useradm
SRCS= psql-useradm.c psqladm.c
NO_MAN= true
WARNS?= 6
.include <bsd.prog.mk>

315
psqluseradm/psql-useradm.c Normal file
View File

@ -0,0 +1,315 @@
/*-
* Copyright (c) 2005 Eirik A. Nygaard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include <pwd.h>
#include <libpq-fe.h>
#include "psql.config.h"
#include "psqladm.h"
#define ACTION_ADD 1
#define ACTION_DELETE 2
#define ACTION_EDIT 3
#define ACTION_LIST 4
#define ACTION_CHPASS 5
PGconn *pgconn;
void usage(void);
int adduser(char *username, char *password, uid_t uid);
int verify_owner(char *username, uid_t uid);
void listusers(uid_t uid);
int dropuser(char *username);
void change_password(char *username, char *password);
int
main(int argc, char **argv)
{
uid_t uid;
int action = 0, c;
char *username = NULL, *password = NULL;
char *newpassword = NULL;
char _username[1024], _password[1024];
char _newpassword[1024];
char getpass1[1024];
char getpass2[1024];
while ((c = getopt(argc, argv, "Phadlu:p:")) != -1) {
switch (c) {
case 'h':
usage();
exit(1);
case 'a':
action = ACTION_ADD;
break;
case 'd':
action = ACTION_DELETE;
break;
case 'e':
action = ACTION_EDIT;
break;
case 'l':
action = ACTION_LIST;
break;
case 'u':
username = optarg;
break;
case 'p':
password = optarg;
break;
case 'P':
action = ACTION_CHPASS;
break;
default:
fprintf(stderr, "Unknown argument: '%c'\n", c);
usage();
exit(1);
}
}
argc -= optind;
argv += optind;
if (action == 0) {
usage();
errx(1, "No action specified!");
}
if (!username && argc > 0) {
username = argv[0];
argc--;
argv++;
}
if (!password && argc > 0) {
password = argv[0];
argc--;
argv++;
}
if (!username &&
(action == ACTION_ADD || action == ACTION_EDIT || action == ACTION_DELETE
|| action == ACTION_CHPASS)) {
usage();
errx(1, "Specify username!");
}
if (!password && action == ACTION_ADD) {
getpassword("Password: ", "Repeast password: ", getpass1,
sizeof(getpass1));
password = getpass1;
}
if (!newpassword && action == ACTION_CHPASS) {
if (password) {
newpassword = password;
}
else {
getpassword("New password: ", "Repeast new password: ", getpass2,
sizeof(getpass2));
newpassword = getpass2;
}
}
/* verify input */
if (username && !verifystr(username, STR_TYPE_NAME))
errx(1, "Invalid username input");
if (password && !verifystr(password, STR_TYPE_PASSWORD))
errx(1, "Invalid password input");
if (newpassword && !verifystr(newpassword, STR_TYPE_PASSWORD))
errx(1, "Invalid new password input");
uid = get_cred();
pgconn = db_connect(PSQL_USER, PSQL_PASSWORD, PSQL_DBNAME, PSQL_HOST);
if (username) {
struct passwd *passwd;
if (strlen(username) > 1000)
errx(1, "Too long username");
PQescapeString(_username, username, MIN(strlen(username), sizeof(_username)));
passwd = getpwuid(uid);
if (passwd == NULL)
err(1, "Unable to get login info");
if (!verify_startwith(username, passwd->pw_name))
errx(1, "Your dbuser must start with your username, and separate username from extrainfo with '_'");
}
if (password) {
if (strlen(password) > 1000)
errx(1, "Too long password");
PQescapeString(_password, password, MIN(strlen(password), sizeof(_password)));
}
if (newpassword) {
if (strlen(newpassword) > 1000)
errx(1, "Too long newpassword");
PQescapeString(_newpassword, newpassword,
MIN(strlen(newpassword), sizeof(_newpassword)));
}
switch (action) {
case ACTION_ADD:
printf("Adding user %s... \n", _username);
if (adduser(_username, _password, uid) != 0)
errx(1, "Unable to add new user");
break;
case ACTION_DELETE:
if (!verify_owner(_username, uid))
errx(1, "You are not the owner for that dbuser.");
printf("Deleting user... \n");
dropuser(username);
break;
case ACTION_EDIT:
if (!verify_owner(_username, uid))
errx(1, "You are not the owner for that dbuser.");
printf("Editing user... nothing to do here, sorry!\n");
break;
case ACTION_LIST:
listusers(uid);
break;
case ACTION_CHPASS:
printf("Changing password... \n");
change_password(_username, _newpassword);
break;
}
return(0);
}
void
usage(void)
{
fprintf(stderr, "psql-useradm [-h] [-a] [-d] [-l] [-P] [username] [password]\n");
fprintf(stderr, "\t-h: This help screen\n");
fprintf(stderr, "\t-a: Create a user\n");
fprintf(stderr, "\t-d: Drop a user\n");
/*fprintf(stderr, "\t-e: Edit you user [not functional]\n");*/
fprintf(stderr, "\t-l: List your database users\n");
fprintf(stderr, "\t-P: Change password\n");
}
int
adduser(char *username, char *password, uid_t uid)
{
char query[1024];
int nfields;
PGresult *res;
snprintf(query, sizeof(query), "SELECT uid FROM psqluseradm WHERE username = '%s'", username);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "Could not execute query: '%s': %s", query, PQerrorMessage(pgconn));
nfields = PQntuples(res);
if (nfields > 0)
errx(1, "A database user with that name already exists");
snprintf(query, sizeof(query), "CREATE USER %s NOCREATEDB NOCREATEUSER ENCRYPTED PASSWORD '%s'",
username, password);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to add db user: %s", PQerrorMessage(pgconn));
snprintf(query, sizeof(query), "INSERT INTO psqluseradm (uid, username) VALUES(%d, '%s')",
uid, username);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to add info user: %s", PQerrorMessage(pgconn));
printf("done!\n");
return(0);
}
void
listusers(uid_t uid)
{
char query[1024];
PGresult *res;
int i, nfields;
snprintf(query, sizeof(query), "SELECT username, ts FROM psqluseradm WHERE uid = %d", uid);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "unable to list users: %s: %s", query, PQerrorMessage(pgconn));
nfields = PQnfields(res);
printf("%-15s %-15s\n", "DBuser", "Created");
for (i = 0; i < PQntuples(res); i++) {
/* XXX: Format timestamp... */
printf("%-15s %-15s\n", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1));
}
if (PQntuples(res) == 0)
printf("You don't have any database users...\n");
}
int
dropuser(char *username)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "DROP USER %s", username);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to drop user: %s: %s", query, PQerrorMessage(pgconn));
snprintf(query, sizeof(query), "DELETE FROM psqluseradm WHERE username = '%s'", username);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to delete info user: %s: %s", query, PQerrorMessage(pgconn));
printf("done!\n");
return(0);
}
int
verify_owner(char *username, uid_t uid)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "SELECT id FROM psqluseradm " \
"WHERE username = '%s' AND uid = %d",
username, uid);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
errx(1, "verify query failed: %s: %s", query, PQerrorMessage(pgconn));
if (PQntuples(res) > 0)
return(1);
return(0);
}
void
change_password(char *username, char *password)
{
char query[1024];
PGresult *res;
snprintf(query, sizeof(query), "ALTER USER %s PASSWORD '%s'", username, password);
res = PQexec(pgconn, query);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
errx(1, "unable to change password for user: %s", query);
printf("done\n");
}

View File

@ -0,0 +1,4 @@
#define PSQL_HOST "129.241.210.168" /* india, avoid ipv6 thingy */
#define PSQL_USER "pgsql"
#define PSQL_DBNAME "psqladm"
#define PSQL_PASSWORD "somepass"

117
psqluseradm/psqladm.c Normal file
View File

@ -0,0 +1,117 @@
/*-
* Copyright (c) 2005 Eirik A. Nygaard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <string.h>
#include <err.h>
#include <unistd.h>
#include <ctype.h>
#include <libpq-fe.h>
#include "psql.config.h"
#include "psqladm.h"
PGconn *
db_connect(const char *dbuser, const char *password, const char *dbname, const char *host)
{
PGconn *conn;
char conninfo[1024];
snprintf(conninfo, sizeof(conninfo),
"dbname = '%s' host = '%s' user = '%s' password = '%s'",
dbname, host, dbuser, password);
conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK)
errx(1, "Could not connect to database(%d): %s", PQstatus(conn), PQerrorMessage(conn));
return(conn);
}
int
verify_startwith(char *string, char *start)
{
if (!strncmp(string, start, strlen(start))) {
if (strlen(string) == strlen(start))
return(1);
if (string[strlen(start)] == '_')
return(1);
}
return(0);
}
uid_t
get_cred(void)
{
uid_t uid;
if ((int)(uid = getuid()) == -1)
err(1, "getuid");
return(uid);
}
void
getpassword(const char *prompt1, const char *prompt2, char *pass, size_t len)
{
char pass1[1024];
char pass2[1024];
char *passwd;
passwd = getpass(prompt1);
strlcpy(pass1, passwd, sizeof(pass1));
passwd = getpass(prompt2);
strlcpy(pass2, passwd, sizeof(pass2));
if (strcmp(pass1, pass2) != 0) {
errx(1, "Passwords doesn't match");
}
strlcpy(pass, pass1, len);
}
/*
* names does not contain spaces
* passwords does not contain spaces
* XXX: Add better checks later.
*/
int
verifystr(char *str, int type)
{
unsigned int i;
for (i = 0; i < strlen(str); i++) {
if (type == STR_TYPE_NAME) {
if (isspace((int)str[i]))
return(0);
}
if (type == STR_TYPE_PASSWORD) {
if (isspace((int)str[i]))
return(0);
}
}
return(1); /* Bad Bad, default case should be non-verified */
}

43
psqluseradm/psqladm.h Normal file
View File

@ -0,0 +1,43 @@
/*-
* Copyright (c) 2005 Eirik A. Nygaard. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _PSQLADM_H_
#define _PSQLADM_H_
#define STR_TYPE_NAME 1
#define STR_TYPE_PASSWORD 2
int verify_startwith(char *string, char *start);
PGconn *db_connect(const char *dbuser, const char *password, const char *dbname, const char *host);
uid_t get_cred(void);
void getpassword(const char *prompt1, const char *prompt2, char *pass, size_t len);
int verifystr(char *str, int type);
#endif /* _PSQLADM_H_ */

15
tables.sql Normal file
View File

@ -0,0 +1,15 @@
CREATE TABLE psqluseradm (
id serial NOT NULL,
uid integer,
username character varying(128),
ts timestamp without time zone DEFAULT now()
);
CREATE TABLE psqldbadm (
id serial NOT NULL,
uid integer,
dbname character varying(128),
"owner" character varying(128),
ts timestamp without time zone DEFAULT now()
);