dbd_pgsql.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. /*
  2. * Copyright (C) 2011, 2012, 2013 Citrix Systems
  3. * Copyright (C) 2014 Vivocha S.p.A.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the project nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #include "../mainrelay.h"
  32. #include "dbd_pgsql.h"
  33. #if !defined(TURN_NO_PQ)
  34. #include <libpq-fe.h>
  35. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  36. static int donot_print_connection_success = 0;
  37. static PGconn *get_pqdb_connection(void) {
  38. persistent_users_db_t *pud = get_persistent_users_db();
  39. PGconn *pqdbconnection = (PGconn*)(pud->connection);
  40. if(pqdbconnection) {
  41. ConnStatusType status = PQstatus(pqdbconnection);
  42. if(status != CONNECTION_OK) {
  43. PQfinish(pqdbconnection);
  44. pqdbconnection = NULL;
  45. }
  46. }
  47. if(!pqdbconnection) {
  48. char *errmsg=NULL;
  49. PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg);
  50. if(!co) {
  51. if(errmsg) {
  52. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
  53. turn_free(errmsg,strlen(errmsg)+1);
  54. } else {
  55. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb);
  56. }
  57. } else {
  58. PQconninfoFree(co);
  59. if(errmsg)
  60. turn_free(errmsg,strlen(errmsg)+1);
  61. pqdbconnection = PQconnectdb(pud->userdb);
  62. if(!pqdbconnection) {
  63. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
  64. } else {
  65. ConnStatusType status = PQstatus(pqdbconnection);
  66. if(status != CONNECTION_OK) {
  67. PQfinish(pqdbconnection);
  68. pqdbconnection = NULL;
  69. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
  70. } else if(!donot_print_connection_success){
  71. TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb);
  72. }
  73. }
  74. }
  75. pud->connection = pqdbconnection;
  76. }
  77. return pqdbconnection;
  78. }
  79. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  80. static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
  81. int ret = -1;
  82. PGconn * pqc = get_pqdb_connection();
  83. if(pqc) {
  84. char statement[TURN_LONG_STRING_SIZE];
  85. snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
  86. PGresult *res = PQexec(pqc, statement);
  87. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  88. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  89. } else {
  90. int i = 0;
  91. for(i=0;i<PQntuples(res);i++) {
  92. char *kval = PQgetvalue(res,i,0);
  93. if(kval) {
  94. add_to_secrets_list(sl,kval);
  95. }
  96. }
  97. ret = 0;
  98. }
  99. if(res) {
  100. PQclear(res);
  101. }
  102. }
  103. return ret;
  104. }
  105. static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
  106. int ret = -1;
  107. PGconn * pqc = get_pqdb_connection();
  108. if(pqc) {
  109. char statement[TURN_LONG_STRING_SIZE];
  110. snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm);
  111. PGresult *res = PQexec(pqc, statement);
  112. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  113. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  114. } else {
  115. char *kval = PQgetvalue(res,0,0);
  116. int len = PQgetlength(res,0,0);
  117. if(kval) {
  118. size_t sz = get_hmackey_size(turn_params.shatype);
  119. if(((size_t)len<sz*2)||(strlen(kval)<sz*2)) {
  120. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: %s, user %s\n",kval,usname);
  121. } else if(convert_string_key_to_binary(kval, key, sz)<0) {
  122. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",kval,usname);
  123. } else {
  124. ret = 0;
  125. }
  126. } else {
  127. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong hmackey data for user %s: NULL\n",usname);
  128. }
  129. }
  130. if(res)
  131. PQclear(res);
  132. }
  133. return ret;
  134. }
  135. static int pgsql_get_user_pwd(u08bits *usname, st_password_t pwd) {
  136. int ret = -1;
  137. char statement[TURN_LONG_STRING_SIZE];
  138. snprintf(statement,sizeof(statement),"select password from turnusers_st where name='%s'",usname);
  139. PGconn * pqc = get_pqdb_connection();
  140. if(pqc) {
  141. PGresult *res = PQexec(pqc, statement);
  142. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  143. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  144. } else {
  145. char *kval = PQgetvalue(res,0,0);
  146. if(kval) {
  147. strncpy((char*)pwd,kval,sizeof(st_password_t));
  148. ret = 0;
  149. } else {
  150. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong password data for user %s: NULL\n",usname);
  151. }
  152. }
  153. if(res) {
  154. PQclear(res);
  155. }
  156. }
  157. return ret;
  158. }
  159. static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
  160. int ret = -1;
  161. char statement[TURN_LONG_STRING_SIZE];
  162. snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key from oauth_key where kid='%s'",(const char*)kid);
  163. PGconn * pqc = get_pqdb_connection();
  164. if(pqc) {
  165. PGresult *res = PQexec(pqc, statement);
  166. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  167. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  168. } else {
  169. STRCPY((char*)key->ikm_key,PQgetvalue(res,0,0));
  170. key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10);
  171. key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10);
  172. STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,0,3));
  173. STRCPY((char*)key->as_rs_alg,PQgetvalue(res,0,4));
  174. STRCPY((char*)key->as_rs_key,PQgetvalue(res,0,5));
  175. STRCPY((char*)key->auth_alg,PQgetvalue(res,0,6));
  176. STRCPY((char*)key->auth_key,PQgetvalue(res,0,7));
  177. STRCPY((char*)key->kid,kid);
  178. ret = 0;
  179. }
  180. if(res) {
  181. PQclear(res);
  182. }
  183. }
  184. return ret;
  185. }
  186. static int pgsql_list_oauth_keys(void) {
  187. oauth_key_data_raw key_;
  188. oauth_key_data_raw *key=&key_;
  189. int ret = -1;
  190. char statement[TURN_LONG_STRING_SIZE];
  191. snprintf(statement,sizeof(statement),"select ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key,kid from oauth_key order by kid");
  192. PGconn * pqc = get_pqdb_connection();
  193. if(pqc) {
  194. PGresult *res = PQexec(pqc, statement);
  195. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  196. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  197. } else {
  198. int i = 0;
  199. for(i=0;i<PQntuples(res);i++) {
  200. STRCPY((char*)key->ikm_key,PQgetvalue(res,i,0));
  201. key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10);
  202. key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10);
  203. STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,i,3));
  204. STRCPY((char*)key->as_rs_alg,PQgetvalue(res,i,4));
  205. STRCPY((char*)key->as_rs_key,PQgetvalue(res,i,5));
  206. STRCPY((char*)key->auth_alg,PQgetvalue(res,i,6));
  207. STRCPY((char*)key->auth_key,PQgetvalue(res,i,7));
  208. STRCPY((char*)key->kid,PQgetvalue(res,i,8));
  209. printf(" kid=%s, ikm_key=%s, timestamp=%llu, lifetime=%lu, hkdf_hash_func=%s, as_rs_alg=%s, as_rs_key=%s, auth_alg=%s, auth_key=%s\n",
  210. key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
  211. key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
  212. ret = 0;
  213. }
  214. }
  215. if(res) {
  216. PQclear(res);
  217. }
  218. }
  219. return ret;
  220. }
  221. static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
  222. int ret = -1;
  223. char statement[TURN_LONG_STRING_SIZE];
  224. PGconn *pqc = get_pqdb_connection();
  225. if(pqc) {
  226. snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key);
  227. PGresult *res = PQexec(pqc, statement);
  228. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  229. if(res) {
  230. PQclear(res);
  231. }
  232. snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
  233. res = PQexec(pqc, statement);
  234. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  235. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
  236. } else {
  237. ret = 0;
  238. }
  239. }
  240. if(res) {
  241. PQclear(res);
  242. }
  243. }
  244. return ret;
  245. }
  246. static int pgsql_set_oauth_key(oauth_key_data_raw *key) {
  247. int ret = -1;
  248. char statement[TURN_LONG_STRING_SIZE];
  249. PGconn *pqc = get_pqdb_connection();
  250. if(pqc) {
  251. snprintf(statement,sizeof(statement),"insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('%s','%s',%llu,%lu,'%s','%s','%s','%s','%s')",
  252. key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime,
  253. key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key);
  254. PGresult *res = PQexec(pqc, statement);
  255. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  256. if(res) {
  257. PQclear(res);
  258. }
  259. snprintf(statement,sizeof(statement),"update oauth_key set ikm_key='%s',timestamp=%lu,lifetime=%lu, hkdf_hash_func = '%s', as_rs_alg='%s',as_rs_key='%s',auth_alg='%s',auth_key='%s' where kid='%s'",key->ikm_key,(unsigned long)key->timestamp,(unsigned long)key->lifetime,
  260. key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key,key->kid);
  261. res = PQexec(pqc, statement);
  262. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  263. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc));
  264. } else {
  265. ret = 0;
  266. }
  267. }
  268. if(res) {
  269. PQclear(res);
  270. }
  271. }
  272. return ret;
  273. }
  274. static int pgsql_set_user_pwd(u08bits *usname, st_password_t pwd) {
  275. int ret = -1;
  276. char statement[TURN_LONG_STRING_SIZE];
  277. PGconn *pqc = get_pqdb_connection();
  278. if(pqc) {
  279. snprintf(statement,sizeof(statement),"insert into turnusers_st values('%s','%s')",usname,pwd);
  280. PGresult *res = PQexec(pqc, statement);
  281. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  282. if(res) {
  283. PQclear(res);
  284. }
  285. snprintf(statement,sizeof(statement),"update turnusers_st set password='%s' where name='%s'",pwd,usname);
  286. res = PQexec(pqc, statement);
  287. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  288. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
  289. } else {
  290. ret = 0;
  291. }
  292. }
  293. if(res) {
  294. PQclear(res);
  295. }
  296. }
  297. return ret;
  298. }
  299. static int pgsql_del_user(u08bits *usname, int is_st, u08bits *realm) {
  300. int ret = -1;
  301. char statement[TURN_LONG_STRING_SIZE];
  302. PGconn *pqc = get_pqdb_connection();
  303. if(pqc) {
  304. if(is_st) {
  305. snprintf(statement,sizeof(statement),"delete from turnusers_st where name='%s'",usname);
  306. } else {
  307. snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
  308. }
  309. PGresult *res = PQexec(pqc, statement);
  310. if(res) {
  311. PQclear(res);
  312. ret = 0;
  313. }
  314. }
  315. return ret;
  316. }
  317. static int pgsql_del_oauth_key(const u08bits *kid) {
  318. int ret = -1;
  319. char statement[TURN_LONG_STRING_SIZE];
  320. PGconn *pqc = get_pqdb_connection();
  321. if(pqc) {
  322. snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid);
  323. PGresult *res = PQexec(pqc, statement);
  324. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  325. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc));
  326. } else {
  327. ret = 0;
  328. }
  329. if(res) {
  330. PQclear(res);
  331. }
  332. }
  333. return ret;
  334. }
  335. static int pgsql_list_users(int is_st, u08bits *realm) {
  336. int ret = -1;
  337. char statement[TURN_LONG_STRING_SIZE];
  338. PGconn *pqc = get_pqdb_connection();
  339. if(pqc) {
  340. if(is_st) {
  341. snprintf(statement,sizeof(statement),"select name,'' from turnusers_st order by name");
  342. } else if(realm && realm[0]) {
  343. snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt where realm='%s' order by name",realm);
  344. } else {
  345. snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by name");
  346. }
  347. PGresult *res = PQexec(pqc, statement);
  348. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  349. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  350. } else {
  351. int i = 0;
  352. for(i=0;i<PQntuples(res);i++) {
  353. char *kval = PQgetvalue(res,i,0);
  354. if(kval) {
  355. char *rval = PQgetvalue(res,i,1);
  356. if(rval && *rval) {
  357. printf("%s[%s]\n",kval,rval);
  358. } else {
  359. printf("%s\n",kval);
  360. }
  361. }
  362. }
  363. ret = 0;
  364. }
  365. if(res) {
  366. PQclear(res);
  367. }
  368. }
  369. return ret;
  370. }
  371. static int pgsql_show_secret(u08bits *realm) {
  372. int ret = -1;
  373. char statement[TURN_LONG_STRING_SIZE];
  374. snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
  375. donot_print_connection_success=1;
  376. PGconn *pqc = get_pqdb_connection();
  377. if(pqc) {
  378. PGresult *res = PQexec(pqc, statement);
  379. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  380. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  381. } else {
  382. int i = 0;
  383. for(i=0;i<PQntuples(res);i++) {
  384. char *kval = PQgetvalue(res,i,0);
  385. if(kval) {
  386. printf("%s\n",kval);
  387. }
  388. }
  389. ret = 0;
  390. }
  391. if(res) {
  392. PQclear(res);
  393. }
  394. }
  395. return ret;
  396. }
  397. static int pgsql_del_secret(u08bits *secret, u08bits *realm) {
  398. int ret = -1;
  399. donot_print_connection_success=1;
  400. char statement[TURN_LONG_STRING_SIZE];
  401. PGconn *pqc = get_pqdb_connection();
  402. if (pqc) {
  403. if(!secret || (secret[0]==0))
  404. snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm);
  405. else
  406. snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm);
  407. PGresult *res = PQexec(pqc, statement);
  408. if (res) {
  409. PQclear(res);
  410. ret = 0;
  411. }
  412. }
  413. return ret;
  414. }
  415. static int pgsql_set_secret(u08bits *secret, u08bits *realm) {
  416. int ret = -1;
  417. donot_print_connection_success = 1;
  418. char statement[TURN_LONG_STRING_SIZE];
  419. PGconn *pqc = get_pqdb_connection();
  420. if (pqc) {
  421. snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret);
  422. PGresult *res = PQexec(pqc, statement);
  423. if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  424. TURN_LOG_FUNC(
  425. TURN_LOG_LEVEL_ERROR,
  426. "Error inserting/updating secret key information: %s\n",
  427. PQerrorMessage(pqc));
  428. } else {
  429. ret = 0;
  430. }
  431. if (res) {
  432. PQclear(res);
  433. }
  434. }
  435. return ret;
  436. }
  437. static int pgsql_add_origin(u08bits *origin, u08bits *realm) {
  438. int ret = -1;
  439. char statement[TURN_LONG_STRING_SIZE];
  440. PGconn *pqc = get_pqdb_connection();
  441. if(pqc) {
  442. snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm);
  443. PGresult *res = PQexec(pqc, statement);
  444. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  445. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting origin information: %s\n",PQerrorMessage(pqc));
  446. } else {
  447. ret = 0;
  448. }
  449. if(res) {
  450. PQclear(res);
  451. }
  452. }
  453. return ret;
  454. }
  455. static int pgsql_del_origin(u08bits *origin) {
  456. int ret = -1;
  457. char statement[TURN_LONG_STRING_SIZE];
  458. PGconn *pqc = get_pqdb_connection();
  459. if(pqc) {
  460. snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin);
  461. PGresult *res = PQexec(pqc, statement);
  462. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  463. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information: %s\n",PQerrorMessage(pqc));
  464. } else {
  465. ret = 0;
  466. }
  467. if(res) {
  468. PQclear(res);
  469. }
  470. }
  471. return ret;
  472. }
  473. static int pgsql_list_origins(u08bits *realm) {
  474. int ret = -1;
  475. donot_print_connection_success = 1;
  476. char statement[TURN_LONG_STRING_SIZE];
  477. PGconn *pqc = get_pqdb_connection();
  478. if(pqc) {
  479. if(realm && realm[0]) {
  480. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
  481. } else {
  482. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
  483. }
  484. PGresult *res = PQexec(pqc, statement);
  485. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  486. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  487. } else {
  488. int i = 0;
  489. for(i=0;i<PQntuples(res);i++) {
  490. char *oval = PQgetvalue(res,i,0);
  491. if(oval) {
  492. char *rval = PQgetvalue(res,i,1);
  493. if(rval) {
  494. printf("%s ==>> %s\n",oval,rval);
  495. }
  496. }
  497. }
  498. ret = 0;
  499. }
  500. if(res) {
  501. PQclear(res);
  502. }
  503. }
  504. return ret;
  505. }
  506. static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
  507. int ret = -1;
  508. char statement[TURN_LONG_STRING_SIZE];
  509. PGconn *pqc = get_pqdb_connection();
  510. if(pqc) {
  511. {
  512. snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt);
  513. PGresult *res = PQexec(pqc, statement);
  514. if(res) {
  515. PQclear(res);
  516. }
  517. }
  518. if(value>0) {
  519. snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value);
  520. PGresult *res = PQexec(pqc, statement);
  521. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  522. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc));
  523. } else {
  524. ret = 0;
  525. }
  526. if(res) {
  527. PQclear(res);
  528. }
  529. }
  530. }
  531. return ret;
  532. }
  533. static int pgsql_list_realm_options(u08bits *realm) {
  534. int ret = -1;
  535. donot_print_connection_success = 1;
  536. char statement[TURN_LONG_STRING_SIZE];
  537. PGconn *pqc = get_pqdb_connection();
  538. if(pqc) {
  539. if(realm && realm[0]) {
  540. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm);
  541. } else {
  542. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt");
  543. }
  544. PGresult *res = PQexec(pqc, statement);
  545. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  546. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  547. } else {
  548. int i = 0;
  549. for(i=0;i<PQntuples(res);i++) {
  550. char *rval = PQgetvalue(res,i,0);
  551. if(rval) {
  552. char *oval = PQgetvalue(res,i,1);
  553. if(oval) {
  554. char *vval = PQgetvalue(res,i,2);
  555. if(vval) {
  556. printf("%s[%s]=%s\n",oval,rval,vval);
  557. }
  558. }
  559. }
  560. }
  561. ret = 0;
  562. }
  563. if(res) {
  564. PQclear(res);
  565. }
  566. }
  567. return ret;
  568. }
  569. static void pgsql_auth_ping(void * rch) {
  570. UNUSED_ARG(rch);
  571. donot_print_connection_success = 1;
  572. PGconn * pqc = get_pqdb_connection();
  573. if(pqc) {
  574. char statement[TURN_LONG_STRING_SIZE];
  575. STRCPY(statement,"select value from turn_secret");
  576. PGresult *res = PQexec(pqc, statement);
  577. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  578. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  579. }
  580. if(res) {
  581. PQclear(res);
  582. }
  583. }
  584. }
  585. static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list)
  586. {
  587. int ret = -1;
  588. PGconn * pqc = get_pqdb_connection();
  589. if (pqc) {
  590. char statement[TURN_LONG_STRING_SIZE];
  591. snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind);
  592. PGresult *res = PQexec(pqc, statement);
  593. if (!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  594. static int wrong_table_reported = 0;
  595. if(!wrong_table_reported) {
  596. wrong_table_reported = 1;
  597. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n",PQerrorMessage(pqc));
  598. }
  599. snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
  600. res = PQexec(pqc, statement);
  601. }
  602. if (res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  603. int i = 0;
  604. for (i = 0; i < PQntuples(res); i++) {
  605. char *kval = PQgetvalue(res, i, 0);
  606. char *rval = PQgetvalue(res, i, 1);
  607. if (kval) {
  608. add_ip_list_range(kval, rval, list);
  609. }
  610. }
  611. ret = 0;
  612. }
  613. if (res) {
  614. PQclear(res);
  615. }
  616. }
  617. return ret;
  618. }
  619. static void pgsql_reread_realms(secrets_list_t * realms_list) {
  620. PGconn * pqc = get_pqdb_connection();
  621. if(pqc) {
  622. char statement[TURN_LONG_STRING_SIZE];
  623. {
  624. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm");
  625. PGresult *res = PQexec(pqc, statement);
  626. if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  627. ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple);
  628. int i = 0;
  629. for(i=0;i<PQntuples(res);i++) {
  630. char *oval = PQgetvalue(res,i,0);
  631. if(oval) {
  632. char *rval = PQgetvalue(res,i,1);
  633. if(rval) {
  634. get_realm(rval);
  635. ur_string_map_value_type value = turn_strdup(rval);
  636. ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
  637. }
  638. }
  639. }
  640. update_o_to_realm(o_to_realm_new);
  641. }
  642. if(res) {
  643. PQclear(res);
  644. }
  645. }
  646. {
  647. {
  648. size_t i = 0;
  649. size_t rlsz = 0;
  650. lock_realms();
  651. rlsz = realms_list->sz;
  652. unlock_realms();
  653. for (i = 0; i<rlsz; ++i) {
  654. char *realm = realms_list->secrets[i];
  655. realm_params_t* rp = get_realm(realm);
  656. lock_realms();
  657. rp->options.perf_options.max_bps = turn_params.max_bps;
  658. unlock_realms();
  659. lock_realms();
  660. rp->options.perf_options.total_quota = turn_params.total_quota;
  661. unlock_realms();
  662. lock_realms();
  663. rp->options.perf_options.user_quota = turn_params.user_quota;
  664. unlock_realms();
  665. }
  666. }
  667. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option");
  668. PGresult *res = PQexec(pqc, statement);
  669. if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  670. int i = 0;
  671. for(i=0;i<PQntuples(res);i++) {
  672. char *rval = PQgetvalue(res,i,0);
  673. char *oval = PQgetvalue(res,i,1);
  674. char *vval = PQgetvalue(res,i,2);
  675. if(rval && oval && vval) {
  676. realm_params_t* rp = get_realm(rval);
  677. if(!strcmp(oval,"max-bps"))
  678. rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
  679. else if(!strcmp(oval,"total-quota"))
  680. rp->options.perf_options.total_quota = (vint)atoi(vval);
  681. else if(!strcmp(oval,"user-quota"))
  682. rp->options.perf_options.user_quota = (vint)atoi(vval);
  683. else {
  684. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval);
  685. }
  686. }
  687. }
  688. }
  689. if(res) {
  690. PQclear(res);
  691. }
  692. }
  693. }
  694. }
  695. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  696. static turn_dbdriver_t driver = {
  697. &pgsql_get_auth_secrets,
  698. &pgsql_get_user_key,
  699. &pgsql_get_user_pwd,
  700. &pgsql_set_user_key,
  701. &pgsql_set_user_pwd,
  702. &pgsql_del_user,
  703. &pgsql_list_users,
  704. &pgsql_show_secret,
  705. &pgsql_del_secret,
  706. &pgsql_set_secret,
  707. &pgsql_add_origin,
  708. &pgsql_del_origin,
  709. &pgsql_list_origins,
  710. &pgsql_set_realm_option_one,
  711. &pgsql_list_realm_options,
  712. &pgsql_auth_ping,
  713. &pgsql_get_ip_list,
  714. &pgsql_reread_realms,
  715. &pgsql_set_oauth_key,
  716. &pgsql_get_oauth_key,
  717. &pgsql_del_oauth_key,
  718. &pgsql_list_oauth_keys
  719. };
  720. turn_dbdriver_t * get_pgsql_dbdriver(void) {
  721. return &driver;
  722. }
  723. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  724. #else
  725. turn_dbdriver_t * get_pgsql_dbdriver(void) {
  726. return NULL;
  727. }
  728. #endif