log_puredb.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include <config.h>
  2. #ifdef WITH_PUREDB
  3. #include "ftpd.h"
  4. #include "messages.h"
  5. #include "log_puredb.h"
  6. #include "pure-pw.h"
  7. #include "../puredb/src/puredb_read.h"
  8. #include "utils.h"
  9. #ifdef HAVE_LIBSODIUM
  10. # include <sodium.h>
  11. #endif
  12. #ifdef WITH_DMALLOC
  13. # include <dmalloc.h>
  14. #endif
  15. static char *pdb_filename;
  16. void pw_puredb_parse(const char * const file)
  17. {
  18. if (file == NULL || *file == 0) {
  19. die(421, LOG_ERR, MSG_NO_VIRTUAL_FILE);
  20. }
  21. if ((pdb_filename = strdup(file)) == NULL) {
  22. die_mem();
  23. }
  24. }
  25. void pw_puredb_exit(void)
  26. {
  27. free(pdb_filename);
  28. }
  29. /*
  30. * The difference between this strtok() and the libc's one is that
  31. * this one doesn't skip empty fields, and takes a char instead of a
  32. * string as a delimiter.
  33. * This strtok2() variant leaves zeroes.
  34. */
  35. static char *my_strtok2(char *str, const char delim)
  36. {
  37. static char *s;
  38. static char save;
  39. if (str != NULL) {
  40. if (*str == 0) {
  41. return NULL;
  42. }
  43. s = str;
  44. scan:
  45. while (*s != 0 && *s != delim) {
  46. s++;
  47. }
  48. save = *s;
  49. *s = 0;
  50. return str;
  51. }
  52. if (s == NULL || save == 0) {
  53. return NULL;
  54. }
  55. s++;
  56. str = s;
  57. goto scan;
  58. }
  59. /* Check whether an IP address matches a pattern. 1 = match 0 = nomatch */
  60. static int access_ip_match(const struct sockaddr_storage * const sa,
  61. char * pattern)
  62. {
  63. unsigned int ip0, ip1, ip2, ip3;
  64. unsigned int netbits;
  65. unsigned long ip;
  66. unsigned long mask;
  67. unsigned long saip;
  68. const unsigned char *saip_raw;
  69. char *comapoint;
  70. if (*pattern == 0) {
  71. return 1;
  72. }
  73. if (STORAGE_FAMILY(*sa) != AF_INET) {
  74. return 0; /* TODO: IPv6 */
  75. }
  76. do {
  77. if ((comapoint = strchr(pattern, ',')) != NULL) {
  78. *comapoint = 0;
  79. }
  80. if (sscanf(pattern, "%u.%u.%u.%u/%u", /* IPv4 */
  81. &ip0, &ip1, &ip2, &ip3, &netbits) == 5) {
  82. ipcheck:
  83. if (STORAGE_FAMILY(*sa) != AF_INET || netbits == 0U) {
  84. return -1;
  85. }
  86. ip =
  87. ((unsigned long) ip0 << 24) |
  88. ((unsigned long) ip1 << 16) |
  89. ((unsigned long) ip2 << 8) |
  90. (unsigned long) ip3;
  91. ipcheck_ipdone:
  92. mask = ~((0x80000000 >> (netbits - 1U)) - 1U);
  93. saip_raw = (const unsigned char *) &(STORAGE_SIN_ADDR_CONST(*sa));
  94. saip =
  95. ((unsigned long) saip_raw[0] << 24) |
  96. ((unsigned long) saip_raw[1] << 16) |
  97. ((unsigned long) saip_raw[2] << 8) |
  98. (unsigned long) saip_raw[3];
  99. if ((ip & mask) == (saip & mask)) {
  100. return 1;
  101. }
  102. } else if (sscanf(pattern, "%u.%u.%u.%u",
  103. &ip0, &ip1, &ip2, &ip3) == 4) {
  104. netbits = 32U;
  105. goto ipcheck;
  106. } else {
  107. struct addrinfo hints, *res;
  108. int on;
  109. memset(&hints, 0, sizeof hints);
  110. hints.ai_family = AF_INET;
  111. hints.ai_addr = NULL;
  112. if ((on = getaddrinfo(pattern, NULL, &hints, &res)) != 0) {
  113. logfile(LOG_WARNING, "puredb: [%s] => [%d]", pattern, on);
  114. } else if (res->ai_family != AF_INET) {
  115. freeaddrinfo(res);
  116. } else {
  117. const unsigned char * const ip_raw =
  118. (const unsigned char *) &
  119. (((const struct sockaddr_in *) (void *)
  120. (res->ai_addr))->sin_addr.s_addr);
  121. ip =
  122. ((unsigned long) ip_raw[0] << 24) |
  123. ((unsigned long) ip_raw[1] << 16) |
  124. ((unsigned long) ip_raw[2] << 8) |
  125. (unsigned long) ip_raw[3];
  126. netbits = 32U;
  127. freeaddrinfo(res);
  128. goto ipcheck_ipdone;
  129. }
  130. }
  131. if (comapoint == NULL) {
  132. break;
  133. }
  134. *comapoint = ',';
  135. pattern = comapoint + 1;
  136. } while (*pattern != 0);
  137. return 0;
  138. }
  139. /* IP check. 0 = ok, -1 = denied */
  140. static int access_ip_check(const struct sockaddr_storage * const sa,
  141. char * const allow, char * const deny)
  142. {
  143. if (sa == NULL) {
  144. return 0;
  145. }
  146. if (*allow == 0) {
  147. if (*deny == 0) {
  148. return 0;
  149. }
  150. if (access_ip_match(sa, deny) != 0) {
  151. return -1;
  152. }
  153. return 0;
  154. }
  155. if (*deny == 0) {
  156. if (access_ip_match(sa, allow) != 0) {
  157. return 0;
  158. }
  159. return -1;
  160. }
  161. if (access_ip_match(sa, allow) != 0 && access_ip_match(sa, deny) == 0) {
  162. return 0;
  163. }
  164. return -1;
  165. }
  166. static int time_restrictions_check(const char * const restrictions)
  167. {
  168. const struct tm *tm;
  169. time_t now_t;
  170. unsigned int time_begin, time_end;
  171. unsigned int now;
  172. if (*restrictions == 0) {
  173. return 0;
  174. }
  175. if (sscanf(restrictions, "%u-%u", &time_begin, &time_end) != 2 ||
  176. (now_t = time(NULL)) == (time_t) -1 ||
  177. (tm = localtime(&now_t)) == NULL) {
  178. return 0;
  179. }
  180. now = (unsigned int) tm->tm_hour * 100U + (unsigned int) tm->tm_min;
  181. if (time_begin <= time_end) {
  182. if (time_begin <= now && now <= time_end) {
  183. return 0;
  184. }
  185. return -1;
  186. }
  187. if (now >= time_begin || now <= time_end) {
  188. return 0;
  189. }
  190. return -1;
  191. }
  192. static int pw_puredb_parseline(char *line, const char * const pwd,
  193. const struct sockaddr_storage * const sa,
  194. const struct sockaddr_storage * const peer,
  195. AuthResult * const result)
  196. {
  197. char *allow_local_ip, *deny_local_ip;
  198. char *allow_remote_ip, *deny_remote_ip;
  199. const char *time_restrictions;
  200. if ((line = my_strtok2(line, *PW_LINE_SEP)) == NULL || *line == 0) { /* pwd */
  201. return -1;
  202. }
  203. {
  204. const char *crypted;
  205. int ret = -1;
  206. #ifdef crypto_pwhash_STRPREFIX
  207. if (crypto_pwhash_str_verify(line, pwd, strlen(pwd)) == 0) {
  208. /* pass */
  209. } else
  210. #endif
  211. #ifdef crypto_pwhash_scryptsalsa208sha256_STRPREFIX
  212. if (crypto_pwhash_scryptsalsa208sha256_str_verify
  213. (line, pwd, strlen(pwd)) == 0) {
  214. /* pass */
  215. } else
  216. #endif
  217. {
  218. ret = - ((crypted = (const char *) crypt(pwd, line)) == NULL ||
  219. pure_strcmp(line, crypted) != 0);
  220. if (ret != 0) {
  221. return -1;
  222. }
  223. }
  224. }
  225. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) { /* uid */
  226. return -1;
  227. }
  228. result->uid = (uid_t) strtoul(line, NULL, 10);
  229. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) { /* gid */
  230. return -1;
  231. }
  232. result->gid = (gid_t) strtoul(line, NULL, 10);
  233. #ifndef ACCEPT_ROOT_VIRTUAL_USERS
  234. if (result->uid <= (uid_t) 0 || result->gid <= (gid_t) 0) {
  235. return -1;
  236. }
  237. #endif
  238. if (my_strtok2(NULL, *PW_LINE_SEP) == NULL) { /* gecos */
  239. return -1;
  240. }
  241. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL || *line == 0) { /* home */
  242. return -1;
  243. }
  244. if ((result->dir = strdup(line)) == NULL || *result->dir != '/') {
  245. return -1;
  246. }
  247. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* bw_ul */
  248. return 0;
  249. }
  250. #ifdef THROTTLING
  251. if (*line != 0) {
  252. result->throttling_ul_changed = 1;
  253. result->throttling_bandwidth_ul = strtoul(line, NULL, 10);
  254. }
  255. #endif
  256. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* bw_dl */
  257. return 0;
  258. }
  259. #ifdef THROTTLING
  260. if (*line != 0) {
  261. result->throttling_dl_changed = 1;
  262. result->throttling_bandwidth_dl = strtoul(line, NULL, 10);
  263. }
  264. #endif
  265. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* ratio up */
  266. return 0;
  267. }
  268. #ifdef RATIOS
  269. if (*line != 0) {
  270. result->ratio_upload = (unsigned int) strtoul(line, NULL, 10);
  271. if (result->ratio_upload > 0U) {
  272. result->ratio_ul_changed = 1;
  273. }
  274. }
  275. #endif
  276. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* ratio down */
  277. return 0;
  278. }
  279. #ifdef RATIOS
  280. if (*line != 0) {
  281. result->ratio_download = (unsigned int) strtoul(line, NULL, 10);
  282. if (result->ratio_download > 0U) {
  283. result->ratio_dl_changed = 1;
  284. }
  285. }
  286. #endif
  287. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* max cnx */
  288. return 0;
  289. }
  290. #ifdef PER_USER_LIMITS
  291. if (*line != 0) {
  292. result->per_user_max = (unsigned int) strtoull(line, NULL, 10);
  293. }
  294. #endif
  295. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* files quota */
  296. return 0;
  297. }
  298. #ifdef QUOTAS
  299. if (*line != 0) {
  300. result->quota_files_changed = 1;
  301. result->user_quota_files = strtoull(line, NULL, 10);
  302. }
  303. #endif
  304. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* size quota */
  305. return 0;
  306. }
  307. #ifdef QUOTAS
  308. if (*line != 0) {
  309. result->quota_size_changed = 1;
  310. result->user_quota_size = strtoull(line, NULL, 10);
  311. }
  312. #endif
  313. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* allowed local ip */
  314. return 0;
  315. }
  316. allow_local_ip = line;
  317. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* denied local ip */
  318. return 0;
  319. }
  320. deny_local_ip = line;
  321. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* allowed remote ip */
  322. return 0;
  323. }
  324. allow_remote_ip = line;
  325. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* denied remote ip */
  326. return 0;
  327. }
  328. deny_remote_ip = line;
  329. if (access_ip_check(sa, allow_local_ip, deny_local_ip) != 0 ||
  330. access_ip_check(peer, allow_remote_ip, deny_remote_ip) != 0) {
  331. return -1;
  332. }
  333. if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* time restrictions */
  334. return 0;
  335. }
  336. time_restrictions = line;
  337. if (time_restrictions_check(time_restrictions) != 0) {
  338. return -1;
  339. }
  340. return 0;
  341. }
  342. void pw_puredb_check(AuthResult * const result,
  343. const char *account, const char *password,
  344. const struct sockaddr_storage * const sa,
  345. const struct sockaddr_storage * const peer)
  346. {
  347. char *line = NULL;
  348. PureDB db;
  349. off_t retpos;
  350. size_t retlen;
  351. result->auth_ok = 0;
  352. (void) sa;
  353. (void) peer;
  354. if (puredb_open(&db, pdb_filename) != 0) {
  355. die(421, LOG_ERR, MSG_PDB_BROKEN);
  356. }
  357. if (puredb_find_s(&db, account, &retpos, &retlen) != 0) {
  358. goto bye;
  359. }
  360. if ((line = puredb_read(&db, retpos, retlen)) == NULL) {
  361. goto bye;
  362. }
  363. result->auth_ok--;
  364. if (pw_puredb_parseline(line, password, sa, peer, result) != 0) {
  365. goto bye;
  366. }
  367. result->slow_tilde_expansion = 1;
  368. result->auth_ok = -result->auth_ok;
  369. bye:
  370. puredb_read_free(line);
  371. puredb_close(&db);
  372. }
  373. #endif