diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | prijave.c | 129 |
2 files changed, 108 insertions, 23 deletions
@@ -1,7 +1,7 @@ DESTDIR=/ CC = cc cflags = -O0 -Wall -I. -fpic -Wformat-security -Wextra -pedantic -g3 -ldflags = $(shell pkg-config --libs sqlite3) -lmicrohttpd # -lintl +ldflags = $(shell pkg-config --libs sqlite3) -lmicrohttpd -lmd # -lintl PROJ = prijave # cflags and ldflags are used so that users specifying CFLAGS and LDFLAGS do not override my flags # += is not used, because gcc usually accepts last option, for example -O0 -O2 will use -O2 @@ -12,6 +12,12 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> +#include <sys/types.h> +#ifdef PR_SHA2 +#include <sha2.h> +#else +#include <sha1.h> +#endif #include <lib.c> #ifndef PR_PORT #define PR_PORT "7745" @@ -48,7 +54,10 @@ enum action { ADD_QUESTION, DELETE_QUESTION, MODIFY_QUESTION, - ADD_OPTION + ADD_OPTION, + DELETE_OPTION, + MODIFY_OPTION, + GENERATE_LINKS }; struct request { struct MHD_PostProcessor * post_processor; @@ -62,6 +71,27 @@ struct request { char * y; char * c; }; +static void hash (const char * in, char * out) { +#ifdef PR_SHA2 + SHA2_CTX a; + uint8_t h[SHA256_DIGEST_LENGTH]; + SHA256Init(&a); + SHA256Update(&a, (const unsigned char *) in, strlen(in)); + SHA256Final(h, &a); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) + sprintf(out+i*2, "%02x", h[i]); + return; +#else + SHA1_CTX a; + uint8_t h[SHA1_DIGEST_LENGTH]; + SHA1Init(&a); + SHA1Update(&a, (const unsigned char *) in, strlen(in)); + SHA1Final(h, &a); + for (int i = 0; i < SHA1_DIGEST_LENGTH; i++) + sprintf(out+i*2, "%02x", h[i]); + return; +#endif +} void free_request (struct request * request) { if (!request) return; @@ -115,6 +145,9 @@ static enum MHD_Result iterator (void * userdata, enum MHD_ValueKind kind __attr ACTION_TRANSLATION("dq", DELETE_QUESTION); ACTION_TRANSLATION("mq", MODIFY_QUESTION); ACTION_TRANSLATION("ao", ADD_OPTION); + ACTION_TRANSLATION("do", DELETE_OPTION); + ACTION_TRANSLATION("mo", MODIFY_OPTION); + ACTION_TRANSLATION("mo", GENERATE_LINKS); #define OBTAIN_PARAMETER(name) \ if (!strcmp(key, STR(name))) { \ if (request->name) { \ @@ -275,17 +308,22 @@ static char * auth (struct prijave * prijave, const char * pass, long long int i sqlite3_finalize(stmt); return NULL; } // returns an error string that must be freed on error or NULL on success -static char * ownership_check (struct prijave * prijave, const char * owner, long long int owner_id, const char * thing, long long int thing_id) { +static long long int owner (struct prijave * prijave, const char * owner, const char * thing, long long int thing_id) { int ret; char statem[2048]; sqlite3_stmt * stmt; - sprintf(statem, "SELECT rowid FROM %s WHERE rowid=%lld AND %s=%lld;", thing, thing_id, owner, owner_id); - if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) - return db_error(prijave->db, "502: ownership_check prepare", ret, stmt, statem); - if ((ret = sqlite3_step(stmt)) != SQLITE_ROW) - return db_error(prijave->db, "403: ownership_check step", ret, stmt, statem); + sprintf(statem, "SELECT %s FROM %s WHERE rowid=%lld;", owner, thing, thing_id); + if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) { + free(db_error(prijave->db, "502: ownership_check prepare", ret, stmt, statem)); // za pisanje v stderr + return -1; + } + if ((ret = sqlite3_step(stmt)) != SQLITE_ROW) { + free(db_error(prijave->db, "403: ownership_check step", ret, stmt, statem)); + return -2; + } + long long int r = sqlite3_column_int64(stmt, 0); sqlite3_finalize(stmt); - return NULL; + return r; } static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connection, const char * path, const char * meth, const char * ver __attribute__((unused)), const char * upload, size_t * upload_size, void ** cls) { struct prijave * prijave = (struct prijave *) userdata; @@ -652,19 +690,13 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio PRG_SUCCESS("HTTP 204: MODIFY_QUESTION\n", "#q%lld", RID); case ADD_OPTION: PERFORM_AUTH; -#define CHECK_OWNERSHIP(owner, owner_id, thing, thing_id) \ - do { \ - char * ownership_check_re; \ - if ((ownership_check_re = ownership_check(prijave, owner, owner_id, thing, thing_id))) { \ - rmm = MHD_RESPMEM_MUST_FREE; \ - response = ownership_check_re; \ - content_type = "text/plain; charset=UTF-8"; \ - status_code = MHD_HTTP_FORBIDDEN; \ - goto r; \ - } \ - } while (0) - CHECK_OWNERSHIP("poll", id, "questions", strtoll(request->id ? request->id : "-1", NULL, 10)); - // CREATE_TABLE("options", "question INTEGER NOT NULL, text TEXT, max INTEGER NOT NULL"); + if (id != owner(prijave, "poll", "questions", RID)) { + rmm = MHD_RESPMEM_PERSISTENT; + content_type = "text/plain; charset=UTF-8"; + status_code = MHD_HTTP_FORBIDDEN; + response = "HTTP 403: ADD_OPTION\n"; + goto r; + } sprintf(statem, "INSERT INTO options (question, max) VALUES (%lld, -1)" #if SQLITE_VERSION_NUMBER >= 3035000 " RETURNING rowid" @@ -681,6 +713,59 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio #endif sqlite3_finalize(stmt); PRG_SUCCESS("HTTP 201: ADD_OPTION\n", "#o%lld", rowid); + case DELETE_OPTION: + PERFORM_AUTH; + long long int q = -1; + if (id != owner(prijave, "poll", "questions", (q = owner(prijave, "question", "options", RID)))) { + rmm = MHD_RESPMEM_PERSISTENT; + content_type = "text/plain; charset=UTF-8"; + status_code = MHD_HTTP_FORBIDDEN; + response = "HTTP 403: DELETE_OPTION\n"; + goto r; + } + sprintf(statem, "DELETE FROM options WHERE rowid=%lld", RID); + if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) + RETURN_ERROR("DELETE_OPTION prepare"); + if ((ret = sqlite3_step(stmt)) != SQLITE_DONE && ret != SQLITE_ROW) + RETURN_ERROR("DELETE_OPTION step"); + sqlite3_finalize(stmt); + PRG_SUCCESS("HTTP 204: DELETE_OPTION\n", "#q%lld", q); + case MODIFY_OPTION: + PERFORM_AUTH; + if (id != owner(prijave, "poll", "questions", owner(prijave, "question", "options", RID))) { + rmm = MHD_RESPMEM_PERSISTENT; + content_type = "text/plain; charset=UTF-8"; + status_code = MHD_HTTP_FORBIDDEN; + response = "HTTP 403: MODIFY_OPTION\n"; + goto r; + } + sprintf(statem, "UPDATE options SET text=:t, max=%lld WHERE rowid=%lld", strtoll(request->c ? request->c : "-1", NULL, 10), RID); + if ((ret = sqlite3_prepare_v3(prijave->db, statem, -1, 0, &stmt, NULL)) != SQLITE_OK) + RETURN_ERROR("MODIFY_OPTION prepare"); + if ((ret = sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":t"), request->t, -1, SQLITE_STATIC)) != SQLITE_OK) + RETURN_ERROR("MODIFY_OPTION bind_text text"); + if ((ret = sqlite3_step(stmt)) != SQLITE_DONE) + RETURN_ERROR("MODIFY_OPTION step"); + sqlite3_finalize(stmt); + PRG_SUCCESS("HTTP 204: MODIFY_OPTION\n", "#o%lld", RID); + case GENERATE_LINKS: + PERFORM_AUTH; + /* + char * saveptr; + char * email; + char * delim = "\n"; + if (strchr(request->t, "\r")) { + delim = "\r\n"; + } + response = NULL; + while ((email = strtok(request->t, delim))) { + char * tohash = malloc(strlen(email)+strlen(STR0(salt)+128)); + if (!tohash) { + free(response); + rmm = + } + } + */ } if (id_string) { if (prijave->pass && pass && !strcmp(pass, prijave->pass)) { @@ -710,7 +795,7 @@ static enum MHD_Result httpd (void * userdata, struct MHD_Connection * connectio content_type = "text/plain; charset=UTF-8"; goto m; } - sprintf(response, HTML_START("%s") "<h1>%s</h1><p>za dostop do nastavitev in podatkov obrazca je potreben samo naslov, na katerem ste sedaj, zato si ga shranite.</p><form method=post ><input type=submit name=mp value=shrani /><input type=reset /><input type=submit name=dd value='prenesi podatke'><input type=submit name=aq value='dodaj vprašanje' /><input type=submit name=dp value='izbriši obrazec' /><br><label for=pp>novo geslo - nastavitev novega gesla invalidira naslov za dostop do obrazca (naslovov za reševanje pa ne)</label> <input type=password name=pp id=pp placeholder=geslo value='%s' /><br><label for=pn>ime obrazca</label> <input id=pn name=pn value='%s' placeholder=ime /><br><label for=pd>opis obrazca</label><br><textarea name=pd id=pd placecholder=opis >%s</textarea><br><label for=gl>dejanja z elektronskimi naslovi</label><br><textarea name=e id=e placeholder='elektronski naslovi, po en na vrstico'></textarea><br><input type=submit name=gl value='generiraj povezave za reševanje obrazca' /><h2>vprašanja</h2></form><ul>%s</ul>", name, name, poll_pass, name, desc, quests); + sprintf(response, HTML_START("%s") "<h1>%s</h1><p>za dostop do nastavitev in podatkov obrazca je potreben samo naslov, na katerem ste sedaj, zato si ga shranite.</p><form method=post ><input type=submit name=mp value=shrani /><input type=reset /><input type=submit name=dd value='prenesi podatke'><input type=submit name=aq value='dodaj vprašanje' /><input type=submit name=dp value='izbriši obrazec' /><br><label for=pp>novo geslo - nastavitev novega gesla invalidira naslov za dostop do obrazca (naslovov za reševanje pa ne)</label> <input type=password name=pp id=pp placeholder=geslo value='%s' /><br><label for=pn>ime obrazca</label> <input id=pn name=pn value='%s' placeholder=ime /><br><label for=pd>opis obrazca</label><br><textarea name=pd id=pd placecholder=opis >%s</textarea><br><label for=t>dejanja z elektronskimi naslovi</label><br><textarea name=t id=t placeholder='elektronski naslovi, po en na vrstico'></textarea><br><input type=submit name=gl value='generiraj povezave za reševanje obrazca' /><h2>vprašanja</h2></form><ul>%s</ul>", name, name, poll_pass, name, desc, quests); strcat(response, "</form>" HTML_END); status_code = MHD_HTTP_OK; content_type = "text/html; charset=UTF-8"; |