feature idea: secret words?
| From: | Vadim Kolontsov | Date: | Mon, 12 Jul 1999 08:30:43 +0000 |
| Subject: | feature idea: secret words? | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-8379@lists.php.net to get a copy of this message | ||
Hi,
all database passwords (or other "secret words") currently stores in
php3-sources (in plaintext), so everyone who can read those files can read
passwords too.
I've implemented a simple solution for this:
1) I use Berkeley-DB database ("SecretDB"), owned and readable/writeable only
by root.
-rw------- 1 root root 32768 May 27 16:27 /etc/phpsecret.db
2) There is a root-setuid utility, which allows any user to add/get/delete
a pair of NAME=VALUE (for example, "DBPassword=simplepassword") to the
database. Actually it stores USERNAME:NAME=VALUE, so every user has it's
own set of pairs (unaccessible for others)
Of course, you can use setgid or nonroot-setuid (depends on access rights
on SecretDB)
3) Web-server initializes php3 engine during startup, running as root
(before set[ug]id()ing to other uid/gid), so php3 engine is able to open
secretDB.
4) I've added a simple php3 function, getsecretword(string) which allows
to get VALUE for specified NAME. It gets uid of script owner and
uses it to get USERNAME. So script is only able to get those pairs,
which are owned by script owner.
So you don't have to write Ora_Logon("username", "password"); you can
use Ora_Logon("username", getsecretword("DatabasePassword"))...
Patches to 3.0.12-dev and 'php3-secretword' utility are included. I use
BerkeleyDB 2.7.5 (www.sleepycat.com), you'll have to add correct
-I, -L, -l to compiler/linker flags.
SecretDB is specified in php3.ini using "secretDB" parameter. You'll
have to edit it by hand in php3-secretword.c
If you'll see any mistakes in this idea (or implementation) or have any
other opinions I'll happy to hear it. Sorry for awful english :)
Regards,
V.
--
Vadim Kolontsov
Tver Internet Center NOC
/* secret words for php3 * Copyright (C) 1999 Vadim Kolontsov <vadim@tversu.ru> * * too simple to be a realworld utility, just an illustration of idea */ #include <stdio.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <db.h> #include <pwd.h> #define DATABASE "/etc/phpsecret.db" DB *dbp; /* Close database on exit */ void exit_handler(void) { if (dbp->close(dbp, 0) != 0) { fprintf(stderr, "can't close %s\n", DATABASE); _exit(1); } _exit(0); } void usage() { fprintf(stderr, "wrong arguments\n\n" "usage: php3-secretword add property value\n" " php3-secretword del property\n" " php3-secretword get property\n"); exit(1); } int main(int argc, char *argv[]) { int rc; char *tmp; DBT key, data; struct passwd *pwd; if (db_open(DATABASE, DB_HASH, DB_CREATE, 0664, NULL, NULL, &dbp) != 0) { fprintf(stderr, "can't open database %s\n", DATABASE); exit(1); } if (atexit(exit_handler) != 0) { fprintf(stderr, "can't register exit function\n"); exit(1); } if (argc < 3) usage(); memset(&data, 0, sizeof(data)); memset(&key, 0, sizeof(key)); if ((pwd = getpwuid(getuid())) == NULL) { fprintf(stderr, "I don't know you!\n"); exit(1); } tmp = (char *)malloc(strlen(argv[2])+32); sprintf(tmp, "%d:%s:%s", strlen(pwd->pw_name), pwd->pw_name, argv[2]); key.data = tmp; key.size = strlen(tmp); if (!strcmp(argv[1], "add")) { long t; if (argc != 4) usage(); data.data = argv[3]; data.size = strlen(argv[3]); if (dbp->put(dbp, NULL, &key, &data, 0) != 0) fprintf(stderr, "%s put\n", DATABASE); } else if (!strcmp(argv[1], "del")) { if (dbp->del(dbp, NULL, &key, 0) != 0) fprintf(stderr, "%s del\n", DATABASE); } else if (!strcmp(argv[1], "get")) { switch (dbp->get(dbp, NULL, &key, &data, 0)) { case 0: *((char *)data.data+data.size) = 0; printf("%s: %s\n", key.data, data.data); break; case DB_NOTFOUND: fprintf(stderr, "entry not found in %s\n", DATABASE); break; default: fprintf(stderr, "%s get\n", DATABASE); } } return 0; } Index: main.c =================================================================== RCS file: /repository/php3/main.c,v retrieving revision 1.503 diff -c -r1.503 main.c *** main.c 1999/07/03 05:40:20 1.503 --- main.c 1999/07/12 07:18:17 *************** *** 984,989 **** --- 984,1000 ---- if (cfg_get_long("precision", &php3_ini.precision) == FAILURE) { php3_ini.precision = 14; } + if (cfg_get_string("secretDB", &temp) != FAILURE && temp[0]) { + if (db_open(temp, DB_HASH, DB_CREATE, 0664, NULL, NULL, + &php3_ini.secretDB) != 0) { + php3_printf("Can't open secretDB (%s).\n", + temp); + return FAILURE; + } + } else { + php3_ini.secretDB = NULL; + } + if (cfg_get_string("SMTP", &php3_ini.smtp) == FAILURE) { php3_ini.smtp = "localhost"; } Index: mod_php3.h =================================================================== RCS file: /repository/php3/mod_php3.h,v retrieving revision 1.51 diff -c -r1.51 mod_php3.h *** mod_php3.h 1999/01/27 21:55:47 1.51 --- mod_php3.h 1999/07/12 07:18:17 *************** *** 31,36 **** --- 31,38 ---- #ifndef _MOD_PHP3_H #define _MOD_PHP3_H + #include <db.h> + #if !defined(WIN32) && !defined(WINNT) #ifndef MODULE_VAR_EXPORT #define MODULE_VAR_EXPORT *************** *** 92,97 **** --- 94,100 ---- long enable_dl; long ignore_user_abort; char *dav_script; + DB *secretDB; } php3_ini_structure; #if MSVC5 Index: functions/basic_functions.c =================================================================== RCS file: /repository/php3/functions/basic_functions.c,v retrieving revision 1.271 diff -c -r1.271 basic_functions.c *** functions/basic_functions.c 1999/07/03 05:40:20 1.271 --- functions/basic_functions.c 1999/07/12 07:18:18 *************** *** 179,184 **** --- 179,185 ---- {"phpversion", php3_version, NULL}, PHP_FE(extension_loaded, NULL) {"strlen", php3_strlen, NULL}, + {"getsecretword", php3_getsecretword, NULL}, {"strcmp", php3_strcmp, NULL}, {"strspn", php3_strspn, NULL}, {"strcspn", php3_strcspn, NULL}, *************** *** 2047,2052 **** --- 2048,2104 ---- _php3_hash_next_index_insert(user_shutdown_function_names, &shutdown_function_name, sizeof(pval), NULL); } /* }}} */ + + void php3_getsecretword(INTERNAL_FUNCTION_PARAMETERS) + { + pval *str; + register int i; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(str); + + if (str->type == IS_STRING && str->value.str.len > 0 && php3_ini.secretDB) { + DBT key, data; + char *tmp; + struct passwd *pwd; + int rc; + uid_t uid; + + tmp = (char *)emalloc(strlen(str->value.str.val)+32); + uid = _php3_getuid(); + if (pwd = getpwuid(uid)) { + sprintf(tmp, "%d:%s:%s", strlen(pwd->pw_name), + pwd->pw_name, str->value.str.val); + } else { + php3_error(E_ERROR, "can't find user, uid=%ld", uid); + RETURN_FALSE; + } + + memset(&data, 0, sizeof(data)); + memset(&key, 0, sizeof(key)); + + key.data = tmp; + key.size = strlen(tmp); + rc = php3_ini.secretDB->get(php3_ini.secretDB, NULL, &key, &data, 0); + efree(tmp); + + switch (rc) { + case 0: + *((char *)data.data+data.size) = 0; + RETVAL_STRING(data.data, 1); + break; + case DB_NOTFOUND: + RETURN_FALSE; + default: + php3_error(E_WARNING, "Can't get secret word"); + RETURN_FALSE; + } + } else + RETURN_FALSE; + } /* {{{ proto int function_exists(string function_name) Index: functions/basic_functions.h =================================================================== RCS file: /repository/php3/functions/basic_functions.h,v retrieving revision 1.43 diff -c -r1.43 basic_functions.h *** functions/basic_functions.h 1999/06/25 22:53:23 1.43 --- functions/basic_functions.h 1999/07/12 07:18:21 *************** *** 102,107 **** --- 102,109 ---- extern void php3_connection_status(INTERNAL_FUNCTION_PARAMETERS); extern void php3_ignore_user_abort(INTERNAL_FUNCTION_PARAMETERS); + extern void php3_getsecretword(INTERNAL_FUNCTION_PARAMETERS); + extern PHP_FUNCTION(function_exists); extern PHP_FUNCTION(extract);
/* secret words for php3 * Copyright (C) 1999 Vadim Kolontsov <vadim@tversu.ru> * * too simple to be a realworld utility, just an illustration of idea */ #include <stdio.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <db.h> #include <pwd.h> #define DATABASE "/etc/phpsecret.db" DB *dbp; /* Close database on exit */ void exit_handler(void) { if (dbp->close(dbp, 0) != 0) { fprintf(stderr, "can't close %s\n", DATABASE); _exit(1); } _exit(0); } void usage() { fprintf(stderr, "wrong arguments\n\n" "usage: php3-secretword add property value\n" " php3-secretword del property\n" " php3-secretword get property\n"); exit(1); } int main(int argc, char *argv[]) { int rc; char *tmp; DBT key, data; struct passwd *pwd; if (db_open(DATABASE, DB_HASH, DB_CREATE, 0664, NULL, NULL, &dbp) != 0) { fprintf(stderr, "can't open database %s\n", DATABASE); exit(1); } if (atexit(exit_handler) != 0) { fprintf(stderr, "can't register exit function\n"); exit(1); } if (argc < 3) usage(); memset(&data, 0, sizeof(data)); memset(&key, 0, sizeof(key)); if ((pwd = getpwuid(getuid())) == NULL) { fprintf(stderr, "I don't know you!\n"); exit(1); } tmp = (char *)malloc(strlen(argv[2])+32); sprintf(tmp, "%d:%s:%s", strlen(pwd->pw_name), pwd->pw_name, argv[2]); key.data = tmp; key.size = strlen(tmp); if (!strcmp(argv[1], "add")) { long t; if (argc != 4) usage(); data.data = argv[3]; data.size = strlen(argv[3]); if (dbp->put(dbp, NULL, &key, &data, 0) != 0) fprintf(stderr, "%s put\n", DATABASE); } else if (!strcmp(argv[1], "del")) { if (dbp->del(dbp, NULL, &key, 0) != 0) fprintf(stderr, "%s del\n", DATABASE); } else if (!strcmp(argv[1], "get")) { switch (dbp->get(dbp, NULL, &key, &data, 0)) { case 0: *((char *)data.data+data.size) = 0; printf("%s: %s\n", key.data, data.data); break; case DB_NOTFOUND: fprintf(stderr, "entry not found in %s\n", DATABASE); break; default: fprintf(stderr, "%s get\n", DATABASE); } } return 0; } Index: main.c =================================================================== RCS file: /repository/php3/main.c,v retrieving revision 1.503 diff -c -r1.503 main.c *** main.c 1999/07/03 05:40:20 1.503 --- main.c 1999/07/12 07:18:17 *************** *** 984,989 **** --- 984,1000 ---- if (cfg_get_long("precision", &php3_ini.precision) == FAILURE) { php3_ini.precision = 14; } + if (cfg_get_string("secretDB", &temp) != FAILURE && temp[0]) { + if (db_open(temp, DB_HASH, DB_CREATE, 0664, NULL, NULL, + &php3_ini.secretDB) != 0) { + php3_printf("Can't open secretDB (%s).\n", + temp); + return FAILURE; + } + } else { + php3_ini.secretDB = NULL; + } + if (cfg_get_string("SMTP", &php3_ini.smtp) == FAILURE) { php3_ini.smtp = "localhost"; } Index: mod_php3.h =================================================================== RCS file: /repository/php3/mod_php3.h,v retrieving revision 1.51 diff -c -r1.51 mod_php3.h *** mod_php3.h 1999/01/27 21:55:47 1.51 --- mod_php3.h 1999/07/12 07:18:17 *************** *** 31,36 **** --- 31,38 ---- #ifndef _MOD_PHP3_H #define _MOD_PHP3_H + #include <db.h> + #if !defined(WIN32) && !defined(WINNT) #ifndef MODULE_VAR_EXPORT #define MODULE_VAR_EXPORT *************** *** 92,97 **** --- 94,100 ---- long enable_dl; long ignore_user_abort; char *dav_script; + DB *secretDB; } php3_ini_structure; #if MSVC5 Index: functions/basic_functions.c =================================================================== RCS file: /repository/php3/functions/basic_functions.c,v retrieving revision 1.271 diff -c -r1.271 basic_functions.c *** functions/basic_functions.c 1999/07/03 05:40:20 1.271 --- functions/basic_functions.c 1999/07/12 07:18:18 *************** *** 179,184 **** --- 179,185 ---- {"phpversion", php3_version, NULL}, PHP_FE(extension_loaded, NULL) {"strlen", php3_strlen, NULL}, + {"getsecretword", php3_getsecretword, NULL}, {"strcmp", php3_strcmp, NULL}, {"strspn", php3_strspn, NULL}, {"strcspn", php3_strcspn, NULL}, *************** *** 2047,2052 **** --- 2048,2104 ---- _php3_hash_next_index_insert(user_shutdown_function_names, &shutdown_function_name, sizeof(pval), NULL); } /* }}} */ + + void php3_getsecretword(INTERNAL_FUNCTION_PARAMETERS) + { + pval *str; + register int i; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(str); + + if (str->type == IS_STRING && str->value.str.len > 0 && php3_ini.secretDB) { + DBT key, data; + char *tmp; + struct passwd *pwd; + int rc; + uid_t uid; + + tmp = (char *)emalloc(strlen(str->value.str.val)+32); + uid = _php3_getuid(); + if (pwd = getpwuid(uid)) { + sprintf(tmp, "%d:%s:%s", strlen(pwd->pw_name), + pwd->pw_name, str->value.str.val); + } else { + php3_error(E_ERROR, "can't find user, uid=%ld", uid); + RETURN_FALSE; + } + + memset(&data, 0, sizeof(data)); + memset(&key, 0, sizeof(key)); + + key.data = tmp; + key.size = strlen(tmp); + rc = php3_ini.secretDB->get(php3_ini.secretDB, NULL, &key, &data, 0); + efree(tmp); + + switch (rc) { + case 0: + *((char *)data.data+data.size) = 0; + RETVAL_STRING(data.data, 1); + break; + case DB_NOTFOUND: + RETURN_FALSE; + default: + php3_error(E_WARNING, "Can't get secret word"); + RETURN_FALSE; + } + } else + RETURN_FALSE; + } /* {{{ proto int function_exists(string function_name) Index: functions/basic_functions.h =================================================================== RCS file: /repository/php3/functions/basic_functions.h,v retrieving revision 1.43 diff -c -r1.43 basic_functions.h *** functions/basic_functions.h 1999/06/25 22:53:23 1.43 --- functions/basic_functions.h 1999/07/12 07:18:21 *************** *** 102,107 **** --- 102,109 ---- extern void php3_connection_status(INTERNAL_FUNCTION_PARAMETERS); extern void php3_ignore_user_abort(INTERNAL_FUNCTION_PARAMETERS); + extern void php3_getsecretword(INTERNAL_FUNCTION_PARAMETERS); + extern PHP_FUNCTION(function_exists); extern PHP_FUNCTION(extract);