auth.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdarg.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7. #include "auth.h"
  8. #include "sqlite3.h"
  9. #include "util.h"
  10. #include "list.h"
  11. #include "dSFMT.h"
  12. #include "ow-crypt.h"
  13. #define BEGIN(db) sqlite3_exec(db->conn, "BEGIN", NULL, NULL, NULL)
  14. #define COMMIT(db) sqlite3_exec(db->conn, "COMMIT", NULL, NULL, NULL)
  15. #define buildList(...) _buildList(__VA_ARGS__, NULL)
  16. #define insertRow(...) _insertRow(__VA_ARGS__, NULL)
  17. struct account {
  18. char* username;
  19. char* passhash;
  20. char* salt;
  21. char* sid;
  22. LIST* groups;
  23. LIST* perms;
  24. };
  25. struct group {
  26. char* groupname;
  27. LIST* members;
  28. LIST* perms;
  29. };
  30. struct passdata {
  31. char* passhash;
  32. char* salt;
  33. };
  34. typedef struct account account;
  35. typedef struct group group;
  36. typedef struct passdata passdata;
  37. //#define group struct group
  38. char* err; //Global SQLite3 error message buffer
  39. void init_prng() { init_gen_rand(time(NULL)); }
  40. static int selectCellWhereText(authdb* db, char* result, char* column, char* table, char* target, char* text) {
  41. char sql[MAXLEN_SQL]; memset(sql, 0, MAXLEN_SQL);
  42. sqlite3_stmt* stmt;
  43. snprintf(sql, MAXLEN_SQL, "select %s from %s where %s='%s'", column, table, target, text);
  44. if (sqlite3_prepare_v2(db->conn, sql, MAXLEN_SQL, &stmt, NULL) != SQLITE_OK) { return 1; }
  45. if (sqlite3_step(stmt) != SQLITE_ROW) { return 1; }
  46. snprintf(result, MAXLEN_RESULT, "%s", (char*)sqlite3_column_text(stmt, 0));
  47. sqlite3_finalize(stmt);
  48. return 0;
  49. }
  50. static int selectRowWhereText(authdb* db, LIST* list, char* column, char* table, char* target, char* text) {
  51. int c; int cmax;
  52. char sql[MAXLEN_SQL]; memset(sql, 0, MAXLEN_SQL);
  53. sqlite3_stmt* stmt;
  54. snprintf(sql, MAXLEN_SQL, "select %s from %s where %s='%s'", column, table, target, text);
  55. if (sqlite3_prepare_v2(db->conn, sql, MAXLEN_SQL, &stmt, NULL) != SQLITE_OK) { return 1; }
  56. if (sqlite3_step(stmt) != SQLITE_ROW) { return 1; }
  57. cmax = sqlite3_column_count(stmt);
  58. if (!cmax) { return 1; }
  59. do {
  60. c = 0;
  61. while (c < cmax) {
  62. listQueue(list, strndup((char*)sqlite3_column_text(stmt, c), MAXLEN_RESULT));
  63. c++;
  64. }
  65. } while (sqlite3_step(stmt) == SQLITE_ROW);
  66. sqlite3_finalize(stmt);
  67. return 0;
  68. }
  69. static int updateRowWhereText(authdb* db, char* column, char* table, char* value, char* target, char* against) {
  70. int status = 0;
  71. char* sql = malloc(MAXLEN_SQL); memset(sql, 0, MAXLEN_SQL);
  72. snprintf(sql, MAXLEN_SQL, "update %s set %s='%s' where %s='%s'", table, column, value, target, against);
  73. logs("SQL: %s", sql);
  74. BEGIN(db);
  75. if (sqlite3_exec(db->conn, sql, NULL, NULL, &err) != SQLITE_OK) {
  76. logs("updateRowWhereText: sqlite3_exec failed: %s", err);
  77. logs("updateRowWhereText: statement was: %s", sql);
  78. status = 1;
  79. }
  80. COMMIT(db);
  81. #if DO_FREE
  82. sqlite3_free(err);
  83. free(sql);
  84. #endif
  85. return status;
  86. }
  87. static int _insertRow(authdb* db, char* table, char* val, ...) {
  88. va_list ap; int l;
  89. char* v = val;
  90. int c=0; int status=0;
  91. char* sql = malloc(MAXLEN_SQL); memset(sql, 0, MAXLEN_SQL);
  92. char* vals = malloc(MAXLEN_SQL); memset(vals, 0, MAXLEN_SQL);
  93. va_start(ap, val);
  94. while (v) {
  95. snprintf(vals, MAXLEN_SQL, "'%s',", v);
  96. l = strlen(vals);
  97. vals += l; c+= l;
  98. v = va_arg(ap, char*);
  99. }
  100. va_end(ap);
  101. vals -= c;
  102. vals[(c-1)] = '\0'; //Strip off the last comma
  103. snprintf(sql, MAXLEN_SQL, "insert into %s values (%s)", table, vals);
  104. logs("SQL: %s", sql);
  105. BEGIN(db);
  106. if (sqlite3_exec(db->conn, sql, NULL, NULL, &err) != SQLITE_OK) {
  107. logs("insertRow: sqlite3_exec failed: %s", err);
  108. logs("insertRow: statement was: %s", sql);
  109. status=1;
  110. }
  111. COMMIT(db);
  112. #if DO_FREE
  113. sqlite3_free(err);
  114. deleteListIterator(i);
  115. free(vals);
  116. free(sql);
  117. #endif
  118. return status;
  119. }
  120. static LIST* _buildList(char* v, ...) {
  121. char* arg;
  122. va_list ap;
  123. LIST* list = newList();
  124. listQueue(list, v);
  125. va_start(ap, v);
  126. while ((arg = va_arg(ap, char*))) {
  127. listQueue(list, arg);
  128. }
  129. return list;
  130. }
  131. #if DO_FREE
  132. static void freeAccount(account* acc) {
  133. deleteList(acc->groups);
  134. deleteList(acc->perms);
  135. free(acc->username);
  136. free(acc->passhash);
  137. free(acc->salt);
  138. free(acc->sid);
  139. free(acc);
  140. }
  141. static void freeGroup(group* grp) {
  142. deleteList(grp->members);
  143. deleteList(grp->perms);
  144. free(grp->groupname);
  145. free(grp);
  146. }
  147. static void freePassdata(passdata *pd) {
  148. free(pd->passhash);
  149. free(pd->salt);
  150. free(pd);
  151. }
  152. #endif
  153. static account* newAccount() {
  154. account* acc = malloc(sizeof(*acc));
  155. if (!acc) { return NULL; }
  156. memset(acc, 0, sizeof(account));
  157. acc->groups = newList();
  158. acc->perms = newList();
  159. return acc;
  160. }
  161. static group* newGroup() {
  162. group* grp = malloc(sizeof(*grp));
  163. if (!grp) { return NULL; }
  164. memset(grp, 0, sizeof(group));
  165. grp->perms = newList();
  166. grp->members = newList();
  167. return grp;
  168. }
  169. static void getGroup(authdb* db, char* groupname, group* grp) {
  170. grp->groupname = groupname;
  171. selectRowWhereText(db, grp->members, "username", "groups_membership", "groupname", groupname);
  172. selectRowWhereText(db, grp->perms, "perm", "groups_perms", "groupname", groupname);
  173. }
  174. static void getAccount(authdb* db, char* user, account* acc) {
  175. LIST* fields = newList();
  176. selectRowWhereText(db, acc->groups, "groupname", "groups_membership", "username", user);
  177. selectRowWhereText(db, acc->perms, "perm", "users_perms", "username", user);
  178. selectRowWhereText(db, fields, "*", "auth", "username", user);
  179. acc->username = (char*)listPop(fields); acc->passhash = (char*)listPop(fields);
  180. acc->salt = (char*)listPop(fields); acc->sid = (char*)listPop(fields);
  181. deleteList(fields);
  182. }
  183. static int connect_db(char* path, sqlite3** conn) {
  184. if (sqlite3_open(path, conn) != SQLITE_OK) {
  185. logs("AUTH: sqlite3_open failed");
  186. return 1;
  187. }
  188. return 0;
  189. }
  190. static int init_authdb(authdb* db) {
  191. if (connect_db(db->path, &db->conn)) {
  192. return 1;
  193. }
  194. char* query = read_file("initauth.sql", MAXLEN_FILE, 1);
  195. if (!query) {
  196. logs("AUTH: couldn't read init SQL file");
  197. return 1;
  198. }
  199. BEGIN(db);
  200. if (sqlite3_exec(db->conn, query, NULL, NULL, &err) != SQLITE_OK) {
  201. logs("AUTH: database initialization failed: %s", err);
  202. #if DO_FREE
  203. sqlite3_free(err);
  204. #endif
  205. return 1;
  206. }
  207. COMMIT(db);
  208. return 0;
  209. }
  210. static passdata* newPassdata() {
  211. passdata* pd = malloc(sizeof(*pd));
  212. memset(pd, 0, sizeof(passdata));
  213. pd->passhash = malloc((MAXLEN_PASSHASH+1)); memset(pd->passhash, 0, (MAXLEN_PASSHASH+1));
  214. pd->salt = malloc(MAXLEN_SALT); memset(pd->salt, 0, MAXLEN_SALT);
  215. return pd;
  216. }
  217. static passdata* hash_password(char* password, char* salt) {
  218. passdata* pd = newPassdata();
  219. if (!salt) {
  220. double salt[(LEN_SALT/8)]; memset(salt, 0, LEN_SALT); //8 chars to 1 double
  221. fill_array_close1_open2(salt, (LEN_SALT/8)); //Get entropy for salt
  222. crypt_gensalt_rn("$2a$", BCRYPT_ROUNDS, (char*)salt, LEN_SALT, pd->salt, MAXLEN_SALT); //Generate salt
  223. }
  224. else { snprintf(pd->salt, MAXLEN_SALT, "%s", salt); }
  225. crypt_rn(password, pd->salt, pd->passhash, MAXLEN_PASSHASH); //Generate password hash
  226. return pd;
  227. }
  228. int user_addgroup(authdb* db, char* username, char* groupname) {
  229. if (insertRow(db, "groups_membership", username, groupname)) { return 1; }
  230. return 0;
  231. }
  232. int group_addperm(authdb* db, char* groupname, char* perm) {
  233. if (insertRow(db, "groups_perms", groupname, perm)) { return 1; }
  234. return 0;
  235. }
  236. int user_addperm(authdb* db, char* username, char* perm) {
  237. if (insertRow(db, "users_perms", username, perm)) { return 1; }
  238. return 0;
  239. }
  240. int register_perm(authdb *db, char* perm, char* desc) {
  241. if (insertRow(db, "perms", desc)) { return 1; }
  242. return 0;
  243. }
  244. int register_group(authdb *db, char* groupname) {
  245. if (insertRow(db, "auth", groupname)) { return 1; }
  246. return 0;
  247. }
  248. int user_validate(authdb *db, char* username, char* password) {
  249. char* salt; char* passhash; passdata* pd;
  250. LIST* data = newList();
  251. if (selectRowWhereText(db, data, "passhash,salt", "auth", "username", username)) { return 1; }
  252. passhash = listPop(data);
  253. salt = listPop(data);
  254. if (!salt || !passhash) { return 1; }
  255. pd = hash_password(password, salt);
  256. if (!pd) { return 1; }
  257. if (!(strncmp(passhash, pd->passhash, MAXLEN_PASSHASH))) { return 0; }
  258. return 1;
  259. }
  260. int user_setpass(authdb *db, char* username, char* password) {
  261. passdata* pd = hash_password(password, NULL);
  262. if (updateRowWhereText(db, "passhash", "auth", pd->passhash, "username", username) ||
  263. updateRowWhereText(db, "salt", "auth", pd->salt, "username", username))
  264. { return 1; }
  265. return 0;
  266. }
  267. int register_user(authdb *db, char* username, char* password, char* groupname, ...) {
  268. va_list ap;
  269. int status = 0;
  270. char sql[MAXLEN_SQL]; memset(sql, 0, MAXLEN_SQL);
  271. if (strlen(password) > MAXLEN_PASSWORD) {
  272. logs("register_user: Password for '%s' exceeds maximum length of %d", username, MAXLEN_PASSWORD);
  273. return 1;
  274. }
  275. passdata* pd = hash_password(password, NULL);
  276. if (insertRow(db, "auth", username, pd->passhash, pd->salt, "")) {
  277. logs("register_user: Couldn't insert row");
  278. return 1;
  279. }
  280. //Join supplied groups - move into own function
  281. va_start(ap, groupname);
  282. do {
  283. snprintf(sql, MAXLEN_SQL, "insert into groups_membership values('%s','%s')", username, groupname);
  284. if (sqlite3_exec(db->conn, sql, NULL, NULL, NULL) != SQLITE_OK) {
  285. logs("register_user: Couldn't add user '%s' to group '%s'", username, groupname);
  286. status=1;
  287. break;
  288. }
  289. } while ((groupname = va_arg(ap, char*)));
  290. va_end(ap);
  291. #if DO_FREE
  292. free(pd);
  293. #endif
  294. return status;
  295. }
  296. authdb* new_authdb(char* path) {
  297. authdb* db = malloc(sizeof(authdb)); memset(db, 0, sizeof(authdb));
  298. db->path = malloc(MAXLEN_PATH); memset(db->path, 0, MAXLEN_PATH);
  299. snprintf(db->path, MAXLEN_PATH, "%s", path);
  300. if (access(db->path, F_OK) == -1) {
  301. logs("AUTH: initializing new database at '%s'", path);
  302. if (init_authdb(db)) { return NULL; }
  303. }
  304. else if (connect_db(db->path, &db->conn)) {
  305. return NULL;
  306. }
  307. return db;
  308. }
  309. int group_has_perm(authdb* db, char* groupname, char* perm) {
  310. char* p;
  311. group* grp = newGroup();
  312. getGroup(db, groupname, grp);
  313. if (!grp) { return 1; }
  314. LIST_ITERATOR* ip = newListIterator(grp->perms);
  315. ITERATE_LIST(p, ip) {
  316. if (!(strncmp(p, perm, MAXLEN_PERM))) { return 0; }
  317. }
  318. #if DO_FREE
  319. deleteListIterator(ip);
  320. freeGroup(grp);
  321. #endif
  322. return 1;
  323. }
  324. int user_has_perm(authdb* db, char* user, char* perm) {
  325. char* p; char* g;
  326. int status = 1;
  327. account* acc = newAccount();
  328. getAccount(db, user, acc);
  329. if (!acc) { return 1; }
  330. LIST_ITERATOR* ip = newListIterator(acc->perms);
  331. LIST_ITERATOR* ig;
  332. //Check if user has permission assigned directly
  333. ITERATE_LIST(p, ip) {
  334. if (!(strncmp(p,perm,MAXLEN_PERM))) { status=0; break;}
  335. }
  336. if (status) {
  337. ig = newListIterator(acc->groups);
  338. //Check if any of the users groups have the permission
  339. ITERATE_LIST(g, ig) {
  340. if (!(group_has_perm(db, g, perm))) { status=0; break; }
  341. }
  342. }
  343. #if DO_FREE
  344. deleteListIterator(ip);
  345. deleteListIterator(ig);
  346. freeAccount(acc);
  347. #endif
  348. return status;
  349. }