1 /*
    2  * WARNING: automatically generated by kwebapp 0.4.12.
    3  * DO NOT EDIT!
    4  */
    5 #include <sys/queue.h>
    6 
    7 #include <assert.h>
    8 #include <stdarg.h>
    9 #include <stdint.h>
   10 #include <stdio.h>
   11 #include <stdlib.h>
   12 #include <string.h>
   13 #include <unistd.h>
   14 
   15 #include <ksql.h>
   16 #include <kcgi.h>
   17 #include <kcgijson.h>
   18 
   19 #include "rbac-ex2.h"
   20 
   21 /*
   22  * All SQL statements we'll later define in "stmts".
   23  */
   24 enum	stmt {
   25 	STMT_USER_BY_UNIQUE_email,
   26 	STMT_USER_BY_UNIQUE_id,
   27 	STMT_USER_BY_SEARCH_0,
   28 	STMT_USER_INSERT,
   29 	STMT_SESSION_BY_UNIQUE_id,
   30 	STMT_SESSION_BY_SEARCH_0,
   31 	STMT_SESSION_INSERT,
   32 	STMT_SESSION_DELETE_0,
   33 	STMT__MAX
   34 };
   35 
   36 /*
   37  * Definition of our opaque "kwbp", which contains role information.
   38  */
   39 struct	kwbp {
   40 	/* Hidden database connection */
   41 	struct ksql *db;
   42 	/* Current RBAC role. */
   43 	enum kwbp_role role;
   44 };
   45 
   46 /*
   47  * A saved role state attached to generated objects.
   48  * We'll use this to make sure that we shouldn't export data that we've 
   49  * kept unexported in a given role (at the time of acquisition).
   50  */
   51 struct	kwbp_store {
   52 	/* Role at the time of acquisition. */
   53 	enum kwbp_role role;
   54 };
   55 
   56 /*
   57  * Define our table columns.
   58  * Since we're using roles, this is all internal to the source and not 
   59  * exported.
   60  */
   61 #define DB_SCHEMA_USER(_x) \
   62 	#_x ".email" "," \
   63 	#_x ".hash" "," \
   64 	#_x ".id"
   65 #define DB_SCHEMA_SESSION(_x) \
   66 	#_x ".userid" "," \
   67 	#_x ".id"
   68 
   69 /*
   70  * Our full set of SQL statements.
   71  * We define these beforehand because that's how ksql(3) handles 
   72  * statement generation.
   73  * Notice the "AS" part: this allows for multiple inner joins without 
   74  * ambiguity.
   75  */
   76 static	const char *const stmts[STMT__MAX] = {
   77 	/* STMT_USER_BY_UNIQUE_email */
   78 	"SELECT " DB_SCHEMA_USER(user) " FROM user WHERE user.email = ?",
   79 	/* STMT_USER_BY_UNIQUE_id */
   80 	"SELECT " DB_SCHEMA_USER(user) " FROM user WHERE user.id = ?",
   81 	/* STMT_USER_BY_SEARCH_0 */
   82 	"SELECT " DB_SCHEMA_USER(user) " FROM user "
   83 		"WHERE user.email = ?",
   84 	/* STMT_USER_INSERT */
   85 	"INSERT INTO user (email,hash) VALUES (?,?)",
   86 	/* STMT_SESSION_BY_UNIQUE_id */
   87 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_a) " FROM session "
   88 		"INNER JOIN user AS _a ON _a.id=session.userid "
   89 		"WHERE session.id = ?",
   90 	/* STMT_SESSION_BY_SEARCH_0 */
   91 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_a) " FROM session "
   92 		"INNER JOIN user AS _a ON _a.id=session.userid "
   93 		"WHERE session.id = ?",
   94 	/* STMT_SESSION_INSERT */
   95 	"INSERT INTO session (userid) VALUES (?)",
   96 	/* STMT_SESSION_DELETE_0 */
   97 	"DELETE FROM session WHERE id = ?",
   98 };
   99 
  100 const struct kvalid valid_keys[VALID__MAX] = {
  101 	{ valid_user_email, "user-email" },
  102 	{ valid_user_hash, "user-hash" },
  103 	{ valid_user_id, "user-id" },
  104 	{ valid_session_userid, "session-userid" },
  105 	{ valid_session_id, "session-id" },
  106 };
  107 
  108 /*
  109  * Finally, all of the functions we'll use.
  110  */
  111 
  112 void
  113 db_trans_open(struct kwbp *p, size_t id, int mode)
  114 {
  115 	if (mode < 0)
  116 		ksql_trans_exclopen(p->db, id);
  117 	else if (mode > 0)
  118 		ksql_trans_singleopen(p->db, id);
  119 	else
  120 		ksql_trans_open(p->db, id);
  121 }
  122 
  123 void
  124 db_trans_rollback(struct kwbp *p, size_t id)
  125 {
  126 	ksql_trans_rollback(p->db, id);
  127 }
  128 
  129 void
  130 db_trans_commit(struct kwbp *p, size_t id)
  131 {
  132 	ksql_trans_commit(p->db, id);
  133 }
  134 
  135 struct kwbp *
  136 db_open(const char *file)
  137 {
  138 	struct ksqlcfg cfg;
  139 	struct ksql *db;
  140 	int role_perms_none[4];
  141 	int role_stmts_none[STMT__MAX];
  142 	int role_perms_default[4];
  143 	int role_stmts_default[STMT__MAX];
  144 	int role_perms_user[4];
  145 	int role_stmts_user[STMT__MAX];
  146 	int role_perms_admin[4];
  147 	int role_stmts_admin[STMT__MAX];
  148 	struct ksqlrole roles[4];
  149 	struct kwbp *ctx;
  150 
  151 	memset(roles, 0, sizeof(roles));
  152 	ctx = malloc(sizeof(struct kwbp));
  153 	if (NULL == ctx)
  154 		return(NULL);
  155 
  156 	/*
  157 	 * Initialise our roles and statements: disallow all statements and 
  158 	 * role transitions except for ROLE_default, which can transition to 
  159 	 * anybody.
  160 	 */
  161 
  162 	roles[ROLE_none].roles = role_perms_none;
  163 	roles[ROLE_none].stmts = role_stmts_none;
  164 	memset(role_perms_none, 0, sizeof(int) * 4);
  165 	memset(role_stmts_none, 0, sizeof(int) * STMT__MAX);
  166 	role_perms_default[ROLE_none] = 1;
  167 
  168 	roles[ROLE_default].roles = role_perms_default;
  169 	roles[ROLE_default].stmts = role_stmts_default;
  170 	roles[ROLE_default].flags = KSQLROLE_OPEN;
  171 	memset(role_stmts_default, 0, sizeof(int) * STMT__MAX);
  172 	role_perms_default[ROLE_default] = 1;
  173 
  174 	roles[ROLE_user].roles = role_perms_user;
  175 	roles[ROLE_user].stmts = role_stmts_user;
  176 	memset(role_perms_user, 0, sizeof(int) * 4);
  177 	memset(role_stmts_user, 0, sizeof(int) * STMT__MAX);
  178 	role_perms_default[ROLE_user] = 1;
  179 
  180 	roles[ROLE_admin].roles = role_perms_admin;
  181 	roles[ROLE_admin].stmts = role_stmts_admin;
  182 	memset(role_perms_admin, 0, sizeof(int) * 4);
  183 	memset(role_stmts_admin, 0, sizeof(int) * STMT__MAX);
  184 	role_perms_default[ROLE_admin] = 1;
  185 
  186 	/*
  187 	 * Assign roles.
  188 	 * Everybody can transition to themselves (this is always allowed in 
  189 	 * ksql(3), so make it explicit for us).
  190 	 * Furthermore, everybody is allowed to transition into ROLE_none.
  191 	 */
  192 
  193 	role_perms_none[ROLE_none] = 1;
  194 	role_perms_user[ROLE_user] = 1;
  195 	role_perms_user[ROLE_none] = 1;
  196 	role_perms_admin[ROLE_admin] = 1;
  197 	role_perms_admin[ROLE_none] = 1;
  198 
  199 	/* White-listing fields and operations for structure "user". */
  200 
  201 	role_stmts_default[STMT_USER_BY_UNIQUE_email] = 1;
  202 	role_stmts_default[STMT_USER_BY_UNIQUE_id] = 1;
  203 	role_stmts_user[STMT_USER_BY_UNIQUE_email] = 1;
  204 	role_stmts_user[STMT_USER_BY_UNIQUE_id] = 1;
  205 	role_stmts_user[STMT_USER_BY_SEARCH_0] = 1;
  206 	role_stmts_admin[STMT_USER_BY_UNIQUE_email] = 1;
  207 	role_stmts_admin[STMT_USER_BY_UNIQUE_id] = 1;
  208 
  209 	/* White-listing fields and operations for structure "session". */
  210 
  211 	role_stmts_default[STMT_SESSION_BY_UNIQUE_id] = 1;
  212 	role_stmts_default[STMT_SESSION_BY_SEARCH_0] = 1;
  213 	role_stmts_user[STMT_SESSION_BY_UNIQUE_id] = 1;
  214 	role_stmts_user[STMT_SESSION_BY_SEARCH_0] = 1;
  215 	role_stmts_user[STMT_SESSION_INSERT] = 1;
  216 	role_stmts_user[STMT_SESSION_DELETE_0] = 1;
  217 	role_stmts_admin[STMT_SESSION_BY_UNIQUE_id] = 1;
  218 	role_stmts_admin[STMT_SESSION_BY_SEARCH_0] = 1;
  219 	role_stmts_admin[STMT_SESSION_INSERT] = 1;
  220 	role_stmts_admin[STMT_SESSION_DELETE_0] = 1;
  221 
  222 	ksql_cfg_defaults(&cfg);
  223 	cfg.stmts.stmts = stmts;
  224 	cfg.stmts.stmtsz = STMT__MAX;
  225 	cfg.roles.roles = roles;
  226 	cfg.roles.rolesz = 4;
  227 	cfg.roles.defrole = ROLE_default;
  228 
  229 	db = ksql_alloc(&cfg);
  230 	if (NULL == db) {
  231 		free(ctx);
  232 		return(NULL);
  233 	}
  234 	ctx->db = db;
  235 	ksql_open(db, file);
  236 	ctx->role = ROLE_default;
  237 	return(ctx);
  238 }
  239 
  240 void
  241 db_close(struct kwbp *p)
  242 {
  243 	if (NULL == p)
  244 		return;
  245 	ksql_close(p->db);
  246 	ksql_free(p->db);
  247 	free(p);
  248 }
  249 
  250 void
  251 db_role(struct kwbp *ctx, enum kwbp_role r)
  252 {
  253 	ksql_role(ctx->db, r);
  254 	if (r == ctx->role)
  255 		return;
  256 	if (ROLE_none == ctx->role)
  257 		abort();
  258 
  259 	switch (ctx->role) {
  260 	case ROLE_default:
  261 		ctx->role = r;
  262 		return;
  263 	case ROLE_user:
  264 		abort();
  265 		/* NOTREACHED */
  266 	case ROLE_admin:
  267 		abort();
  268 		/* NOTREACHED */
  269 	default:
  270 		abort();
  271 	}
  272 }
  273 
  274 enum kwbp_role
  275 db_role_current(struct kwbp *ctx)
  276 {
  277 	return(ctx->role);
  278 }
  279 
  280 enum kwbp_role
  281 db_role_stored(struct kwbp_store *s)
  282 {
  283 	return(s->role);
  284 }
  285 
  286 static void
  287 db_user_fill(struct kwbp *ctx, struct user *p, struct ksqlstmt *stmt, size_t *pos)
  288 {
  289 	size_t i = 0;
  290 	enum ksqlc c;
  291 
  292 	if (NULL == pos)
  293 		pos = &i;
  294 	memset(p, 0, sizeof(*p));
  295 	c = ksql_result_str_alloc(stmt, &p->email, (*pos)++);
  296 	if (KSQL_OK != c)
  297 		exit(EXIT_FAILURE);
  298 	c = ksql_result_str_alloc(stmt, &p->hash, (*pos)++);
  299 	if (KSQL_OK != c)
  300 		exit(EXIT_FAILURE);
  301 	c = ksql_result_int(stmt, &p->id, (*pos)++);
  302 	if (KSQL_OK != c)
  303 		exit(EXIT_FAILURE);
  304 	p->priv_store = malloc(sizeof(struct kwbp_store));
  305 	if (NULL == p->priv_store) {
  306 		perror(NULL);
  307 		exit(EXIT_FAILURE);
  308 	}
  309 	p->priv_store->role = ctx->role;
  310 }
  311 
  312 static void
  313 db_user_fill_r(struct kwbp *ctx, struct user *p, struct ksqlstmt *stmt, size_t *pos)
  314 {
  315 	size_t i = 0;
  316 
  317 	if (NULL == pos)
  318 		pos = &i;
  319 	db_user_fill(ctx, p, stmt, pos);
  320 }
  321 
  322 static void
  323 db_user_unfill(struct user *p)
  324 {
  325 	if (NULL == p)
  326 		return;
  327 	free(p->email);
  328 	free(p->hash);
  329 	free(p->priv_store);
  330 }
  331 
  332 static void
  333 db_user_unfill_r(struct user *p)
  334 {
  335 	if (NULL == p)
  336 		return;
  337 
  338 	db_user_unfill(p);
  339 }
  340 
  341 void
  342 db_user_free(struct user *p)
  343 {
  344 	db_user_unfill_r(p);
  345 	free(p);
  346 }
  347 
  348 void
  349 json_user_data(struct kjsonreq *r, const struct user *p)
  350 {
  351 	kjson_putstringp(r, "email", p->email);
  352 
  353 	/* Omitting hash: is a password hash. */
  354 
  355 	kjson_putintp(r, "id", p->id);
  356 }
  357 
  358 void
  359 json_user_obj(struct kjsonreq *r, const struct user *p)
  360 {
  361 	kjson_objp_open(r, "user");
  362 	json_user_data(r, p);
  363 	kjson_obj_close(r);
  364 }
  365 
  366 int
  367 valid_user_email(struct kpair *p)
  368 {
  369 	if ( ! kvalid_email(p))
  370 		return 0;
  371 	return 1;
  372 }
  373 
  374 int
  375 valid_user_hash(struct kpair *p)
  376 {
  377 	if ( ! kvalid_string(p))
  378 		return 0;
  379 	return 1;
  380 }
  381 
  382 int
  383 valid_user_id(struct kpair *p)
  384 {
  385 	if ( ! kvalid_int(p))
  386 		return 0;
  387 	return 1;
  388 }
  389 
  390 struct user *
  391 db_user_get_creds(struct kwbp *ctx, const char *v1, const char *v2)
  392 {
  393 	struct ksqlstmt *stmt;
  394 	struct user *p = NULL;
  395 	struct ksql *db = ctx->db;
  396 
  397 	ksql_stmt_alloc(db, &stmt, NULL, STMT_USER_BY_SEARCH_0);
  398 	ksql_bind_str(stmt, 0, v1);
  399 	if (KSQL_ROW == ksql_stmt_step(stmt)) {
  400 		p = malloc(sizeof(struct user));
  401 		if (NULL == p) {
  402 			perror(NULL);
  403 			exit(EXIT_FAILURE);
  404 		}
  405 		db_user_fill_r(ctx, p, stmt, NULL);
  406 		if (NULL != p && crypt_checkpass(v2, p->hash) < 0) {
  407 			db_user_free(p);
  408 			p = NULL;
  409 		}
  410 	}
  411 	ksql_stmt_free(stmt);
  412 	return p;
  413 }
  414 
  415 static void
  416 db_session_fill(struct kwbp *ctx, struct session *p, struct ksqlstmt *stmt, size_t *pos)
  417 {
  418 	size_t i = 0;
  419 	enum ksqlc c;
  420 
  421 	if (NULL == pos)
  422 		pos = &i;
  423 	memset(p, 0, sizeof(*p));
  424 	c = ksql_result_int(stmt, &p->userid, (*pos)++);
  425 	if (KSQL_OK != c)
  426 		exit(EXIT_FAILURE);
  427 	c = ksql_result_int(stmt, &p->id, (*pos)++);
  428 	if (KSQL_OK != c)
  429 		exit(EXIT_FAILURE);
  430 	p->priv_store = malloc(sizeof(struct kwbp_store));
  431 	if (NULL == p->priv_store) {
  432 		perror(NULL);
  433 		exit(EXIT_FAILURE);
  434 	}
  435 	p->priv_store->role = ctx->role;
  436 }
  437 
  438 static void
  439 db_session_fill_r(struct kwbp *ctx, struct session *p, struct ksqlstmt *stmt, size_t *pos)
  440 {
  441 	size_t i = 0;
  442 
  443 	if (NULL == pos)
  444 		pos = &i;
  445 	db_session_fill(ctx, p, stmt, pos);
  446 	db_user_fill_r(ctx, &p->user, stmt, pos);
  447 }
  448 
  449 static void
  450 db_session_unfill(struct session *p)
  451 {
  452 	if (NULL == p)
  453 		return;
  454 	free(p->priv_store);
  455 }
  456 
  457 static void
  458 db_session_unfill_r(struct session *p)
  459 {
  460 	if (NULL == p)
  461 		return;
  462 
  463 	db_session_unfill(p);
  464 	db_user_unfill_r(&p->user);
  465 }
  466 
  467 void
  468 db_session_free(struct session *p)
  469 {
  470 	db_session_unfill_r(p);
  471 	free(p);
  472 }
  473 
  474 int64_t
  475 db_session_insert(struct kwbp *ctx, int64_t v1)
  476 {
  477 	struct ksqlstmt *stmt;
  478 	int64_t id = -1;
  479 	struct ksql *db = ctx->db;
  480 
  481 	ksql_stmt_alloc(db, &stmt, NULL, STMT_SESSION_INSERT);
  482 	ksql_bind_int(stmt, 0, v1);
  483 	if (KSQL_DONE == ksql_stmt_cstep(stmt))
  484 		ksql_lastid(db, &id);
  485 	ksql_stmt_free(stmt);
  486 	return(id);
  487 }
  488 
  489 void
  490 json_session_data(struct kjsonreq *r, const struct session *p)
  491 {
  492 	kjson_objp_open(r, "user");
  493 	json_user_data(r, &p->user);
  494 	kjson_obj_close(r);
  495 	kjson_putintp(r, "userid", p->userid);
  496 	kjson_putintp(r, "id", p->id);
  497 }
  498 
  499 void
  500 json_session_obj(struct kjsonreq *r, const struct session *p)
  501 {
  502 	kjson_objp_open(r, "session");
  503 	json_session_data(r, p);
  504 	kjson_obj_close(r);
  505 }
  506 
  507 int
  508 valid_session_userid(struct kpair *p)
  509 {
  510 	if ( ! kvalid_int(p))
  511 		return 0;
  512 	return 1;
  513 }
  514 
  515 int
  516 valid_session_id(struct kpair *p)
  517 {
  518 	if ( ! kvalid_int(p))
  519 		return 0;
  520 	return 1;
  521 }
  522 
  523 struct session *
  524 db_session_get_id(struct kwbp *ctx, int64_t v1)
  525 {
  526 	struct ksqlstmt *stmt;
  527 	struct session *p = NULL;
  528 	struct ksql *db = ctx->db;
  529 
  530 	ksql_stmt_alloc(db, &stmt, NULL, STMT_SESSION_BY_SEARCH_0);
  531 	ksql_bind_int(stmt, 0, v1);
  532 	if (KSQL_ROW == ksql_stmt_step(stmt)) {
  533 		p = malloc(sizeof(struct session));
  534 		if (NULL == p) {
  535 			perror(NULL);
  536 			exit(EXIT_FAILURE);
  537 		}
  538 		db_session_fill_r(ctx, p, stmt, NULL);
  539 	}
  540 	ksql_stmt_free(stmt);
  541 	return p;
  542 }
  543 
  544 int
  545 db_session_delete_by_id_eq(struct kwbp *ctx, int64_t v1)
  546 {
  547 	struct ksqlstmt *stmt;
  548 	enum ksqlc c;
  549 	struct ksql *db = ctx->db;
  550 
  551 	ksql_stmt_alloc(db, &stmt, NULL, STMT_SESSION_DELETE_0);
  552 	ksql_bind_int(stmt, 0, v1);
  553 	c = ksql_stmt_cstep(stmt);
  554 	ksql_stmt_free(stmt);
  555 	return(KSQL_CONSTRAINT != c);
  556 }
  557