1 /*
    2  * WARNING: automatically generated by ort-c-source 0.8.5.
    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> /* int64_t */
   11 #include <stdlib.h>
   12 #include <string.h>
   13 #include <time.h> /* _XOPEN_SOURCE and gmtime_r()*/
   14 #include <unistd.h>
   15 
   16 #include <sqlbox.h>
   17 #include <kcgi.h>
   18 #include <kcgijson.h>
   19 
   20 #include "rbac-ex1.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_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 "ort", which contains role information.
   38  */
   39 struct	ort {
   40 	/* Hidden database connection */
   41 	struct sqlbox *db;
   42 };
   43 
   44 /*
   45  * Define our table columns.
   46  * Since we're using roles, this is all internal to the source and not 
   47  * exported.
   48  */
   49 #define DB_SCHEMA_USER(_x) \
   50 	#_x ".email" "," \
   51 	#_x ".hash" "," \
   52 	#_x ".id"
   53 #define DB_SCHEMA_SESSION(_x) \
   54 	#_x ".userid" "," \
   55 	#_x ".id"
   56 
   57 /*
   58  * Our full set of SQL statements.
   59  * We define these beforehand because that's how sqlbox(3) handles 
   60  * statement generation.
   61  * Notice the "AS" part: this allows for multiple inner joins without 
   62  * ambiguity.
   63  */
   64 static	const char *const stmts[STMT__MAX] = {
   65 	/* STMT_USER_BY_UNIQUE_email */
   66 	"SELECT " DB_SCHEMA_USER(user) " FROM user WHERE user.email = ?",
   67 	/* STMT_USER_BY_UNIQUE_id */
   68 	"SELECT " DB_SCHEMA_USER(user) " FROM user WHERE user.id = ?",
   69 	/* STMT_USER_BY_SEARCH_0 */
   70 	"SELECT " DB_SCHEMA_USER(user) " FROM user "
   71 		"WHERE user.email = ?",
   72 	/* STMT_SESSION_BY_UNIQUE_id */
   73 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_a) " FROM session "
   74 		"INNER JOIN user AS _a ON _a.id=session.userid "
   75 		"WHERE session.id = ?",
   76 	/* STMT_SESSION_BY_SEARCH_0 */
   77 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_a) " FROM session "
   78 		"INNER JOIN user AS _a ON _a.id=session.userid "
   79 		"WHERE session.id = ?",
   80 	/* STMT_SESSION_INSERT */
   81 	"INSERT INTO session (userid) VALUES (?)",
   82 	/* STMT_SESSION_DELETE_0 */
   83 	"DELETE FROM session WHERE id = ?",
   84 };
   85 
   86 const struct kvalid valid_keys[VALID__MAX] = {
   87 	{ valid_user_email, "user-email" },
   88 	{ valid_user_hash, "user-hash" },
   89 	{ valid_user_id, "user-id" },
   90 	{ valid_session_userid, "session-userid" },
   91 	{ valid_session_id, "session-id" },
   92 };
   93 
   94 /*
   95  * Finally, all of the functions we'll use.
   96  */
   97 
   98 void
   99 db_trans_open(struct ort *ctx, size_t id, int mode)
  100 {
  101 	struct sqlbox *db = ctx->db;
  102 	int c;
  103 
  104 	if (mode < 0)
  105 		c = sqlbox_trans_exclusive(db, 0, id);
  106 	else if (mode > 0)
  107 		c = sqlbox_trans_immediate(db, 0, id);
  108 	else
  109 		c = sqlbox_trans_deferred(db, 0, id);
  110 	if (!c)
  111 		exit(EXIT_FAILURE);
  112 }
  113 
  114 void
  115 db_trans_rollback(struct ort *ctx, size_t id)
  116 {
  117 	struct sqlbox *db = ctx->db;
  118 
  119 	if (!sqlbox_trans_rollback(db, 0, id))
  120 		exit(EXIT_FAILURE);
  121 }
  122 
  123 void
  124 db_trans_commit(struct ort *ctx, size_t id)
  125 {
  126 	struct sqlbox *db = ctx->db;
  127 
  128 	if (!sqlbox_trans_commit(db, 0, id))
  129 		exit(EXIT_FAILURE);
  130 }
  131 
  132 void
  133 db_logging_data(struct ort *ort, const void *arg, size_t sz)
  134 {
  135 
  136 	if (!sqlbox_msg_set_dat(ort->db, arg, sz))
  137 		exit(EXIT_FAILURE);
  138 }
  139 
  140 struct ort *
  141 db_open(const char *file)
  142 {
  143 
  144 	return db_open_logging(file, NULL, NULL, NULL);
  145 }
  146 
  147 struct ort *
  148 db_open_logging(const char *file,
  149 	void (*log)(const char *, void *),
  150 	void (*log_short)(const char *, ...), void *log_arg)
  151 {
  152 	size_t i;
  153 	struct ort *ctx = NULL;
  154 	struct sqlbox_cfg cfg;
  155 	struct sqlbox *db = NULL;
  156 	struct sqlbox_pstmt pstmts[STMT__MAX];
  157 	struct sqlbox_src srcs[1] = {
  158 		{ .fname = (char *)file,
  159 		  .mode = SQLBOX_SRC_RW }
  160 	};
  161 
  162 	memset(&cfg, 0, sizeof(struct sqlbox_cfg));
  163 	cfg.msg.func = log;
  164 	cfg.msg.func_short = log_short;
  165 	cfg.msg.dat = log_arg;
  166 	cfg.srcs.srcs = srcs;
  167 	cfg.srcs.srcsz = 1;
  168 	cfg.stmts.stmts = pstmts;
  169 	cfg.stmts.stmtsz = STMT__MAX;
  170 
  171 	for (i = 0; i < STMT__MAX; i++)
  172 		pstmts[i].stmt = (char *)stmts[i];
  173 
  174 	ctx = malloc(sizeof(struct ort));
  175 	if (ctx == NULL)
  176 		goto err;
  177 
  178 	if ((db = sqlbox_alloc(&cfg)) == NULL)
  179 		goto err;
  180 	ctx->db = db;
  181 
  182 	/*
  183 	 * Now actually open the database.
  184 	 * If this succeeds, then we're good to go.
  185 	 */
  186 
  187 	if (sqlbox_open_async(db, 0))
  188 		return ctx;
  189 err:
  190 	sqlbox_free(db);
  191 	free(ctx);
  192 	return NULL;
  193 }
  194 
  195 void
  196 db_close(struct ort *p)
  197 {
  198 	if (p == NULL)
  199 		return;
  200 	sqlbox_free(p->db);
  201 	free(p);
  202 }
  203 
  204 /*
  205  * Fill in a user from an open statement "stmt".
  206  * This starts grabbing results from "pos", which may be NULL to start 
  207  * from zero.
  208  * This follows DB_SCHEMA_USER's order for columns.
  209  */
  210 static void
  211 db_user_fill(struct ort *ctx, struct user *p, const struct sqlbox_parmset *set, size_t *pos)
  212 {
  213 	size_t i = 0;
  214 
  215 	if (pos == NULL)
  216 		pos = &i;
  217 	memset(p, 0, sizeof(*p));
  218 	if (sqlbox_parm_string_alloc
  219 	    (&set->ps[(*pos)++], &p->email, NULL) == -1)
  220 		exit(EXIT_FAILURE);
  221 	if (sqlbox_parm_string_alloc
  222 	    (&set->ps[(*pos)++], &p->hash, NULL) == -1)
  223 		exit(EXIT_FAILURE);
  224 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->id) == -1)
  225 		exit(EXIT_FAILURE);
  226 }
  227 
  228 static void
  229 db_user_fill_r(struct ort *ctx, struct user *p,
  230 	const struct sqlbox_parmset *res, size_t *pos)
  231 {
  232 	size_t i = 0;
  233 
  234 	if (pos == NULL)
  235 		pos = &i;
  236 	db_user_fill(ctx, p, res, pos);
  237 }
  238 
  239 /*
  240  * Free resources from "p" and all nested objects.
  241  * Does not free the "p" pointer itself.
  242  * Has no effect if "p" is NULL.
  243  */
  244 static void
  245 db_user_unfill(struct user *p)
  246 {
  247 	if (p == NULL)
  248 		return;
  249 	free(p->email);
  250 	free(p->hash);
  251 }
  252 
  253 static void
  254 db_user_unfill_r(struct user *p)
  255 {
  256 	if (p == NULL)
  257 		return;
  258 	db_user_unfill(p);
  259 }
  260 
  261 void
  262 db_user_free(struct user *p)
  263 {
  264 	db_user_unfill_r(p);
  265 	free(p);
  266 }
  267 
  268 void
  269 json_user_data(struct kjsonreq *r, const struct user *p)
  270 {
  271 	kjson_putstringp(r, "email", p->email);
  272 
  273 	/* Omitting hash: is a password hash. */
  274 
  275 	kjson_putintp(r, "id", p->id);
  276 }
  277 
  278 void
  279 json_user_obj(struct kjsonreq *r, const struct user *p)
  280 {
  281 	kjson_objp_open(r, "user");
  282 	json_user_data(r, p);
  283 	kjson_obj_close(r);
  284 }
  285 
  286 int
  287 valid_user_email(struct kpair *p)
  288 {
  289 	if (!kvalid_email(p))
  290 		return 0;
  291 	return 1;
  292 }
  293 
  294 int
  295 valid_user_hash(struct kpair *p)
  296 {
  297 	if (!kvalid_string(p))
  298 		return 0;
  299 	return 1;
  300 }
  301 
  302 int
  303 valid_user_id(struct kpair *p)
  304 {
  305 	if (!kvalid_int(p))
  306 		return 0;
  307 	return 1;
  308 }
  309 
  310 struct user *
  311 db_user_get_creds(struct ort *ctx, const char *v1, const char *v2)
  312 {
  313 	struct user *p = NULL;
  314 	const struct sqlbox_parmset *res;
  315 	struct sqlbox *db = ctx->db;
  316 	struct sqlbox_parm parms[1];
  317 
  318 	memset(parms, 0, sizeof(parms));
  319 	parms[0].sparm = v1;
  320 	parms[0].type = SQLBOX_PARM_STRING;
  321 
  322 	if (!sqlbox_prepare_bind_async
  323 	    (db, 0, STMT_USER_BY_SEARCH_0, 1, parms, 0))
  324 		exit(EXIT_FAILURE);
  325 	if ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  326 		p = malloc(sizeof(struct user));
  327 		if (p == NULL) {
  328 			perror(NULL);
  329 			exit(EXIT_FAILURE);
  330 		}
  331 		db_user_fill_r(ctx, p, res, NULL);
  332 		if (crypt_checkpass(v2, p->hash) == -1) {
  333 			db_user_free(p);
  334 			p = NULL;
  335 		}
  336 	}
  337 	if (res == NULL)
  338 		exit(EXIT_FAILURE);
  339 	if (!sqlbox_finalise(db, 0))
  340 		exit(EXIT_FAILURE);
  341 	return p;
  342 }
  343 
  344 /*
  345  * Fill in a session from an open statement "stmt".
  346  * This starts grabbing results from "pos", which may be NULL to start 
  347  * from zero.
  348  * This follows DB_SCHEMA_SESSION's order for columns.
  349  */
  350 static void
  351 db_session_fill(struct ort *ctx, struct session *p, const struct sqlbox_parmset *set, size_t *pos)
  352 {
  353 	size_t i = 0;
  354 
  355 	if (pos == NULL)
  356 		pos = &i;
  357 	memset(p, 0, sizeof(*p));
  358 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->userid) == -1)
  359 		exit(EXIT_FAILURE);
  360 	if (sqlbox_parm_int(&set->ps[(*pos)++], &p->id) == -1)
  361 		exit(EXIT_FAILURE);
  362 }
  363 
  364 static void
  365 db_session_fill_r(struct ort *ctx, struct session *p,
  366 	const struct sqlbox_parmset *res, size_t *pos)
  367 {
  368 	size_t i = 0;
  369 
  370 	if (pos == NULL)
  371 		pos = &i;
  372 	db_session_fill(ctx, p, res, pos);
  373 	db_user_fill_r(ctx, &p->user, res, pos);
  374 }
  375 
  376 /*
  377  * Free resources from "p" and all nested objects.
  378  * Does not free the "p" pointer itself.
  379  * Has no effect if "p" is NULL.
  380  */
  381 static void
  382 db_session_unfill(struct session *p)
  383 {
  384 	if (p == NULL)
  385 		return;
  386 }
  387 
  388 static void
  389 db_session_unfill_r(struct session *p)
  390 {
  391 	if (p == NULL)
  392 		return;
  393 	db_session_unfill(p);
  394 	db_user_unfill_r(&p->user);
  395 }
  396 
  397 void
  398 db_session_free(struct session *p)
  399 {
  400 	db_session_unfill_r(p);
  401 	free(p);
  402 }
  403 
  404 int64_t
  405 db_session_insert(struct ort *ctx, int64_t v1)
  406 {
  407 	int rc;
  408 	int64_t id = -1;
  409 	struct sqlbox *db = ctx->db;
  410 	struct sqlbox_parm parms[1];
  411 
  412 	memset(parms, 0, sizeof(parms));
  413 	parms[0].iparm = v1;
  414 	parms[0].type = SQLBOX_PARM_INT;
  415 
  416 	rc = sqlbox_exec(db, 0, STMT_SESSION_INSERT, 
  417 	     1, parms, SQLBOX_STMT_CONSTRAINT);
  418 	if (rc == SQLBOX_CODE_ERROR)
  419 		exit(EXIT_FAILURE);
  420 	else if (rc != SQLBOX_CODE_OK)
  421 		return (-1);
  422 	if (!sqlbox_lastid(db, 0, &id))
  423 		exit(EXIT_FAILURE);
  424 	return id;
  425 }
  426 
  427 void
  428 json_session_data(struct kjsonreq *r, const struct session *p)
  429 {
  430 	kjson_objp_open(r, "user");
  431 	json_user_data(r, &p->user);
  432 	kjson_obj_close(r);
  433 	kjson_putintp(r, "userid", p->userid);
  434 	kjson_putintp(r, "id", p->id);
  435 }
  436 
  437 void
  438 json_session_obj(struct kjsonreq *r, const struct session *p)
  439 {
  440 	kjson_objp_open(r, "session");
  441 	json_session_data(r, p);
  442 	kjson_obj_close(r);
  443 }
  444 
  445 int
  446 valid_session_userid(struct kpair *p)
  447 {
  448 	if (!kvalid_int(p))
  449 		return 0;
  450 	return 1;
  451 }
  452 
  453 int
  454 valid_session_id(struct kpair *p)
  455 {
  456 	if (!kvalid_int(p))
  457 		return 0;
  458 	return 1;
  459 }
  460 
  461 struct session *
  462 db_session_get_id(struct ort *ctx, int64_t v1)
  463 {
  464 	struct session *p = NULL;
  465 	const struct sqlbox_parmset *res;
  466 	struct sqlbox *db = ctx->db;
  467 	struct sqlbox_parm parms[1];
  468 
  469 	memset(parms, 0, sizeof(parms));
  470 	parms[0].iparm = v1;
  471 	parms[0].type = SQLBOX_PARM_INT;
  472 
  473 	if (!sqlbox_prepare_bind_async
  474 	    (db, 0, STMT_SESSION_BY_SEARCH_0, 1, parms, 0))
  475 		exit(EXIT_FAILURE);
  476 	if ((res = sqlbox_step(db, 0)) != NULL && res->psz) {
  477 		p = malloc(sizeof(struct session));
  478 		if (p == NULL) {
  479 			perror(NULL);
  480 			exit(EXIT_FAILURE);
  481 		}
  482 		db_session_fill_r(ctx, p, res, NULL);
  483 	}
  484 	if (res == NULL)
  485 		exit(EXIT_FAILURE);
  486 	if (!sqlbox_finalise(db, 0))
  487 		exit(EXIT_FAILURE);
  488 	return p;
  489 }
  490 
  491 int
  492 db_session_delete_by_id_eq(struct ort *ctx, int64_t v1)
  493 {
  494 	enum sqlbox_code c;
  495 	struct sqlbox *db = ctx->db;
  496 	struct sqlbox_parm parms[1];
  497 
  498 	memset(parms, 0, sizeof(parms));
  499 	parms[0].iparm = v1;
  500 	parms[0].type = SQLBOX_PARM_INT;
  501 
  502 	c = sqlbox_exec
  503 		(db, 0, STMT_SESSION_DELETE_0,
  504 		 1, parms, SQLBOX_STMT_CONSTRAINT);
  505 	if (c == SQLBOX_CODE_ERROR)
  506 		exit(EXIT_FAILURE);
  507 	return (c == SQLBOX_CODE_OK) ? 1 : 0;
  508 }
  509