user.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * user.c
  3. *
  4. * Copyright (C) 2013 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <user.h>
  20. #include <process.h>
  21. #include <heap.h>
  22. #include <timer.h>
  23. static user_t *reference_user_by_id(uid_t uid)
  24. {
  25. user_t *user = NULL;
  26. while (enum_objects_by_type(OBJECT_USER, (object_t**)&user) == ERR_SUCCESS)
  27. {
  28. if (user->uid == uid) return user;
  29. }
  30. return NULL;
  31. }
  32. static dword_t add_user(uid_t uid, const char *name, dword_t *password_hash, qword_t privileges)
  33. {
  34. user_t *user;
  35. if ((user = reference_user_by_id(uid)) != NULL)
  36. {
  37. dereference(&user->header);
  38. return ERR_EXISTS;
  39. }
  40. if (reference_by_name(name, OBJECT_USER, (object_t**)&user))
  41. {
  42. dereference(&user->header);
  43. return ERR_EXISTS;
  44. }
  45. user = (user_t*)malloc(sizeof(user_t));
  46. if (user == NULL) return ERR_NOMEMORY;
  47. init_object(&user->header, name, OBJECT_USER);
  48. user->uid = uid;
  49. memcpy(user->password_hash, password_hash, sizeof(user->password_hash));
  50. user->privileges = privileges;
  51. dword_t ret = create_object(&user->header);
  52. if (ret != ERR_SUCCESS)
  53. {
  54. free(user->header.name);
  55. free(user);
  56. }
  57. return ret;
  58. }
  59. static void sha256_compute(byte_t *buffer, size_t size, dword_t *sum)
  60. {
  61. static const dword_t round_constants[] =
  62. {
  63. 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
  64. 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
  65. 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
  66. 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
  67. 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
  68. 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
  69. 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
  70. 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
  71. };
  72. size_t i, j;
  73. dword_t message[64];
  74. size_t num_chunks = (size >> 6) + ((size & 0x3F) > 55) ? 2 : 1;
  75. sum[0] = 0x6A09E667;
  76. sum[1] = 0xBB67AE85;
  77. sum[2] = 0x3C6EF372;
  78. sum[3] = 0xA54FF53A;
  79. sum[4] = 0x510E527F;
  80. sum[5] = 0x9B05688C;
  81. sum[6] = 0x1F83D9AB;
  82. sum[7] = 0x5BE0CD19;
  83. for (i = 0; i < num_chunks; i++)
  84. {
  85. for (j = 0; j < 64; j++)
  86. {
  87. byte_t value = 0;
  88. if ((i << 6) + j < size) value = buffer[(i << 6) + j];
  89. else if ((i << 6) + j == size) value = 0x80;
  90. else if (i == num_chunks - 1 && j >= 56) value = ((size << 3) >> ((63 - j) << 3)) & 0xFF;
  91. switch (j & 3)
  92. {
  93. case 0:
  94. message[j >> 2] = value << 24;
  95. break;
  96. case 1:
  97. message[j >> 2] |= value << 16;
  98. break;
  99. case 2:
  100. message[j >> 2] |= value << 8;
  101. break;
  102. case 3:
  103. message[j >> 2] |= value;
  104. break;
  105. }
  106. }
  107. for (j = 16; j < 64; j++)
  108. {
  109. message[j] = message[j - 7] + message[j - 16]
  110. + (((message[j - 15] >> 7) | (message[j - 15] << 25))
  111. ^ ((message[j - 15] >> 18) | (message[j - 15] << 14))
  112. ^ (message[j - 15] >> 3))
  113. + (((message[j - 2] >> 17) | (message[j - 2] << 15))
  114. ^ ((message[j - 2] >> 19) | (message[j - 2] << 13))
  115. ^ (message[j - 2] >> 10));
  116. }
  117. dword_t vars[8];
  118. for (j = 0; j < 8; j++) vars[j] = sum[j];
  119. for (j = 0; j < 64; j++)
  120. {
  121. dword_t temp1 = vars[7] + (((vars[4] >> 6) | (vars[4] << 26))
  122. ^ ((vars[4] >> 11) | (vars[4] << 21))
  123. ^ ((vars[4] >> 25) | (vars[4] << 7)))
  124. + ((vars[4] & vars[5]) ^ (~vars[4] & vars[6]))
  125. + round_constants[j] + message[j];
  126. dword_t temp2 = (((vars[0] >> 2) | (vars[0] << 30))
  127. ^ ((vars[0] >> 13) | (vars[0] << 19))
  128. ^ ((vars[0] >> 22) | (vars[0] << 10)))
  129. + ((vars[0] & vars[1]) ^ (vars[0] & vars[2]) ^ (vars[1] & vars[2]));
  130. vars[7] = vars[6];
  131. vars[6] = vars[5];
  132. vars[5] = vars[4];
  133. vars[4] = vars[3] + temp1;
  134. vars[3] = vars[2];
  135. vars[2] = vars[1];
  136. vars[1] = vars[0];
  137. vars[0] = temp1 + temp2;
  138. }
  139. for (j = 0; j < 8; j++) sum[j] += vars[j];
  140. }
  141. }
  142. bool_t check_privileges(qword_t privilege_mask)
  143. {
  144. qword_t privileges = get_current_process()->current_user->privileges;
  145. return ((privileges & privilege_mask) == privilege_mask);
  146. }
  147. dword_t get_current_uid(void)
  148. {
  149. process_t *proc = get_current_process();
  150. return proc && proc->current_user ? proc->current_user->uid : 0;
  151. }
  152. sysret_t syscall_set_user_id(uid_t uid)
  153. {
  154. process_t *proc = get_current_process();
  155. user_t *user = reference_user_by_id(uid);
  156. if (user == NULL) return ERR_NOTFOUND;
  157. if (get_previous_mode() == USER_MODE && !check_privileges(PRIVILEGE_CHANGE_UID))
  158. {
  159. dereference(&user->header);
  160. return ERR_FORBIDDEN;
  161. }
  162. if (proc->current_user) dereference(&proc->current_user->header);
  163. proc->current_user = user;
  164. return ERR_SUCCESS;
  165. }
  166. sysret_t syscall_revert_user()
  167. {
  168. process_t *proc = get_current_process();
  169. if (proc->original_user != proc->current_user)
  170. {
  171. if (proc->current_user) dereference(&proc->current_user->header);
  172. reference(&proc->original_user->header);
  173. proc->current_user = proc->original_user;
  174. return ERR_SUCCESS;
  175. }
  176. else
  177. {
  178. return ERR_INVALID;
  179. }
  180. }
  181. sysret_t syscall_create_user(uid_t uid, const char *name, dword_t *password_hash, qword_t privileges)
  182. {
  183. dword_t safe_password_hash[64];
  184. if (get_previous_mode() == USER_MODE)
  185. {
  186. if (!check_privileges(privileges | PRIVILEGE_MANAGE_USERS)) return ERR_FORBIDDEN;
  187. if (!check_usermode(password_hash, sizeof(safe_password_hash))) return ERR_BADPTR;
  188. EH_TRY
  189. {
  190. memcpy(safe_password_hash, password_hash, sizeof(safe_password_hash));
  191. password_hash = &safe_password_hash[0];
  192. }
  193. EH_CATCH
  194. {
  195. EH_ESCAPE(return ERR_BADPTR);
  196. }
  197. EH_DONE;
  198. }
  199. return add_user(uid, name, password_hash, privileges);
  200. }
  201. sysret_t syscall_delete_user(uid_t uid)
  202. {
  203. if (get_previous_mode() == USER_MODE && !check_privileges(PRIVILEGE_MANAGE_USERS))
  204. {
  205. return ERR_FORBIDDEN;
  206. }
  207. process_t *proc = NULL;
  208. dword_t ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  209. ASSERT(ret == ERR_SUCCESS || ret == ERR_NOMORE);
  210. while (ret == ERR_SUCCESS)
  211. {
  212. if (proc->current_user->uid == uid || proc->original_user->uid == uid)
  213. {
  214. dereference(&proc->header);
  215. return ERR_BUSY;
  216. }
  217. ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  218. }
  219. ASSERT(ret == ERR_NOMORE);
  220. user_t *user = reference_user_by_id(uid);
  221. if (user == NULL) return ERR_NOTFOUND;
  222. dereference(&user->header);
  223. dereference(&user->header);
  224. return ERR_SUCCESS;
  225. }
  226. sysret_t syscall_logon_user(uid_t uid, const char *password)
  227. {
  228. dword_t ret;
  229. process_t *proc = get_current_process();
  230. user_t *user = reference_user_by_id(uid);
  231. user_t *current_user = get_current_process()->current_user;
  232. char *safe_password;
  233. if (user == NULL) return ERR_NOTFOUND;
  234. if ((timer_get_milliseconds() - current_user->last_login_attempt) < LOGIN_ATTEMPT_TIMEOUT) return ERR_BUSY;
  235. if (get_previous_mode() == USER_MODE)
  236. {
  237. safe_password = copy_user_string(password);
  238. }
  239. else
  240. {
  241. safe_password = (char*)password;
  242. }
  243. if (uid == 0)
  244. {
  245. current_user->last_login_attempt = timer_get_milliseconds();
  246. ret = ERR_INVALID;
  247. goto cleanup;
  248. }
  249. char *salted = (char*)__builtin_alloca(strlen(user->name) + strlen(password) + 4);
  250. strcpy(salted, "%");
  251. strcat(salted, user->name);
  252. strcat(salted, "%");
  253. strcat(salted, password);
  254. strcat(salted, "%");
  255. dword_t hash_sum[64];
  256. sha256_compute((byte_t*)salted, strlen(salted), hash_sum);
  257. if (memcmp(hash_sum, user->password_hash, sizeof(hash_sum)) == 0)
  258. {
  259. reference(&user->header);
  260. proc->current_user = user;
  261. ret = ERR_SUCCESS;
  262. }
  263. else
  264. {
  265. user->last_login_attempt = timer_get_milliseconds();
  266. ret = ERR_INVALID;
  267. }
  268. cleanup:
  269. dereference(&user->header);
  270. if (get_previous_mode() == USER_MODE) free(safe_password);
  271. return ret;
  272. }
  273. sysret_t syscall_query_user(uid_t uid, user_info_t info_type, void *buffer, dword_t size)
  274. {
  275. dword_t ret = ERR_SUCCESS;
  276. void *safe_buffer;
  277. user_t *user = reference_user_by_id(uid);
  278. if (user == NULL) return ERR_NOTFOUND;
  279. if (get_previous_mode() == USER_MODE)
  280. {
  281. if (!check_usermode(buffer, size))
  282. {
  283. ret = ERR_BADPTR;
  284. goto cleanup;
  285. }
  286. safe_buffer = malloc(size);
  287. if (safe_buffer == NULL)
  288. {
  289. ret = ERR_NOMEMORY;
  290. goto cleanup;
  291. }
  292. memset(safe_buffer, 0, size);
  293. }
  294. else
  295. {
  296. safe_buffer = buffer;
  297. }
  298. switch (info_type)
  299. {
  300. case USER_NAME_INFO:
  301. if (size >= sizeof(strlen(user->name) + 1)) strcpy(safe_buffer, user->name);
  302. else ret = ERR_SMALLBUF;
  303. break;
  304. case USER_PRIVILEGE_INFO:
  305. if (size >= sizeof(qword_t)) *((qword_t*)safe_buffer) = user->privileges;
  306. else ret = ERR_SMALLBUF;
  307. break;
  308. default:
  309. ret = ERR_INVALID;
  310. }
  311. if (get_previous_mode() == USER_MODE)
  312. {
  313. EH_TRY memcpy(buffer, safe_buffer, size);
  314. EH_CATCH ret = ERR_BADPTR;
  315. EH_DONE;
  316. }
  317. cleanup:
  318. dereference(&user->header);
  319. return ret;
  320. }
  321. void user_init()
  322. {
  323. dword_t blank_password_hash[64] = { 0 };
  324. if (add_user(0, "root", blank_password_hash, ALL_PRIVILEGES) != ERR_SUCCESS)
  325. {
  326. KERNEL_CRASH("Failed to create root user!");
  327. }
  328. user_t *root = reference_user_by_id(0);
  329. reference(&root->header);
  330. kernel_process->original_user = kernel_process->current_user = root;
  331. }