// ========================================================================== // METHOD limadb::createlist // ========================================================================== bool limadb::createlist (const statstring &listid, const string &owner, bool usemoderation, bool usesubmoderation, const string &plistname, const string &psubjecttag) { // Filter format, reject doubles. if (!listid.sval().validate (VALID_LISTNAME)) { ::fprintf (stderr, "Invalid listame %s\n", listid.str()); return false; } if (listexists (listid)) { ::fprintf (stderr, "List already exists\n"); return false; } // Create a 64bits salt. string mysalt = gensalt(); mysalt = mysalt.encode64 (); string listname = plistname; string subjecttag = psubjecttag; // If no listname is provided, use the 'user'-part of the // list's address. if (! listname.strlen()) { listname = listid.sval().copyuntil ('@'); } // If no subject tag is provided, use the listname. if (! subjecttag.strlen()) { subjecttag = listname; } // Fill in database metadata. value data; data["address"] = listid; data["subjecttag"] = subjecttag; data["name"] = listname; data["moderation_posts"] = (int) usemoderation; data["moderation_subscriptions"] = usesubmoderation?1:0; data["replyto"] = 0; data["owner"] = owner; data["salt"] = mysalt; // Send create statement dbquery q (DB); q.insertinto (tlists).values (data); if (! q.execvoid()) { ::fprintf (stderr, "SQL query failed\n"); return false; } return true; };
/* * Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB * in /etc/login.defs is "yes", the salt string will be prefixed by "$1$" * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible * version of crypt() instead of the standard one. * Other methods can be set with ENCRYPT_METHOD * * The method can be forced with the meth parameter. * If NULL, the method will be defined according to the MD5_CRYPT_ENAB and * ENCRYPT_METHOD login.defs variables. * * If meth is specified, an additional parameter can be provided. * * For the SHA256 and SHA512 method, this specifies the number of rounds * (if not NULL). */ /*@observer@*/const char *crypt_make_salt (/*@null@*/const char *meth, /*@null@*/void *arg) { /* Max result size for the SHA methods: * +3 $5$ * +17 rounds=999999999$ * +16 salt * +1 \0 */ static char result[40]; size_t salt_len = 8; const char *method; result[0] = '\0'; if (NULL != meth) method = meth; else { method = getdef_str ("ENCRYPT_METHOD"); if (NULL == method) { method = getdef_bool ("MD5_CRYPT_ENAB") ? "MD5" : "DES"; } } if (0 == strcmp (method, "MD5")) { MAGNUM(result, '1'); #ifdef USE_SHA_CRYPT } else if (0 == strcmp (method, "SHA256")) { MAGNUM(result, '5'); strcat(result, SHA_salt_rounds((int *)arg)); salt_len = SHA_salt_size(); } else if (0 == strcmp (method, "SHA512")) { MAGNUM(result, '6'); strcat(result, SHA_salt_rounds((int *)arg)); salt_len = SHA_salt_size(); #endif /* USE_SHA_CRYPT */ } else if (0 != strcmp (method, "DES")) { fprintf (stderr, _("Invalid ENCRYPT_METHOD value: '%s'.\n" "Defaulting to DES.\n"), method); result[0] = '\0'; } /* * Concatenate a pseudo random salt. */ assert (sizeof (result) > strlen (result) + salt_len); strncat (result, gensalt (salt_len), sizeof (result) - strlen (result) - 1); return result; }
int main(int argc, char **argv){ int err; char *err_msg; sqlite3 *db; char dbpath[PATH_MAX] = {0}; char *dellabel = NULL; int addflag = 0; int showflag = 0; int delflag = 0; int listflag = 0; int initdb = 0; int c; while ((c = getopt (argc, argv, "asd:lh")) != -1){ switch (c){ case 'a': addflag = 1; break; case 's': showflag = 1; break; case 'd': delflag = 1; dellabel = optarg; break; case 'l': listflag = 1; break; case 'h': default: fprintf(stdout, usage); exit(0); } } if (addflag & delflag){ fprintf(stderr, "Specify either -a or -d, not both\n"); exit(1); } if (fs_datadir_init(DATA_DIR)){ perror("Failed to open config directory"); exit(1); } if (fs_exists_relative(DB_NAME) != 0){ puts("First run, initializing db..."); initdb = 1; } strcat(dbpath, fs_datadir_getpath()); strcat(dbpath, "/"); strcat(dbpath, DB_NAME); if ((err = sqlite3_open(dbpath, &db)) != SQLITE_OK){ fprintf(stderr, "sqlite3_open failure: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } if (initdb){ char *sql = "CREATE TABLE passwords (label TEXT, salt TEXT, hash TEXT, created DATETIME, last_success DATETIME);"; err = sqlite3_exec(db, sql, 0, 0, &err_msg); if (err != SQLITE_OK){ fprintf(stderr, "SQL error: %s\n", err_msg); sqlite3_free(err_msg); sqlite3_close(db); exit(1); } } if (listflag){ int err; char *err_msg; err = sqlite3_exec(db, "SELECT created, label FROM passwords ORDER BY label ASC", passlist_cb, NULL, &err_msg); if (err != SQLITE_OK){ fprintf(stderr, "SQL SELECT error: %s\n", err_msg); sqlite3_free(err_msg); sqlite3_close(db); exit(1); } exit(0); } if (delflag){ int err; char *yn; if (sql_label_exists(db, dellabel) == 0){ fprintf(stderr, "A password with that label does not exist\n"); sqlite3_close(db); exit(1); } fprintf(stdout, "You are about to delete the entry labeled ``%s''\n", dellabel); err = stdin_prompt("Continue [yn]", &yn); if (err != 0){ exit(0); } if (strcmp("y", yn) == 0){ sql_label_delete(db, dellabel); puts("Entry deleted."); } exit(0); } if (addflag){ char *label, *pass; time_t rawtime; struct tm *timeinfo; char timestr[24] = {0}; char *sql_p = "INSERT INTO passwords (label, salt, hash, created, last_success) VALUES (?, ?, ?, ?, ?);"; sqlite3_stmt *res; char hash[SHA512_OUTPUT]; puts("Adding new password"); if (stdin_prompt("label", &label)){ sqlite3_close(db); fprintf(stderr, "entry canceled\n"); exit(1); } if (sql_label_exists(db, label) != 0){ fprintf(stderr, "A password with that label already exists.\n"); exit(1); } if (stdin_prompt("pass", &pass)){ sqlite3_close(db); fprintf(stderr, "entry canceled\n"); exit(1); } time(&rawtime); timeinfo = localtime(&rawtime); strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", timeinfo); err = sqlite3_prepare_v2(db, sql_p, -1, &res, 0); if (err == SQLITE_OK){ char salt[SALT_LEN+1]; gensalt(salt, SALT_LEN); sha512(pass, salt, hash); sqlite3_bind_text(res, 1, label, strlen(label), NULL); sqlite3_bind_text(res, 2, salt, SALT_LEN, NULL); sqlite3_bind_text(res, 3, hash, strlen(hash), NULL); sqlite3_bind_text(res, 4, timestr, strlen(timestr), NULL); sqlite3_bind_text(res, 5, timestr, strlen(timestr), NULL); } else { fprintf(stderr, "Failed to prepare insert statement: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } err = sqlite3_step(res); free(label); free(pass); if (err != SQLITE_OK && err != SQLITE_DONE){ fprintf(stderr, "Failed to execute prepared insert: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } sqlite3_finalize(res); puts("Entry added successfully."); } else { int entries = 0; sqlite3_stmt *res; err = sqlite3_prepare_v2(db, "SELECT count(*) from passwords", -1, &res, 0); if (err != SQLITE_OK){ fprintf(stderr, "SQL prepare failure: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } err = sqlite3_step(res); if (err == SQLITE_ROW){ entries = sqlite3_column_int(res, 0); } sqlite3_finalize(res); if (entries == 0){ fprintf(stderr, "No passwords in db\n"); exit(0); } fprintf(stdout, "%d passwords in db.\n", entries); err = sqlite3_exec(db, "SELECT label, salt, hash FROM passwords ORDER BY RANDOM()", passcheck_cb, &showflag, &err_msg); if (err != SQLITE_OK){ fprintf(stderr, "SQL SELECT error: %s\n", err_msg); sqlite3_free(err_msg); sqlite3_close(db); exit(1); } puts("Finished."); } sqlite3_close(db); return 0; }