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