log_mysql.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. #include <config.h>
  2. #ifdef WITH_MYSQL
  3. # include "ftpd.h"
  4. # include "parser.h"
  5. # include "log_mysql_p.h"
  6. # include "log_mysql.h"
  7. # include "messages.h"
  8. # include "crypto.h"
  9. # include "crypto-sha1.h"
  10. # include "alt_arc4random.h"
  11. # include "utils.h"
  12. #ifdef HAVE_LIBSODIUM
  13. # include <sodium.h>
  14. #endif
  15. #ifdef WITH_DMALLOC
  16. # include <dmalloc.h>
  17. # endif
  18. static int pw_mysql_validate_name(const char *name)
  19. {
  20. if (name == NULL || *name == 0) {
  21. return -1;
  22. }
  23. do {
  24. if ((*name >= 'a' && *name <= 'z') ||
  25. (*name >= 'A' && *name <= 'Z') ||
  26. (*name >= '0' && *name <= '9') ||
  27. *name == ' ' || *name == '-' ||
  28. *name == '_' || *name == '\'' || *name == '.' ||
  29. *name == ':' || *name == '@' || *name == '+') {
  30. /* God bless the Ruby 'unless' keyword */
  31. } else {
  32. return -1;
  33. }
  34. name++;
  35. } while (*name != 0);
  36. return 0;
  37. }
  38. static char *pw_mysql_escape_string(MYSQL * const id_sql_server,
  39. const char *from)
  40. {
  41. size_t from_len;
  42. size_t to_len;
  43. char *to;
  44. unsigned long escaped_len;
  45. unsigned int t;
  46. unsigned char t1, t2, t3, t4;
  47. if (from == NULL) {
  48. return NULL;
  49. }
  50. from_len = strlen(from);
  51. to_len = from_len * 2U + (size_t) 1U;
  52. if ((to = malloc(to_len + (size_t) 4U)) == NULL) {
  53. return NULL;
  54. }
  55. t = zrand();
  56. t1 = t & 0xff;
  57. t2 = (t >> 8) & 0xff;
  58. t = zrand();
  59. t3 = t & 0xff;
  60. t4 = (t >> 8) & 0xff;
  61. to[to_len] = (char) t1;
  62. to[to_len + 1] = (char) t2;
  63. to[to_len + 2] = (char) t3;
  64. to[to_len + 3] = (char) t4;
  65. /*
  66. * I really hate giving a buffer without any size to a 3rd party function.
  67. * The "to" buffer is allocated on the heap, not on the stack, if
  68. * mysql_real_escape_string() is buggy, the stack shouldn't be already
  69. * smashed at this point, but data from other malloc can be corrupted and
  70. * bad things can happen. It make sense to wipe this area as soon as
  71. * possible instead of doing anything with the heap. We'll end up with
  72. * a segmentation violation, but without any possible exploit.
  73. */
  74. escaped_len = mysql_real_escape_string(id_sql_server, to, from, from_len);
  75. if (escaped_len >= to_len ||
  76. (unsigned char) to[to_len] != t1 ||
  77. (unsigned char) to[to_len + 1] != t2 ||
  78. (unsigned char) to[to_len + 2] != t3 ||
  79. (unsigned char) to[to_len + 3] != t4) {
  80. for (;;) {
  81. *to++ = 0;
  82. }
  83. }
  84. to[escaped_len] = 0;
  85. return to;
  86. }
  87. /*
  88. * Substitute digraphs for SQL requests.
  89. * orig_str is the original string, full of \L, \I, \P, \R and \D.
  90. * query is a buffer to handle the result.
  91. * query_len is the size of the buffer.
  92. * returns the buffer @ if successful, NULL otherwise. -frank.
  93. */
  94. static char *sqlsubst(const char *orig_str, char * const query,
  95. size_t query_len, const char * const user,
  96. const char * const ip, const char * const port,
  97. const char * const peer_ip,
  98. const char * const decimal_ip)
  99. {
  100. char *query_pnt = query;
  101. const char *orig_str_scan = orig_str;
  102. const size_t user_len = (user == NULL ? (size_t) 0U : strlen(user));
  103. const size_t ip_len = (ip == NULL ? (size_t) 0U : strlen(ip));
  104. const size_t port_len = (port == NULL ? (size_t) 0U : strlen(port));
  105. const size_t peer_ip_len = (peer_ip == NULL ? (size_t) 0U : strlen(peer_ip));
  106. const size_t decimal_ip_len = (decimal_ip == NULL ? (size_t) 0U : strlen(decimal_ip));
  107. while (*orig_str_scan != 0) {
  108. if (*orig_str_scan == '\\' && orig_str_scan[1] != 0) {
  109. orig_str_scan++;
  110. switch(tolower((unsigned char) *orig_str_scan)) {
  111. case 'l' :
  112. if (user_len >= query_len) {
  113. return NULL;
  114. }
  115. if (user_len <= (size_t) 0U) {
  116. goto nextone;
  117. }
  118. memcpy(query_pnt, user, user_len);
  119. query_pnt += user_len;
  120. query_len -= user_len;
  121. goto nextone;
  122. case 'i' :
  123. if (ip_len >= query_len) {
  124. return NULL;
  125. }
  126. if (ip_len <= (size_t) 0U) {
  127. goto nextone;
  128. }
  129. memcpy(query_pnt, ip, ip_len);
  130. query_pnt += ip_len;
  131. query_len -= ip_len;
  132. goto nextone;
  133. case 'p' :
  134. if (port_len >= query_len) {
  135. return NULL;
  136. }
  137. if (port_len <= (size_t) 0U) {
  138. goto nextone;
  139. }
  140. memcpy(query_pnt, port, port_len);
  141. query_pnt += port_len;
  142. query_len -= port_len;
  143. goto nextone;
  144. case 'r' :
  145. if (peer_ip_len >= query_len) {
  146. return NULL;
  147. }
  148. if (peer_ip_len <= (size_t) 0U) {
  149. goto nextone;
  150. }
  151. memcpy(query_pnt, peer_ip, peer_ip_len);
  152. query_pnt += peer_ip_len;
  153. query_len -= peer_ip_len;
  154. goto nextone;
  155. case 'd' :
  156. if (decimal_ip_len >= query_len) {
  157. return NULL;
  158. }
  159. if (decimal_ip_len <= (size_t) 0U) {
  160. goto nextone;
  161. }
  162. memcpy(query_pnt, decimal_ip, decimal_ip_len);
  163. query_pnt += decimal_ip_len;
  164. query_len -= decimal_ip_len;
  165. goto nextone;
  166. default :
  167. if (--query_len <= (size_t) 0U) {
  168. return NULL;
  169. }
  170. *query_pnt++ = '\\';
  171. }
  172. }
  173. if (ISCTRLCODE(*orig_str_scan)) {
  174. goto nextone;
  175. }
  176. if (--query_len <= (size_t) 0U) {
  177. return NULL;
  178. }
  179. *query_pnt++ = *orig_str_scan;
  180. nextone:
  181. orig_str_scan++;
  182. }
  183. *query_pnt = 0;
  184. return query;
  185. }
  186. static int pw_mysql_connect(MYSQL ** const id_sql_server)
  187. {
  188. *id_sql_server = NULL;
  189. if ((*id_sql_server = mysql_init(NULL)) == NULL) {
  190. down:
  191. if (server_down == 0) {
  192. const char *mysql_err = "mysql_init()";
  193. if (*id_sql_server != NULL) {
  194. mysql_err = mysql_error(*id_sql_server);
  195. }
  196. server_down++;
  197. logfile(LOG_ERR, MSG_SQL_DOWN " [%s]", mysql_err);
  198. }
  199. return -1;
  200. }
  201. if (mysql_real_connect(*id_sql_server, server, user, pw,
  202. db, port, socket_path,
  203. #ifdef CLIENT_MULTI_STATEMENTS
  204. CLIENT_MULTI_STATEMENTS
  205. #else
  206. 0
  207. #endif
  208. ) == NULL) {
  209. goto down;
  210. }
  211. if (mysql_ping(*id_sql_server) != 0) {
  212. goto down;
  213. }
  214. server_down = 0;
  215. return 0;
  216. }
  217. static int pw_mysql_simplequery(MYSQL * const id_sql_server,
  218. const char * const query)
  219. {
  220. if (mysql_real_query(id_sql_server, query, strlen(query)) != 0) {
  221. return -1;
  222. }
  223. return 0;
  224. }
  225. static char *pw_mysql_getquery(MYSQL * const id_sql_server,
  226. const char * const orig_query,
  227. const char * const account,
  228. const char * const ip,
  229. const char * const port,
  230. const char * const peer_ip,
  231. const char * const decimal_ip)
  232. {
  233. char query[MYSQL_MAX_REQUEST_LENGTH];
  234. MYSQL_RES *qresult = NULL;
  235. unsigned long *lengths;
  236. char *answer = NULL;
  237. MYSQL_ROW row;
  238. size_t length;
  239. if (orig_query == NULL || *orig_query == 0) {
  240. goto bye;
  241. }
  242. if (sqlsubst(orig_query, query, sizeof query,
  243. account, ip, port, peer_ip, decimal_ip) == NULL) {
  244. goto bye;
  245. }
  246. if (mysql_real_query(id_sql_server, query, strlen(query)) != 0) {
  247. logfile(LOG_WARNING, MSG_SQL_WRONG_PARMS " : [%s]", query);
  248. goto bye;
  249. }
  250. if (mysql_field_count(id_sql_server) != 1) {
  251. goto bye;
  252. }
  253. if ((qresult = mysql_store_result(id_sql_server)) == NULL) {
  254. goto bye;
  255. }
  256. if (mysql_num_rows(qresult) != 1) {
  257. goto bye;
  258. }
  259. if ((row = mysql_fetch_row(qresult)) == NULL || row[0] == NULL) {
  260. goto bye;
  261. }
  262. lengths = mysql_fetch_lengths(qresult);
  263. if (lengths == NULL ||
  264. (length = (size_t) lengths[0] + (size_t) 1U) <= (size_t) 1U) {
  265. goto bye;
  266. }
  267. if ((answer = malloc(length)) == NULL) {
  268. goto bye;
  269. }
  270. strncpy(answer, row[0], length - (size_t) 1U);
  271. answer[length - (size_t) 1U] = 0;
  272. bye:
  273. if (qresult != NULL) {
  274. mysql_free_result(qresult);
  275. #ifdef CLIENT_MULTI_STATEMENTS
  276. while (mysql_next_result(id_sql_server) == 0) {
  277. qresult = mysql_store_result(id_sql_server);
  278. mysql_free_result(qresult);
  279. }
  280. #endif
  281. }
  282. return answer;
  283. }
  284. void pw_mysql_check(AuthResult * const result,
  285. const char *account, const char *password,
  286. const struct sockaddr_storage * const sa,
  287. const struct sockaddr_storage * const peer)
  288. {
  289. MYSQL *id_sql_server = NULL;
  290. const char *spwd = NULL; /* stored password */
  291. const char *uid = sql_default_uid; /* stored system login/uid */
  292. const char *gid = sql_default_gid; /* stored system group/gid */
  293. const char *dir = NULL; /* stored home directory */
  294. #ifdef QUOTAS
  295. const char *sqta_fs = NULL; /* stored quota files */
  296. const char *sqta_sz = NULL; /* stored quota size */
  297. #endif
  298. #ifdef RATIOS
  299. const char *ratio_ul = NULL; /* stored ratio UL */
  300. const char *ratio_dl = NULL; /* stored ratio DL */
  301. #endif
  302. #ifdef THROTTLING
  303. const char *bandwidth_ul = NULL; /* stored bandwidth UL */
  304. const char *bandwidth_dl = NULL; /* stored bandwidth DL */
  305. #endif
  306. char *escaped_account = NULL;
  307. char *escaped_ip = NULL;
  308. char *escaped_port = NULL;
  309. char *escaped_peer_ip = NULL;
  310. char *escaped_decimal_ip = NULL;
  311. int committed = 1;
  312. int crypto_argon2 = 0, crypto_scrypt = 0, crypto_crypt = 0,
  313. crypto_mysql = 0, crypto_md5 = 0, crypto_sha1 = 0, crypto_plain = 0;
  314. unsigned long decimal_ip_num = 0UL;
  315. char decimal_ip[42];
  316. char hbuf[NI_MAXHOST];
  317. char pbuf[NI_MAXSERV];
  318. char phbuf[NI_MAXHOST];
  319. result->auth_ok = 0;
  320. if (pw_mysql_validate_name(account) != 0) {
  321. goto bye;
  322. }
  323. if (getnameinfo((const struct sockaddr *) sa, STORAGE_LEN(*sa),
  324. hbuf, sizeof hbuf, pbuf, sizeof pbuf,
  325. NI_NUMERICHOST | NI_NUMERICSERV) != 0 ||
  326. getnameinfo((const struct sockaddr *) peer, STORAGE_LEN(*peer),
  327. phbuf, sizeof phbuf, NULL, (size_t) 0U,
  328. NI_NUMERICHOST) != 0) {
  329. goto bye;
  330. }
  331. *decimal_ip = 0;
  332. if (STORAGE_FAMILY(*peer) == AF_INET) {
  333. const unsigned char *decimal_ip_raw =
  334. (const unsigned char *) &(STORAGE_SIN_ADDR(*peer));
  335. decimal_ip_num = ((unsigned long) decimal_ip_raw[0] << 24) |
  336. ((unsigned long) decimal_ip_raw[1] << 16) |
  337. (decimal_ip_raw[2] << 8) | decimal_ip_raw[3];
  338. if (SNCHECK(snprintf(decimal_ip, sizeof decimal_ip,
  339. "%lu", decimal_ip_num), sizeof decimal_ip)) {
  340. goto bye;
  341. }
  342. }
  343. if (pw_mysql_connect(&id_sql_server) != 0) {
  344. goto bye;
  345. }
  346. if ((escaped_account =
  347. pw_mysql_escape_string(id_sql_server, account)) == NULL) {
  348. goto bye;
  349. }
  350. if ((escaped_ip =
  351. pw_mysql_escape_string(id_sql_server, hbuf)) == NULL) {
  352. goto bye;
  353. }
  354. if ((escaped_port =
  355. pw_mysql_escape_string(id_sql_server, pbuf)) == NULL) {
  356. goto bye;
  357. }
  358. if ((escaped_peer_ip =
  359. pw_mysql_escape_string(id_sql_server, phbuf)) == NULL) {
  360. goto bye;
  361. }
  362. if ((escaped_decimal_ip =
  363. pw_mysql_escape_string(id_sql_server, decimal_ip)) == NULL) {
  364. goto bye;
  365. }
  366. if (transactions != NULL && strcasecmp(transactions, "on") == 0) {
  367. if (pw_mysql_simplequery(id_sql_server, MYSQL_TRANSACTION_START) == 0) {
  368. committed = 0;
  369. }
  370. }
  371. if ((spwd = pw_mysql_getquery(id_sql_server, sqlreq_getpw,
  372. escaped_account, escaped_ip,
  373. escaped_port, escaped_peer_ip,
  374. escaped_decimal_ip)) == NULL) {
  375. goto bye;
  376. }
  377. if (uid == NULL) {
  378. uid = pw_mysql_getquery(id_sql_server, sqlreq_getuid,
  379. escaped_account, escaped_ip,
  380. escaped_port, escaped_peer_ip,
  381. escaped_decimal_ip);
  382. }
  383. if (uid == NULL) {
  384. goto bye;
  385. }
  386. if (gid == NULL) {
  387. gid = pw_mysql_getquery(id_sql_server, sqlreq_getgid,
  388. escaped_account, escaped_ip,
  389. escaped_port, escaped_peer_ip,
  390. escaped_decimal_ip);
  391. }
  392. if (gid == NULL) {
  393. goto bye;
  394. }
  395. if ((dir = pw_mysql_getquery(id_sql_server, sqlreq_getdir,
  396. escaped_account, escaped_ip,
  397. escaped_port, escaped_peer_ip,
  398. escaped_decimal_ip)) == NULL) {
  399. goto bye;
  400. }
  401. result->auth_ok--; /* -1 */
  402. if (strcasecmp(crypto, PASSWD_SQL_ANY) == 0) {
  403. crypto_argon2++;
  404. crypto_scrypt++;
  405. crypto_crypt++;
  406. crypto_mysql++;
  407. crypto_md5++;
  408. crypto_sha1++;
  409. } else if (strcasecmp(crypto, PASSWD_SQL_ARGON2) == 0) {
  410. crypto_argon2++;
  411. } else if (strcasecmp(crypto, PASSWD_SQL_SCRYPT) == 0) {
  412. crypto_scrypt++;
  413. } else if (strcasecmp(crypto, PASSWD_SQL_CRYPT) == 0) {
  414. crypto_crypt++;
  415. } else if (strcasecmp(crypto, PASSWD_SQL_MYSQL) == 0) {
  416. crypto_mysql++;
  417. } else if (strcasecmp(crypto, PASSWD_SQL_MD5) == 0) {
  418. crypto_md5++;
  419. } else if (strcasecmp(crypto, PASSWD_SQL_SHA1) == 0) {
  420. crypto_sha1++;
  421. } else { /* default to plaintext */
  422. crypto_plain++;
  423. }
  424. #ifdef crypto_pwhash_STRPREFIX
  425. if (crypto_argon2 != 0) {
  426. if (crypto_pwhash_str_verify(spwd, password, strlen(password)) == 0) {
  427. goto auth_ok;
  428. }
  429. }
  430. #endif
  431. #ifdef crypto_pwhash_scryptsalsa208sha256_STRPREFIX
  432. if (crypto_scrypt != 0) {
  433. if (crypto_pwhash_scryptsalsa208sha256_str_verify
  434. (spwd, password, strlen(password)) == 0) {
  435. goto auth_ok;
  436. }
  437. }
  438. #endif
  439. if (crypto_crypt != 0) {
  440. const char *crypted;
  441. if ((crypted = (const char *) crypt(password, spwd)) != NULL &&
  442. pure_strcmp(crypted, spwd) == 0) {
  443. goto auth_ok;
  444. }
  445. }
  446. if (crypto_mysql != 0) {
  447. char scrambled_password[42]; /* 2 * 20 (sha1 hash size) + 2 */
  448. SHA1_CTX ctx;
  449. unsigned char h0[20], h1[20];
  450. char *p;
  451. SHA1Init(&ctx);
  452. SHA1Update(&ctx, password, strlen(password));
  453. SHA1Final(h0, &ctx);
  454. SHA1Init(&ctx);
  455. SHA1Update(&ctx, h0, sizeof h0);
  456. pure_memzero(h0, sizeof h0);
  457. SHA1Final(h1, &ctx);
  458. *scrambled_password = '*';
  459. hexify(scrambled_password + 1U, h1,
  460. (sizeof scrambled_password) - 1U, sizeof h1);
  461. *(p = scrambled_password) = '*';
  462. while (*p++ != 0) {
  463. *p = (char) toupper((unsigned char) *p);
  464. }
  465. if (pure_strcmp(scrambled_password, spwd) == 0) {
  466. goto auth_ok;
  467. }
  468. }
  469. if (crypto_md5 != 0) {
  470. const char *crypted;
  471. if ((crypted = (const char *) crypto_hash_md5(password, 1)) != NULL &&
  472. pure_strcmp(crypted, spwd) == 0) {
  473. goto auth_ok;
  474. }
  475. }
  476. if (crypto_sha1 != 0) {
  477. const char *crypted;
  478. if ((crypted = (const char *) crypto_hash_sha1(password, 1)) != NULL &&
  479. pure_strcmp(crypted, spwd) == 0) {
  480. goto auth_ok;
  481. }
  482. }
  483. if (crypto_plain != 0) {
  484. if (*password != 0 && /* refuse null cleartext passwords */
  485. pure_strcmp(password, spwd) == 0) {
  486. goto auth_ok;
  487. }
  488. }
  489. goto bye;
  490. auth_ok:
  491. /*
  492. * do *NOT* accept root uid/gid - if the database is compromized, the FTP
  493. * server could also be rooted.
  494. */
  495. result->uid = (uid_t) strtoul(uid, NULL, 10);
  496. if (result->uid <= (uid_t) 0) {
  497. struct passwd *pw;
  498. if ((pw = getpwnam(uid)) == NULL || pw->pw_uid <= (uid_t) 0) {
  499. goto bye;
  500. }
  501. result->uid = pw->pw_uid;
  502. }
  503. result->gid = (gid_t) strtoul(gid, NULL, 10);
  504. if (result->gid <= (gid_t) 0) {
  505. struct group *gr;
  506. if ((gr = getgrnam(gid)) == NULL || (gid_t) gr->gr_gid <= (gid_t) 0) {
  507. goto bye;
  508. }
  509. result->gid = gr->gr_gid;
  510. }
  511. result->dir = dir;
  512. dir = NULL;
  513. #ifdef QUOTAS
  514. if ((sqta_fs = pw_mysql_getquery(id_sql_server, sqlreq_getqta_fs,
  515. escaped_account, escaped_ip,
  516. escaped_port, escaped_peer_ip,
  517. escaped_decimal_ip)) != NULL) {
  518. const unsigned long long q = strtoull(sqta_fs, NULL, 10);
  519. if (q > 0ULL) {
  520. result->user_quota_files = q;
  521. result->quota_files_changed = 1;
  522. }
  523. }
  524. if ((sqta_sz = pw_mysql_getquery(id_sql_server, sqlreq_getqta_sz,
  525. escaped_account, escaped_ip,
  526. escaped_port, escaped_peer_ip,
  527. escaped_decimal_ip)) != NULL) {
  528. const unsigned long long q = strtoull(sqta_sz, NULL, 10);
  529. if (q > 0ULL) {
  530. result->user_quota_size = q * (1024UL * 1024UL);
  531. result->quota_size_changed = 1;
  532. }
  533. }
  534. #endif
  535. #ifdef RATIOS
  536. if ((ratio_ul = pw_mysql_getquery(id_sql_server, sqlreq_getratio_ul,
  537. escaped_account, escaped_ip,
  538. escaped_port, escaped_peer_ip,
  539. escaped_decimal_ip)) != NULL) {
  540. const unsigned int q = (unsigned int) strtoul(ratio_ul, NULL, 10);
  541. if (q > 0U) {
  542. result->ratio_upload = q;
  543. result->ratio_ul_changed = 1;
  544. }
  545. }
  546. if ((ratio_dl = pw_mysql_getquery(id_sql_server, sqlreq_getratio_dl,
  547. escaped_account, escaped_ip,
  548. escaped_port, escaped_peer_ip,
  549. escaped_decimal_ip)) != NULL) {
  550. const unsigned int q = (unsigned int) strtoul(ratio_dl, NULL, 10);
  551. if (q > 0U) {
  552. result->ratio_download = q;
  553. result->ratio_dl_changed = 1;
  554. }
  555. }
  556. #endif
  557. #ifdef THROTTLING
  558. if ((bandwidth_ul = pw_mysql_getquery(id_sql_server, sqlreq_getbandwidth_ul,
  559. escaped_account, escaped_ip,
  560. escaped_port, escaped_peer_ip,
  561. escaped_decimal_ip)) != NULL) {
  562. const unsigned long q = (unsigned long) strtoul(bandwidth_ul, NULL, 10);
  563. if (q > 0UL) {
  564. result->throttling_bandwidth_ul = q * 1024UL;
  565. result->throttling_ul_changed = 1;
  566. }
  567. }
  568. if ((bandwidth_dl = pw_mysql_getquery(id_sql_server, sqlreq_getbandwidth_dl,
  569. escaped_account, escaped_ip,
  570. escaped_port, escaped_peer_ip,
  571. escaped_decimal_ip)) != NULL) {
  572. const unsigned long q = (unsigned long) strtoul(bandwidth_dl, NULL, 10);
  573. if (q > 0UL) {
  574. result->throttling_bandwidth_dl = q * 1024UL;
  575. result->throttling_dl_changed = 1;
  576. }
  577. }
  578. #endif
  579. result->slow_tilde_expansion = !tildexp;
  580. result->auth_ok = -result->auth_ok;
  581. bye:
  582. if (committed == 0) {
  583. (void) pw_mysql_simplequery(id_sql_server, MYSQL_TRANSACTION_END);
  584. }
  585. if (id_sql_server != NULL) {
  586. mysql_close(id_sql_server);
  587. }
  588. free((void *) spwd);
  589. if (uid != sql_default_uid) {
  590. free((void *) uid);
  591. }
  592. if (gid != sql_default_gid) {
  593. free((void *) gid);
  594. }
  595. free((void *) dir);
  596. #ifdef QUOTAS
  597. free((void *) sqta_fs);
  598. free((void *) sqta_sz);
  599. #endif
  600. #ifdef RATIOS
  601. free((void *) ratio_ul);
  602. free((void *) ratio_dl);
  603. #endif
  604. #ifdef THROTTLING
  605. free((void *) bandwidth_ul);
  606. free((void *) bandwidth_dl);
  607. #endif
  608. free((void *) escaped_account);
  609. free((void *) escaped_ip);
  610. free((void *) escaped_port);
  611. free((void *) escaped_peer_ip);
  612. free((void *) escaped_decimal_ip);
  613. }
  614. void pw_mysql_parse(const char * const file)
  615. {
  616. if (generic_parser(file, mysql_config_keywords) != 0) {
  617. die(421, LOG_ERR, MSG_CONF_ERR ": " MSG_ILLEGAL_CONFIG_FILE_SQL ": %s",
  618. file);
  619. }
  620. if (server == NULL && socket_path == NULL) {
  621. die(421, LOG_ERR, MSG_SQL_MISSING_SERVER);
  622. }
  623. if (server != NULL && socket_path != NULL) {
  624. free(socket_path);
  625. socket_path = NULL;
  626. }
  627. if (tildexp_s != NULL) {
  628. if ((tildexp = atoi(tildexp_s)) < 0) {
  629. tildexp = 0;
  630. }
  631. free(tildexp_s);
  632. tildexp_s = NULL;
  633. }
  634. if (port_s != NULL) {
  635. port = atoi(port_s);
  636. if (port <= 0 || port > 65535) {
  637. port = MYSQL_DEFAULT_PORT;
  638. }
  639. free(port_s);
  640. port_s = NULL;
  641. }
  642. }
  643. #define ZFREE(X) do { free(X); (X) = NULL; } while (0)
  644. void pw_mysql_exit(void)
  645. {
  646. ZFREE(server);
  647. ZFREE(port_s);
  648. port = -1;
  649. ZFREE(socket_path);
  650. ZFREE(user);
  651. ZFREE(pw);
  652. ZFREE(db);
  653. ZFREE(crypto);
  654. ZFREE(transactions);
  655. ZFREE(sqlreq_getpw);
  656. ZFREE(sqlreq_getuid);
  657. ZFREE(sql_default_uid);
  658. ZFREE(sqlreq_getgid);
  659. ZFREE(sql_default_gid);
  660. ZFREE(sqlreq_getdir);
  661. #ifdef QUOTAS
  662. ZFREE(sqlreq_getqta_fs);
  663. ZFREE(sqlreq_getqta_sz);
  664. #endif
  665. #ifdef RATIOS
  666. ZFREE(sqlreq_getratio_ul);
  667. ZFREE(sqlreq_getratio_dl);
  668. #endif
  669. #ifdef THROTTLING
  670. ZFREE(sqlreq_getbandwidth_ul);
  671. ZFREE(sqlreq_getbandwidth_dl);
  672. #endif
  673. }
  674. #else
  675. extern signed char v6ready;
  676. #endif