summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-05-18 20:13:40 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2022-05-18 20:13:40 +0200
commit8ff83bf617be0b8e1653a4c8d27672c76f1fc9de (patch)
treeefd1d5329ff21faa42e1389095343eef6a1278db
parentadded options (diff)
downloadprijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar.gz
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar.bz2
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar.lz
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar.xz
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.tar.zst
prijave-8ff83bf617be0b8e1653a4c8d27672c76f1fc9de.zip
-rw-r--r--Makefile2
-rw-r--r--prijave.c129
2 files changed, 108 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index 2007c1b..00ee869 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/prijave.c b/prijave.c
index 45ed48e..4100e7f 100644
--- a/prijave.c
+++ b/prijave.c
@@ -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";