2018-03-05 15:59:14 +01:00
|
|
|
|
/*
|
2012-11-30 14:46:41 +01:00
|
|
|
|
* @(#) $Header: /home/stud/admin/cvs/mysql-admutils/mysql-dbadm.c,v 1.20 2007/06/04 08:40:54 geirha Exp $
|
2001-11-25 01:41:16 +01:00
|
|
|
|
*
|
|
|
|
|
* mysql-dbadm.c
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "mysql-admutils.h"
|
|
|
|
|
|
2001-11-25 01:41:16 +01:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <mysql.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <pwd.h>
|
2002-03-06 17:47:12 +01:00
|
|
|
|
#include <grp.h>
|
2001-11-25 01:41:16 +01:00
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
strchr_whitespace(const char *s)
|
|
|
|
|
{
|
|
|
|
|
char *sp, *tab;
|
|
|
|
|
sp = strchr(s, ' ');
|
|
|
|
|
tab = strchr(s, '\t');
|
|
|
|
|
if (sp == NULL)
|
|
|
|
|
return tab;
|
|
|
|
|
if (tab == NULL)
|
|
|
|
|
return sp;
|
|
|
|
|
return sp < tab ? sp : tab; /* if both are found, return the first one */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
strtok_whitespace(char *s)
|
|
|
|
|
{
|
|
|
|
|
static char *cp;
|
|
|
|
|
char *r;
|
|
|
|
|
|
|
|
|
|
r = s ? s : cp;
|
|
|
|
|
if (r == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
cp = strchr_whitespace(r);
|
|
|
|
|
if (cp == NULL)
|
|
|
|
|
return r;
|
2006-08-15 13:51:59 +02:00
|
|
|
|
while ((*cp == ' ') || (*cp == '\t'))
|
|
|
|
|
*cp++ = '\0';
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
valid_priv(const char *s)
|
|
|
|
|
{
|
2007-06-04 10:40:54 +02:00
|
|
|
|
if (s == NULL) return 0;
|
2012-11-30 14:46:41 +01:00
|
|
|
|
#define ACCEPT(x) if (strcmp(s, x) == 0) return 1
|
2001-11-25 01:41:16 +01:00
|
|
|
|
ACCEPT("Y");
|
|
|
|
|
ACCEPT("N");
|
|
|
|
|
ACCEPT("y");
|
|
|
|
|
ACCEPT("n");
|
2012-11-30 14:46:41 +01:00
|
|
|
|
#undef ACCEPT
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return 0; /* not a valid priv */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
usage()
|
|
|
|
|
{
|
|
|
|
|
printf("Usage: %s COMMAND [DATABASE]...\n", program_name);
|
|
|
|
|
printf("Create, drop og edit permission for the DATABASE(s),\n");
|
|
|
|
|
printf("as determined by the COMMAND. Valid COMMANDs:\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf(" create create the DATABASE(s).\n");
|
|
|
|
|
printf(" drop delete the DATABASE(s).\n");
|
|
|
|
|
printf(" show give information about the DATABASE(s), or, if\n");
|
|
|
|
|
printf(" none are given, all the ones you own.\n");
|
|
|
|
|
printf(" editperm change permissions for the DATABASE(s). Your\n");
|
|
|
|
|
printf(" favorite editor will be started, allowing you\n");
|
|
|
|
|
printf(" to make changes to the permission table.\n");
|
2007-06-04 10:40:54 +02:00
|
|
|
|
printf(" Run '%s --help-editperm' for more\n"
|
|
|
|
|
" information.\n",program_name);
|
|
|
|
|
printf("\n");
|
2018-03-01 17:03:04 +01:00
|
|
|
|
printf("Report bugs to orakel@ntnu.no\n");
|
2007-06-04 10:40:54 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
usage_editperm()
|
|
|
|
|
{
|
|
|
|
|
printf("Usage: %s editperm [DATABASE]\n", program_name);
|
|
|
|
|
printf("Edit permissions for the DATABASE. Running this command will\n");
|
|
|
|
|
printf("spawn the editor stored in the $EDITOR environment variable.\n");
|
|
|
|
|
printf("(pico will be used if the variable is unset)\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("The file should contain one line per user, starting with the\n");
|
|
|
|
|
printf("username and followed by ten Y/N-values seperated by whitespace.\n");
|
|
|
|
|
printf("Lines starting with # are ignored.\n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("The Y/N-values corresponds to the following mysql privileges:\n");
|
2018-03-05 15:38:57 +01:00
|
|
|
|
printf(" Select - Enables use of SELECT\n");
|
|
|
|
|
printf(" Insert - Enables use of INSERT\n");
|
|
|
|
|
printf(" Update - Enables use of UPDATE\n");
|
|
|
|
|
printf(" Delete - Enables use of DELETE\n");
|
|
|
|
|
printf(" Create - Enables use of CREATE TABLE\n");
|
|
|
|
|
printf(" Drop - Enables use of DROP TABLE\n");
|
|
|
|
|
printf(" Alter - Enables use of ALTER TABLE\n");
|
|
|
|
|
printf(" Index - Enables use of CREATE INDEX and DROP INDEX\n");
|
|
|
|
|
printf(" Temp - Enables use of CREATE TEMPORARY TABLE\n");
|
|
|
|
|
printf(" Lock - Enables use of LOCK TABLE\n");
|
|
|
|
|
printf(" References - Enables use of REFERENCES\n");
|
2001-11-25 01:41:16 +01:00
|
|
|
|
printf("\n");
|
2018-03-01 17:03:04 +01:00
|
|
|
|
printf("Report bugs to orakel@ntnu.no\n");
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
create(MYSQL *pmysql, char *db)
|
|
|
|
|
{
|
2004-11-16 21:56:51 +01:00
|
|
|
|
// hvis man fors<72>ker <20> dra mysql_create_db() p<> en database som
|
|
|
|
|
// allerede finnes, s<> henger bare hele sql-kallet. Vi m<> derfor
|
|
|
|
|
// fors<72>ke <20> selecte databasen f<>rst. Ettersom man alltid er root,
|
|
|
|
|
// g<>r jo dette vanligvis bra.
|
|
|
|
|
// finner ut om denne finnes fra f<>r.
|
|
|
|
|
if (!mysql_select_db(pmysql, db)) {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
return dberror(pmysql, "Database '%s' already exists.", db);
|
2004-11-16 21:56:51 +01:00
|
|
|
|
}
|
|
|
|
|
mysql_select_db(pmysql, "mysql");
|
|
|
|
|
// oppretter databasen.
|
2012-11-30 14:46:41 +01:00
|
|
|
|
char query[1024], *end;
|
|
|
|
|
end = strmov(query, "CREATE DATABASE `");
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, db, strlen(db));
|
|
|
|
|
*end++ = '`';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("query: %s\n", query);
|
|
|
|
|
#endif
|
2005-06-27 12:13:01 +02:00
|
|
|
|
if (mysql_query(pmysql, query))
|
2006-08-15 13:51:59 +02:00
|
|
|
|
return dberror(pmysql, "Cannot create database '%s'.", db);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
fprintf(stderr, "Database '%s' created.\n", db);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
drop(MYSQL *pmysql, char *db)
|
|
|
|
|
{
|
2012-11-30 14:46:41 +01:00
|
|
|
|
char query[1024], *end;
|
|
|
|
|
|
|
|
|
|
end = strmov(query, "DELETE FROM db WHERE db = '");
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, db, strlen(db));
|
|
|
|
|
*end++ = '\'';
|
|
|
|
|
*end = '\0';
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("query: %s\n", query);
|
|
|
|
|
#endif
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (mysql_query(pmysql, query))
|
|
|
|
|
dberror(pmysql, "Failed to delete permissions for database '%s'.", db);
|
|
|
|
|
|
2004-11-16 21:56:51 +01:00
|
|
|
|
if (mysql_select_db(pmysql, db)) {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
dberror(pmysql, "Database '%s' doesn't exists.", db);
|
|
|
|
|
return 0;
|
2004-11-16 21:56:51 +01:00
|
|
|
|
}
|
|
|
|
|
mysql_select_db(pmysql, "mysql");
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
end = strmov(query, "DROP DATABASE `");
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, db, strlen(db));
|
|
|
|
|
*end++ = '`';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("query: %s\n", query);
|
|
|
|
|
#endif
|
2005-06-27 12:13:01 +02:00
|
|
|
|
if (mysql_query(pmysql, query))
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return dberror(pmysql, "Cannot drop database '%s'.", db);
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "Database '%s' dropped.\n", db);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* return a list of the user's databases */
|
|
|
|
|
char **
|
|
|
|
|
list(MYSQL *pmysql)
|
|
|
|
|
{
|
|
|
|
|
char *wild;
|
2002-03-06 17:47:12 +01:00
|
|
|
|
char **usr_groups, **cp; /* holds all group names this dude is a member of [tlan]*/
|
2001-11-25 01:41:16 +01:00
|
|
|
|
MYSQL_RES *res;
|
2002-03-06 17:47:12 +01:00
|
|
|
|
int rows, numgroups, numgroupdbs;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
char **dblist;
|
2002-03-06 17:47:12 +01:00
|
|
|
|
int i, counter;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
struct passwd *p;
|
2003-04-08 20:31:53 +02:00
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
// variabler som brukes til <20> escape gruppenavnet til mysqlvennlig format.
|
2003-04-08 20:31:53 +02:00
|
|
|
|
char escaped_user[64];
|
|
|
|
|
char *cp_kopi;
|
2002-06-05 10:01:31 +02:00
|
|
|
|
|
2001-11-25 01:41:16 +01:00
|
|
|
|
p = getpwuid(getuid());
|
2006-08-15 13:51:59 +02:00
|
|
|
|
if (!p) {
|
|
|
|
|
dberror(NULL, "Failed to lookup your UNIX username.");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2002-03-06 17:47:12 +01:00
|
|
|
|
|
|
|
|
|
dblist = malloc(2 * sizeof(char*)); /* one for username (if used), rest is done below */
|
|
|
|
|
|
|
|
|
|
numgroupdbs = 0;
|
|
|
|
|
counter = 0;
|
|
|
|
|
|
|
|
|
|
usr_groups = get_group_names(&numgroups);
|
|
|
|
|
cp = usr_groups;
|
2017-09-28 17:21:02 +02:00
|
|
|
|
while (cp && *cp) { // itererer over alle grupper en person er med i
|
2002-03-06 17:47:12 +01:00
|
|
|
|
if (*cp == NULL)
|
2006-08-15 13:51:59 +02:00
|
|
|
|
break;
|
2002-03-06 17:47:12 +01:00
|
|
|
|
|
2003-04-08 20:31:53 +02:00
|
|
|
|
#ifdef DEBUG
|
2003-04-07 18:21:36 +02:00
|
|
|
|
printf("cp er %s\n", *cp);
|
2003-04-08 20:31:53 +02:00
|
|
|
|
#endif
|
2003-04-07 18:21:36 +02:00
|
|
|
|
|
2003-04-08 20:31:53 +02:00
|
|
|
|
escaped_user[0] = '\0';
|
|
|
|
|
cp_kopi=*cp;
|
2003-04-07 18:21:36 +02:00
|
|
|
|
|
2003-04-08 20:31:53 +02:00
|
|
|
|
// itererer over bokstavene i gruppenavn, og escaper spesialtegn.
|
|
|
|
|
for(i=0; i<=strlen(cp_kopi); i++) {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
// hvis % _ , s<> skriv \ og s<> tegn
|
|
|
|
|
if ((cp_kopi[i] == '_') || (cp_kopi[i] == '%')) {
|
|
|
|
|
strcat(escaped_user, "\\");
|
|
|
|
|
}
|
2003-04-07 18:21:36 +02:00
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
escaped_user[strlen(escaped_user) + 1] = '\0';
|
|
|
|
|
escaped_user[strlen(escaped_user)] = cp_kopi[i];
|
2003-04-08 20:31:53 +02:00
|
|
|
|
} // for
|
|
|
|
|
|
2006-08-15 12:32:42 +02:00
|
|
|
|
wild = malloc(strlen(escaped_user)+4);
|
2003-04-08 20:31:53 +02:00
|
|
|
|
sprintf(wild, "%s\\_%%", escaped_user);
|
2002-03-06 17:47:12 +01:00
|
|
|
|
|
2003-04-04 00:30:45 +02:00
|
|
|
|
#ifdef DEBUG
|
2003-04-07 18:21:36 +02:00
|
|
|
|
printf("dbadm: wildcard: '%s'\n", wild);
|
2003-04-04 00:30:45 +02:00
|
|
|
|
#endif
|
2003-04-07 18:21:36 +02:00
|
|
|
|
|
2002-03-06 17:47:12 +01:00
|
|
|
|
res = mysql_list_dbs(pmysql, wild);
|
|
|
|
|
rows = mysql_num_rows(res);
|
|
|
|
|
|
|
|
|
|
if (rows > 0) {
|
|
|
|
|
numgroupdbs += rows;
|
|
|
|
|
|
|
|
|
|
dblist = realloc(dblist, (numgroupdbs+2) * sizeof(char *));
|
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
|
|
if ((row = mysql_fetch_row(res))) {
|
|
|
|
|
dblist[counter++] = strdup(row[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-03-06 17:47:12 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-04-07 18:21:36 +02:00
|
|
|
|
free(wild);
|
2012-11-30 14:46:41 +01:00
|
|
|
|
mysql_free_result(res);
|
2002-03-06 17:47:12 +01:00
|
|
|
|
cp++;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-15 12:32:42 +02:00
|
|
|
|
wild = malloc(strlen(p->pw_name) + 4);
|
2003-04-07 18:21:36 +02:00
|
|
|
|
sprintf(wild, "%s\\_%%", p->pw_name);
|
|
|
|
|
#ifdef DEBUG
|
2006-08-15 13:51:59 +02:00
|
|
|
|
printf("dbadm: wildcard: '%s'\n", wild);
|
2003-04-07 18:21:36 +02:00
|
|
|
|
#endif
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
res = mysql_list_dbs(pmysql, wild);
|
|
|
|
|
rows = mysql_num_rows(res);
|
2002-03-06 17:47:12 +01:00
|
|
|
|
dblist = realloc(dblist, (numgroupdbs+rows+2) * sizeof(char *));
|
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
if (!dblist) {
|
|
|
|
|
dberror(NULL, "Out of memory.\n");
|
|
|
|
|
free(wild);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2002-03-06 17:47:12 +01:00
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
|
|
if ((row = mysql_fetch_row(res))) {
|
|
|
|
|
dblist[counter++] = strdup(row[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-30 14:46:41 +01:00
|
|
|
|
mysql_free_result(res);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
res = mysql_list_dbs(pmysql, p->pw_name);
|
|
|
|
|
rows = mysql_num_rows(res);
|
|
|
|
|
if (rows == 1)
|
2006-08-15 13:51:59 +02:00
|
|
|
|
dblist[counter++] = strdup(p->pw_name);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
2002-03-06 17:47:12 +01:00
|
|
|
|
dblist[counter] = NULL;
|
2006-08-15 13:51:59 +02:00
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
mysql_free_result(res);
|
2006-08-15 13:51:59 +02:00
|
|
|
|
free(wild);
|
2012-11-30 14:46:41 +01:00
|
|
|
|
for (i=0;i<numgroups;i++)
|
|
|
|
|
free(usr_groups[i]);
|
2006-08-15 13:51:59 +02:00
|
|
|
|
free(usr_groups);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return dblist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
writeperm(FILE *f, MYSQL *pmysql, const char *db)
|
|
|
|
|
{
|
2012-11-30 14:46:41 +01:00
|
|
|
|
char query[2048], *end;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
MYSQL_RES *res;
|
|
|
|
|
int rows, i;
|
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
end = strmov(query, "SELECT user,select_priv,insert_priv,update_priv,"
|
|
|
|
|
"delete_priv,create_priv,drop_priv,"
|
|
|
|
|
"alter_priv,index_priv,"
|
2018-03-05 15:38:57 +01:00
|
|
|
|
"create_tmp_table_priv,lock_tables_priv,"
|
2018-03-05 15:48:07 +01:00
|
|
|
|
"references_priv "
|
2012-11-30 14:46:41 +01:00
|
|
|
|
"FROM db WHERE db = '");
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, db, strlen(db));
|
|
|
|
|
*end++ = '\'';
|
|
|
|
|
*end = '\0';
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("query: %s\n", query);
|
|
|
|
|
#endif
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (mysql_query(pmysql, query))
|
|
|
|
|
return dberror(pmysql, "Query for permissions failed.");
|
|
|
|
|
res = mysql_store_result(pmysql);
|
|
|
|
|
rows = mysql_num_rows(res);
|
|
|
|
|
fprintf(f, "# User "
|
2007-02-27 12:38:07 +01:00
|
|
|
|
"Select Insert Update Delete Create Drop Alter Index "
|
2018-03-05 15:38:57 +01:00
|
|
|
|
" Temp Lock References\n");
|
2001-11-25 01:41:16 +01:00
|
|
|
|
fprintf(f, "# ---------------- "
|
2007-02-27 12:38:07 +01:00
|
|
|
|
"------ ------ ------ ------ ------ ---- ----- ----- "
|
2018-03-05 15:38:57 +01:00
|
|
|
|
" ---- ---- ----------\n");
|
2002-06-05 10:01:31 +02:00
|
|
|
|
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (rows == 0)
|
2006-08-15 13:51:59 +02:00
|
|
|
|
fprintf(f, "# (no permissions currently granted to any users)\n");
|
|
|
|
|
else {
|
|
|
|
|
for (i = 0; i < rows; i++) {
|
|
|
|
|
row = mysql_fetch_row(res);
|
2018-03-05 15:38:57 +01:00
|
|
|
|
fprintf(f, " %-16s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s %s\n",
|
|
|
|
|
row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9], row[10], row[11]);
|
2006-08-15 13:51:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-30 14:46:41 +01:00
|
|
|
|
mysql_free_result(res);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* show information about the database */
|
|
|
|
|
int
|
|
|
|
|
show(MYSQL *pmysql, const char *db)
|
|
|
|
|
{
|
|
|
|
|
printf("Database '%s':\n", db);
|
|
|
|
|
|
|
|
|
|
writeperm(stdout, pmysql, db);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX_GRANTS 1024
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
editperm(MYSQL *pmysql, const char *db)
|
|
|
|
|
{
|
|
|
|
|
char fn[] = "/tmp/mysql-dbadm.tmp.XXXXXX";
|
|
|
|
|
FILE *f;
|
|
|
|
|
char *editor;
|
2017-09-25 12:49:58 +02:00
|
|
|
|
char *cmd;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
char line[1024]; /* buffer to hold one line */
|
|
|
|
|
char *cp; /* used to interate through a line */
|
|
|
|
|
char *user, *select_priv, *insert_priv, *update_priv, *delete_priv,
|
2006-11-17 15:32:46 +01:00
|
|
|
|
*create_priv, *drop_priv, *alter_priv, *index_priv, *create_tmp_table_priv,
|
2018-03-05 15:48:07 +01:00
|
|
|
|
*lock_tables_priv, *references_priv;
|
2012-11-30 14:46:41 +01:00
|
|
|
|
char query[4096], *end; /* used to build a query */
|
2001-11-25 01:41:16 +01:00
|
|
|
|
char *queries[MAX_GRANTS]; /* insert queries */
|
|
|
|
|
int lines; /* number of grant lines processed */
|
|
|
|
|
int i; /* iterate through lines[] */
|
2012-12-11 14:41:48 +01:00
|
|
|
|
int fd;
|
|
|
|
|
pid_t pid;
|
|
|
|
|
int exit_status = -1;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
2012-12-11 14:41:48 +01:00
|
|
|
|
fd = mkstemp(fn);
|
2003-04-08 20:31:53 +02:00
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
if (fd == -1)
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return dberror(NULL, "Cannot create a unique temporary file name.");
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
f = fdopen(fd, "w");
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (f == NULL)
|
|
|
|
|
return dberror(NULL, "Failed to open temporary file %s.", fn);
|
|
|
|
|
writeperm(f, pmysql, db);
|
|
|
|
|
fclose(f);
|
|
|
|
|
|
2012-12-11 14:41:48 +01:00
|
|
|
|
pid = fork();
|
|
|
|
|
if ( pid < 0 )
|
|
|
|
|
{
|
|
|
|
|
perror("Failed to fork");
|
|
|
|
|
exit(2);
|
2006-08-15 13:51:59 +02:00
|
|
|
|
}
|
2012-12-11 14:41:48 +01:00
|
|
|
|
else if ( pid != 0 )
|
|
|
|
|
{
|
|
|
|
|
int status = 0;
|
|
|
|
|
while ( waitpid(pid, &status, 0) )
|
|
|
|
|
{
|
|
|
|
|
if (WIFEXITED(status))
|
|
|
|
|
{
|
|
|
|
|
exit_status = WEXITSTATUS(status);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Should not have access to the mysql socket here */
|
|
|
|
|
if (close(pmysql->net.fd) != 0)
|
|
|
|
|
{
|
|
|
|
|
perror("Failed to close fd");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-25 12:49:58 +02:00
|
|
|
|
editor = getenv("EDITOR");
|
|
|
|
|
if (!editor)
|
|
|
|
|
editor = "pico"; /* OK since editor won't be freed */
|
|
|
|
|
|
|
|
|
|
cmd = malloc(sizeof(char) * strlen(editor) + 7);
|
|
|
|
|
sprintf(cmd, "%s \"$1\"", editor);
|
|
|
|
|
|
|
|
|
|
/* sh -c '$EDITOR "$1"' sh "$fn" */
|
|
|
|
|
execlp("sh", "sh", "-c", cmd, "sh", fn, NULL);
|
2012-12-11 14:41:48 +01:00
|
|
|
|
perror("Failed to execute editor");
|
|
|
|
|
fprintf(stderr, "Make sure the EDITOR environment variable contains"
|
|
|
|
|
" a valid editor\n");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exit_status != 0)
|
|
|
|
|
return 1;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
/* parse */
|
|
|
|
|
f = fopen(fn, "r");
|
|
|
|
|
lines = 0;
|
2006-08-15 13:51:59 +02:00
|
|
|
|
while (fgets(line, sizeof(line), f)) {
|
|
|
|
|
cp = strchr(line, '\n');
|
|
|
|
|
if (cp)
|
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
|
|
|
|
cp = line;
|
|
|
|
|
while (*cp && ((*cp == ' ') || (*cp == '\t'))) cp++;
|
|
|
|
|
if (*cp == '\0') continue;
|
|
|
|
|
if (*cp == '#') continue;
|
|
|
|
|
if (*cp == '\n') continue;
|
|
|
|
|
|
|
|
|
|
#define STRTOK_WHITESPACE(res, start) \
|
|
|
|
|
{ if (!(res = strtok_whitespace(start))) continue; }
|
|
|
|
|
|
|
|
|
|
STRTOK_WHITESPACE(user, cp);
|
|
|
|
|
if (strlen(user) < 1)
|
|
|
|
|
return dberror(NULL, "Invalid user '%s' in grant line %d.", user,
|
|
|
|
|
lines + 1);
|
|
|
|
|
if (strcmp(user, "%") == 0)
|
|
|
|
|
*user = '\0'; /* ugly, but it works... */
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
#define CHECK_PRIV(PRIV) \
|
|
|
|
|
if (!valid_priv(PRIV)) return dberror(NULL, "Invalid value '%s' " \
|
2007-06-04 10:40:54 +02:00
|
|
|
|
"in grant line %d.\nMake sure you fill in a value (Y or N) for " \
|
|
|
|
|
"all ten privileges.\nRun '%s --help-editerm' for more " \
|
|
|
|
|
"information.\nNo permissions have been set.", PRIV, lines + 1, \
|
|
|
|
|
program_name)
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
STRTOK_WHITESPACE(select_priv, NULL);
|
|
|
|
|
CHECK_PRIV(select_priv);
|
|
|
|
|
STRTOK_WHITESPACE(insert_priv, NULL);
|
|
|
|
|
CHECK_PRIV(insert_priv);
|
|
|
|
|
STRTOK_WHITESPACE(update_priv, NULL);
|
|
|
|
|
CHECK_PRIV(update_priv);
|
|
|
|
|
STRTOK_WHITESPACE(delete_priv, NULL);
|
|
|
|
|
CHECK_PRIV(delete_priv);
|
|
|
|
|
STRTOK_WHITESPACE(create_priv, NULL);
|
|
|
|
|
CHECK_PRIV(create_priv);
|
|
|
|
|
STRTOK_WHITESPACE(drop_priv, NULL);
|
|
|
|
|
CHECK_PRIV(drop_priv);
|
|
|
|
|
STRTOK_WHITESPACE(alter_priv, NULL);
|
|
|
|
|
CHECK_PRIV(alter_priv);
|
|
|
|
|
STRTOK_WHITESPACE(index_priv, NULL);
|
|
|
|
|
CHECK_PRIV(index_priv);
|
2006-11-17 15:32:46 +01:00
|
|
|
|
STRTOK_WHITESPACE(create_tmp_table_priv, NULL);
|
|
|
|
|
CHECK_PRIV(create_tmp_table_priv);
|
|
|
|
|
STRTOK_WHITESPACE(lock_tables_priv, NULL);
|
|
|
|
|
CHECK_PRIV(lock_tables_priv);
|
2018-03-05 15:48:07 +01:00
|
|
|
|
STRTOK_WHITESPACE(references_priv, NULL);
|
|
|
|
|
CHECK_PRIV(references_priv);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
#undef STRTOK_WHITESPACE
|
|
|
|
|
#undef CHECK_PRIV
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
end = strmov(query, "INSERT INTO db ("
|
|
|
|
|
"host,db,user,select_priv,insert_priv,"
|
|
|
|
|
"update_priv,delete_priv,create_priv,"
|
|
|
|
|
"drop_priv,alter_priv,index_priv,"
|
2018-03-05 15:38:57 +01:00
|
|
|
|
"create_tmp_table_priv,lock_tables_priv,"
|
2018-03-05 15:48:07 +01:00
|
|
|
|
"references_priv"
|
2012-11-30 14:46:41 +01:00
|
|
|
|
") VALUES (");
|
|
|
|
|
|
|
|
|
|
end = strmov(end, "'%'");
|
|
|
|
|
|
|
|
|
|
#define APPEND(VAR) {\
|
|
|
|
|
*end++ = ',';\
|
|
|
|
|
*end++ = '\'';\
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, VAR, strlen(VAR));\
|
|
|
|
|
*end++ = '\'';\
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APPEND(db);
|
|
|
|
|
APPEND(user);
|
|
|
|
|
APPEND(select_priv);
|
|
|
|
|
APPEND(insert_priv);
|
|
|
|
|
APPEND(update_priv);
|
|
|
|
|
APPEND(delete_priv);
|
|
|
|
|
APPEND(create_priv);
|
|
|
|
|
APPEND(drop_priv);
|
|
|
|
|
APPEND(alter_priv);
|
|
|
|
|
APPEND(index_priv);
|
|
|
|
|
APPEND(create_tmp_table_priv);
|
|
|
|
|
APPEND(lock_tables_priv);
|
2018-03-05 15:48:07 +01:00
|
|
|
|
APPEND(references_priv);
|
2012-11-30 14:46:41 +01:00
|
|
|
|
*end++ = ')';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
|
|
|
|
|
#undef APPEND
|
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
queries[lines] = strdup(query);
|
|
|
|
|
lines++;
|
|
|
|
|
if (lines >= MAX_GRANTS)
|
|
|
|
|
{
|
|
|
|
|
dberror(NULL, "Warning: Maximum of %d grants reached.\n",
|
|
|
|
|
MAX_GRANTS);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} /* while fgets ... */
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
unlink(fn);
|
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
|
|
/* now that we have checked the input for errors, we can safely
|
|
|
|
|
delete the old grants from the database and insert the new ones. */
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
end = strmov(query, "DELETE FROM db WHERE db = '");
|
|
|
|
|
end += mysql_real_escape_string(pmysql, end, db, strlen(db));
|
|
|
|
|
*end++ = '\'';
|
|
|
|
|
*end = '\0';
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("query: %s\n", query);
|
|
|
|
|
#endif
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (mysql_query(pmysql, query))
|
|
|
|
|
dberror(pmysql, "Failed to delete old grants for '%s'.", db);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < lines; i++)
|
2006-08-15 13:51:59 +02:00
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
puts(queries[i]);
|
|
|
|
|
putchar('\n');
|
|
|
|
|
#endif
|
|
|
|
|
if (mysql_query(pmysql, queries[i]))
|
|
|
|
|
dberror(pmysql, "Failed to insert grant line %d.", i + 1);
|
2012-11-30 14:46:41 +01:00
|
|
|
|
free(queries[i]);
|
2006-08-15 13:51:59 +02:00
|
|
|
|
}
|
2012-12-11 14:41:48 +01:00
|
|
|
|
|
|
|
|
|
fprintf(stderr,"Permissions updated\n");
|
2007-06-04 10:40:54 +02:00
|
|
|
|
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
enum { c_create, c_drop, c_editperm, c_show } command;
|
|
|
|
|
MYSQL mysql;
|
2005-06-27 12:13:01 +02:00
|
|
|
|
mysql_init(&mysql);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
char **dblist, **p;
|
2004-11-16 21:56:51 +01:00
|
|
|
|
char *db;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
program_name = argv[0];
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
|
if (strcmp(argv[i], "--help") == 0)
|
|
|
|
|
return usage();
|
2007-06-04 10:40:54 +02:00
|
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
|
if (strcmp(argv[i], "--help-editperm") == 0)
|
|
|
|
|
return usage_editperm();
|
2001-11-25 01:41:16 +01:00
|
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
|
if (strcmp(argv[i], "--version") == 0)
|
|
|
|
|
return version();
|
|
|
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
|
return wrong_use(NULL);
|
|
|
|
|
|
2003-04-08 20:31:53 +02:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf("NB NB NB: denne versjonen av programmet er kompilert med -DDEBUG, og\n");
|
|
|
|
|
printf("kan komme til <20> skrive ut ekstra informasjon. Dette er ikke farlig,\n");
|
|
|
|
|
printf("og programmet b<>r virke som vanlig.\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2001-11-25 01:41:16 +01:00
|
|
|
|
/* check that the supplied command is valid */
|
|
|
|
|
|
|
|
|
|
if (strcmp(argv[1], "create") == 0)
|
|
|
|
|
command = c_create;
|
|
|
|
|
else if (strcmp(argv[1], "drop") == 0)
|
|
|
|
|
command = c_drop;
|
|
|
|
|
else if (strcmp(argv[1], "editperm") == 0)
|
|
|
|
|
command = c_editperm;
|
|
|
|
|
else if (strcmp(argv[1], "show") == 0)
|
|
|
|
|
command = c_show;
|
|
|
|
|
else
|
|
|
|
|
return wrong_use("unrecognized command"); /* XXX */
|
|
|
|
|
|
2012-11-30 14:46:41 +01:00
|
|
|
|
/* all other than show requires at least one DATABASE argument. */
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if ((command != c_show) && (argc < 3))
|
|
|
|
|
return wrong_use(NULL);
|
|
|
|
|
|
2018-10-26 16:53:47 +02:00
|
|
|
|
read_toml_file();
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
/* connect to the database server and select the mysql database */
|
2005-06-27 12:13:01 +02:00
|
|
|
|
if (!mysql_real_connect(&mysql, db_server, db_user, db_passwd, db_name, 0, NULL, 0))
|
2001-11-25 01:41:16 +01:00
|
|
|
|
return dberror(&mysql, "Cannot connect to database server '%s'.",
|
2006-08-15 13:51:59 +02:00
|
|
|
|
db_server);
|
2001-11-25 01:41:16 +01:00
|
|
|
|
if (mysql_select_db(&mysql, db_name))
|
|
|
|
|
return dberror(&mysql, "Cannot select database '%s'.", db_name);
|
|
|
|
|
|
2006-08-15 13:51:59 +02:00
|
|
|
|
if ((command == c_show) && (argc == 2)) {
|
|
|
|
|
dblist = list(&mysql);
|
|
|
|
|
p = dblist;
|
2017-09-28 17:21:02 +02:00
|
|
|
|
while (p && *p) {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
show(&mysql, *p);
|
|
|
|
|
free(*p);
|
|
|
|
|
p++;
|
2001-11-25 01:41:16 +01:00
|
|
|
|
}
|
2006-08-15 13:51:59 +02:00
|
|
|
|
free(dblist);
|
|
|
|
|
}
|
2004-11-16 21:56:51 +01:00
|
|
|
|
else {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
db = malloc(64);
|
|
|
|
|
/* for each supplied database name, perform the requested action */
|
|
|
|
|
for (i = 2; i < argc; i++) {
|
|
|
|
|
// HE HE
|
|
|
|
|
strncpy(db, argv[i], 32);
|
|
|
|
|
db[32] = '\0';
|
|
|
|
|
|
|
|
|
|
if (! (owner(db) || member(db))) {
|
2007-02-27 15:10:08 +01:00
|
|
|
|
if (command == c_create)
|
|
|
|
|
dberror(NULL,"Unable to create mysql-database '%s'.\n"
|
|
|
|
|
"A mysql-database must start with either '%s_' or "
|
|
|
|
|
"'groupname_', where groupname is a unix group you are a "
|
|
|
|
|
"member of. Type \"groups\" to see which groups you are a "
|
|
|
|
|
"member of.\n",
|
|
|
|
|
db, getpwuid(getuid())->pw_name);
|
|
|
|
|
else
|
|
|
|
|
dberror(NULL, "You are not in charge of mysql-database: '%s'. Skipping.", db);
|
|
|
|
|
continue;
|
2006-08-15 13:51:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (command) {
|
|
|
|
|
case c_create:
|
|
|
|
|
// We only check newly created databases. Many old ("unclean") databases are still in use.
|
2012-12-11 15:24:07 +01:00
|
|
|
|
if(name_isclean(db)) {
|
2006-08-15 13:51:59 +02:00
|
|
|
|
create(&mysql, db);
|
|
|
|
|
} else {
|
|
|
|
|
dberror(NULL, "Database name '%s' contains invalid characters.\n"
|
|
|
|
|
"Only A-Z, a-z, 0-9, _ (underscore) and - (dash) permitted. Skipping.", db);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case c_drop:
|
2012-12-11 15:24:07 +01:00
|
|
|
|
if(name_isclean(db)) {
|
2012-11-29 15:57:13 +01:00
|
|
|
|
drop(&mysql, db);
|
|
|
|
|
} else {
|
|
|
|
|
dberror(NULL, "Database name '%s' contains invalid characters.\n"
|
|
|
|
|
"Only A-Z, a-z, 0-9, _ (underscore) and - (dash) permitted. Skipping.", db);
|
|
|
|
|
}
|
2006-08-15 13:51:59 +02:00
|
|
|
|
break;
|
|
|
|
|
case c_editperm:
|
2012-12-11 15:24:07 +01:00
|
|
|
|
if(name_isclean(db)) {
|
2012-11-29 15:57:13 +01:00
|
|
|
|
editperm(&mysql, db);
|
|
|
|
|
} else {
|
|
|
|
|
dberror(NULL, "Database name '%s' contains invalid characters.\n"
|
|
|
|
|
"Only A-Z, a-z, 0-9, _ (underscore) and - (dash) permitted. Skipping.", db);
|
|
|
|
|
}
|
2006-08-15 13:51:59 +02:00
|
|
|
|
break;
|
|
|
|
|
case c_show:
|
2012-12-11 15:24:07 +01:00
|
|
|
|
if(name_isclean(db)) {
|
2012-11-29 15:57:13 +01:00
|
|
|
|
show(&mysql, db);
|
|
|
|
|
} else {
|
|
|
|
|
dberror(NULL, "Database name '%s' contains invalid characters.\n"
|
|
|
|
|
"Only A-Z, a-z, 0-9, _ (underscore) and - (dash) permitted. Skipping.", db);
|
|
|
|
|
}
|
2006-08-15 13:51:59 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return dberror(NULL, "This point should never be reached!");
|
|
|
|
|
}
|
|
|
|
|
} // for
|
|
|
|
|
free(db);
|
|
|
|
|
} // else
|
2001-11-25 01:41:16 +01:00
|
|
|
|
|
|
|
|
|
mysql_reload(&mysql);
|
|
|
|
|
mysql_close(&mysql);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|