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