dbd_pgsql.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  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*)pthread_getspecific(connection_key);
  40. if(pqdbconnection) {
  41. ConnStatusType status = PQstatus(pqdbconnection);
  42. if(status != CONNECTION_OK) {
  43. PQfinish(pqdbconnection);
  44. pqdbconnection = NULL;
  45. (void) pthread_setspecific(connection_key, pqdbconnection);
  46. }
  47. }
  48. if(!pqdbconnection) {
  49. char *errmsg=NULL;
  50. PQconninfoOption *co = PQconninfoParse(pud->userdb, &errmsg);
  51. if(!co) {
  52. if(errmsg) {
  53. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection <%s>, connection string format error: %s\n",pud->userdb,errmsg);
  54. turn_free(errmsg,strlen(errmsg)+1);
  55. } else {
  56. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, unknown connection string format error\n",pud->userdb);
  57. }
  58. } else {
  59. PQconninfoFree(co);
  60. if(errmsg)
  61. turn_free(errmsg,strlen(errmsg)+1);
  62. pqdbconnection = PQconnectdb(pud->userdb);
  63. if(!pqdbconnection) {
  64. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
  65. } else {
  66. ConnStatusType status = PQstatus(pqdbconnection);
  67. if(status != CONNECTION_OK) {
  68. PQfinish(pqdbconnection);
  69. pqdbconnection = NULL;
  70. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot open PostgreSQL DB connection: <%s>, runtime error\n",pud->userdb);
  71. } else if(!donot_print_connection_success){
  72. TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "PostgreSQL DB connection success: %s\n",pud->userdb);
  73. donot_print_connection_success = 1;
  74. }
  75. }
  76. }
  77. if(pqdbconnection) {
  78. (void) pthread_setspecific(connection_key, pqdbconnection);
  79. }
  80. }
  81. return pqdbconnection;
  82. }
  83. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  84. static int pgsql_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
  85. int ret = -1;
  86. PGconn * pqc = get_pqdb_connection();
  87. if(pqc) {
  88. char statement[TURN_LONG_STRING_SIZE];
  89. snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
  90. PGresult *res = PQexec(pqc, statement);
  91. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  92. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  93. } else {
  94. int i = 0;
  95. for(i=0;i<PQntuples(res);i++) {
  96. char *kval = PQgetvalue(res,i,0);
  97. if(kval) {
  98. add_to_secrets_list(sl,kval);
  99. }
  100. }
  101. ret = 0;
  102. }
  103. if(res) {
  104. PQclear(res);
  105. }
  106. }
  107. return ret;
  108. }
  109. static int pgsql_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
  110. int ret = -1;
  111. PGconn * pqc = get_pqdb_connection();
  112. if(pqc) {
  113. char statement[TURN_LONG_STRING_SIZE];
  114. snprintf(statement,sizeof(statement),"select hmackey from turnusers_lt where name='%s' and realm='%s'",usname,realm);
  115. PGresult *res = PQexec(pqc, statement);
  116. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  117. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  118. } else {
  119. char *kval = PQgetvalue(res,0,0);
  120. int len = PQgetlength(res,0,0);
  121. if(kval) {
  122. size_t sz = get_hmackey_size(turn_params.shatype);
  123. if(((size_t)len<sz*2)||(strlen(kval)<sz*2)) {
  124. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key format: %s, user %s\n",kval,usname);
  125. } else if(convert_string_key_to_binary(kval, key, sz)<0) {
  126. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong key: %s, user %s\n",kval,usname);
  127. } else {
  128. ret = 0;
  129. }
  130. } else {
  131. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Wrong hmackey data for user %s: NULL\n",usname);
  132. }
  133. }
  134. if(res)
  135. PQclear(res);
  136. }
  137. return ret;
  138. }
  139. static int pgsql_get_oauth_key(const u08bits *kid, oauth_key_data_raw *key) {
  140. int ret = -1;
  141. char statement[TURN_LONG_STRING_SIZE];
  142. 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);
  143. PGconn * pqc = get_pqdb_connection();
  144. if(pqc) {
  145. PGresult *res = PQexec(pqc, statement);
  146. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  147. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  148. } else {
  149. STRCPY((char*)key->ikm_key,PQgetvalue(res,0,0));
  150. key->timestamp = (u64bits)strtoll(PQgetvalue(res,0,1),NULL,10);
  151. key->lifetime = (u32bits)strtol(PQgetvalue(res,0,2),NULL,10);
  152. STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,0,3));
  153. STRCPY((char*)key->as_rs_alg,PQgetvalue(res,0,4));
  154. STRCPY((char*)key->as_rs_key,PQgetvalue(res,0,5));
  155. STRCPY((char*)key->auth_alg,PQgetvalue(res,0,6));
  156. STRCPY((char*)key->auth_key,PQgetvalue(res,0,7));
  157. STRCPY((char*)key->kid,kid);
  158. ret = 0;
  159. }
  160. if(res) {
  161. PQclear(res);
  162. }
  163. }
  164. return ret;
  165. }
  166. static int pgsql_list_oauth_keys(void) {
  167. oauth_key_data_raw key_;
  168. oauth_key_data_raw *key=&key_;
  169. int ret = -1;
  170. char statement[TURN_LONG_STRING_SIZE];
  171. 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");
  172. PGconn * pqc = get_pqdb_connection();
  173. if(pqc) {
  174. PGresult *res = PQexec(pqc, statement);
  175. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  176. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  177. } else {
  178. int i = 0;
  179. for(i=0;i<PQntuples(res);i++) {
  180. STRCPY((char*)key->ikm_key,PQgetvalue(res,i,0));
  181. key->timestamp = (u64bits)strtoll(PQgetvalue(res,i,1),NULL,10);
  182. key->lifetime = (u32bits)strtol(PQgetvalue(res,i,2),NULL,10);
  183. STRCPY((char*)key->hkdf_hash_func,PQgetvalue(res,i,3));
  184. STRCPY((char*)key->as_rs_alg,PQgetvalue(res,i,4));
  185. STRCPY((char*)key->as_rs_key,PQgetvalue(res,i,5));
  186. STRCPY((char*)key->auth_alg,PQgetvalue(res,i,6));
  187. STRCPY((char*)key->auth_key,PQgetvalue(res,i,7));
  188. STRCPY((char*)key->kid,PQgetvalue(res,i,8));
  189. 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",
  190. key->kid, key->ikm_key, (unsigned long long)key->timestamp, (unsigned long)key->lifetime, key->hkdf_hash_func,
  191. key->as_rs_alg, key->as_rs_key, key->auth_alg, key->auth_key);
  192. ret = 0;
  193. }
  194. }
  195. if(res) {
  196. PQclear(res);
  197. }
  198. }
  199. return ret;
  200. }
  201. static int pgsql_set_user_key(u08bits *usname, u08bits *realm, const char *key) {
  202. int ret = -1;
  203. char statement[TURN_LONG_STRING_SIZE];
  204. PGconn *pqc = get_pqdb_connection();
  205. if(pqc) {
  206. snprintf(statement,sizeof(statement),"insert into turnusers_lt (realm,name,hmackey) values('%s','%s','%s')",realm,usname,key);
  207. PGresult *res = PQexec(pqc, statement);
  208. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  209. if(res) {
  210. PQclear(res);
  211. }
  212. snprintf(statement,sizeof(statement),"update turnusers_lt set hmackey='%s' where name='%s' and realm='%s'",key,usname,realm);
  213. res = PQexec(pqc, statement);
  214. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  215. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
  216. } else {
  217. ret = 0;
  218. }
  219. }
  220. if(res) {
  221. PQclear(res);
  222. }
  223. }
  224. return ret;
  225. }
  226. static int pgsql_set_oauth_key(oauth_key_data_raw *key) {
  227. int ret = -1;
  228. char statement[TURN_LONG_STRING_SIZE];
  229. PGconn *pqc = get_pqdb_connection();
  230. if(pqc) {
  231. 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')",
  232. key->kid,key->ikm_key,(unsigned long long)key->timestamp,(unsigned long)key->lifetime,
  233. key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key);
  234. PGresult *res = PQexec(pqc, statement);
  235. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  236. if(res) {
  237. PQclear(res);
  238. }
  239. 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,
  240. key->hkdf_hash_func,key->as_rs_alg,key->as_rs_key,key->auth_alg,key->auth_key,key->kid);
  241. res = PQexec(pqc, statement);
  242. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  243. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating oauth_key information: %s\n",PQerrorMessage(pqc));
  244. } else {
  245. ret = 0;
  246. }
  247. }
  248. if(res) {
  249. PQclear(res);
  250. }
  251. }
  252. return ret;
  253. }
  254. static int pgsql_del_user(u08bits *usname, u08bits *realm) {
  255. int ret = -1;
  256. char statement[TURN_LONG_STRING_SIZE];
  257. PGconn *pqc = get_pqdb_connection();
  258. if(pqc) {
  259. snprintf(statement,sizeof(statement),"delete from turnusers_lt where name='%s' and realm='%s'",usname,realm);
  260. PGresult *res = PQexec(pqc, statement);
  261. if(res) {
  262. PQclear(res);
  263. ret = 0;
  264. }
  265. }
  266. return ret;
  267. }
  268. static int pgsql_del_oauth_key(const u08bits *kid) {
  269. int ret = -1;
  270. char statement[TURN_LONG_STRING_SIZE];
  271. PGconn *pqc = get_pqdb_connection();
  272. if(pqc) {
  273. snprintf(statement,sizeof(statement),"delete from oauth_key where kid = '%s'",(const char*)kid);
  274. PGresult *res = PQexec(pqc, statement);
  275. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  276. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting oauth_key information: %s\n",PQerrorMessage(pqc));
  277. } else {
  278. ret = 0;
  279. }
  280. if(res) {
  281. PQclear(res);
  282. }
  283. }
  284. return ret;
  285. }
  286. static int pgsql_list_users(u08bits *realm, secrets_list_t *users, secrets_list_t *realms)
  287. {
  288. int ret = -1;
  289. char statement[TURN_LONG_STRING_SIZE];
  290. u08bits realm0[STUN_MAX_REALM_SIZE+1] = "\0";
  291. if(!realm) realm=realm0;
  292. PGconn *pqc = get_pqdb_connection();
  293. if(pqc) {
  294. if(realm[0]) {
  295. snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt where realm='%s' order by name",realm);
  296. } else {
  297. snprintf(statement,sizeof(statement),"select name,realm from turnusers_lt order by realm,name");
  298. }
  299. PGresult *res = PQexec(pqc, statement);
  300. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  301. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  302. } else {
  303. int i = 0;
  304. for(i=0;i<PQntuples(res);i++) {
  305. char *kval = PQgetvalue(res,i,0);
  306. if(kval) {
  307. char *rval = PQgetvalue(res,i,1);
  308. if(rval) {
  309. if(users) {
  310. add_to_secrets_list(users,kval);
  311. if(realms) {
  312. if(rval && *rval) {
  313. add_to_secrets_list(realms,rval);
  314. } else {
  315. add_to_secrets_list(realms,(char*)realm);
  316. }
  317. }
  318. } else {
  319. printf("%s[%s]\n", kval, rval);
  320. }
  321. }
  322. }
  323. }
  324. ret = 0;
  325. }
  326. if(res) {
  327. PQclear(res);
  328. }
  329. }
  330. return ret;
  331. }
  332. static int pgsql_show_secret(u08bits *realm) {
  333. int ret = -1;
  334. char statement[TURN_LONG_STRING_SIZE];
  335. snprintf(statement,sizeof(statement)-1,"select value from turn_secret where realm='%s'",realm);
  336. donot_print_connection_success=1;
  337. PGconn *pqc = get_pqdb_connection();
  338. if(pqc) {
  339. PGresult *res = PQexec(pqc, statement);
  340. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  341. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  342. } else {
  343. int i = 0;
  344. for(i=0;i<PQntuples(res);i++) {
  345. char *kval = PQgetvalue(res,i,0);
  346. if(kval) {
  347. printf("%s\n",kval);
  348. }
  349. }
  350. ret = 0;
  351. }
  352. if(res) {
  353. PQclear(res);
  354. }
  355. }
  356. return ret;
  357. }
  358. static int pgsql_del_secret(u08bits *secret, u08bits *realm) {
  359. int ret = -1;
  360. donot_print_connection_success=1;
  361. char statement[TURN_LONG_STRING_SIZE];
  362. PGconn *pqc = get_pqdb_connection();
  363. if (pqc) {
  364. if(!secret || (secret[0]==0))
  365. snprintf(statement,sizeof(statement),"delete from turn_secret where realm='%s'",realm);
  366. else
  367. snprintf(statement,sizeof(statement),"delete from turn_secret where value='%s' and realm='%s'",secret,realm);
  368. PGresult *res = PQexec(pqc, statement);
  369. if (res) {
  370. PQclear(res);
  371. ret = 0;
  372. }
  373. }
  374. return ret;
  375. }
  376. static int pgsql_set_secret(u08bits *secret, u08bits *realm) {
  377. int ret = -1;
  378. donot_print_connection_success = 1;
  379. char statement[TURN_LONG_STRING_SIZE];
  380. PGconn *pqc = get_pqdb_connection();
  381. if (pqc) {
  382. snprintf(statement,sizeof(statement),"insert into turn_secret (realm,value) values('%s','%s')",realm,secret);
  383. PGresult *res = PQexec(pqc, statement);
  384. if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  385. TURN_LOG_FUNC(
  386. TURN_LOG_LEVEL_ERROR,
  387. "Error inserting/updating secret key information: %s\n",
  388. PQerrorMessage(pqc));
  389. } else {
  390. ret = 0;
  391. }
  392. if (res) {
  393. PQclear(res);
  394. }
  395. }
  396. return ret;
  397. }
  398. static int pgsql_add_origin(u08bits *origin, u08bits *realm) {
  399. int ret = -1;
  400. char statement[TURN_LONG_STRING_SIZE];
  401. PGconn *pqc = get_pqdb_connection();
  402. if(pqc) {
  403. snprintf(statement,sizeof(statement),"insert into turn_origin_to_realm (origin,realm) values('%s','%s')",origin,realm);
  404. PGresult *res = PQexec(pqc, statement);
  405. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  406. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting origin information: %s\n",PQerrorMessage(pqc));
  407. } else {
  408. ret = 0;
  409. }
  410. if(res) {
  411. PQclear(res);
  412. }
  413. }
  414. return ret;
  415. }
  416. static int pgsql_del_origin(u08bits *origin) {
  417. int ret = -1;
  418. char statement[TURN_LONG_STRING_SIZE];
  419. PGconn *pqc = get_pqdb_connection();
  420. if(pqc) {
  421. snprintf(statement,sizeof(statement),"delete from turn_origin_to_realm where origin='%s'",origin);
  422. PGresult *res = PQexec(pqc, statement);
  423. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  424. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information: %s\n",PQerrorMessage(pqc));
  425. } else {
  426. ret = 0;
  427. }
  428. if(res) {
  429. PQclear(res);
  430. }
  431. }
  432. return ret;
  433. }
  434. static int pgsql_list_origins(u08bits *realm) {
  435. int ret = -1;
  436. donot_print_connection_success = 1;
  437. char statement[TURN_LONG_STRING_SIZE];
  438. PGconn *pqc = get_pqdb_connection();
  439. if(pqc) {
  440. if(realm && realm[0]) {
  441. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm where realm='%s' order by origin",realm);
  442. } else {
  443. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm order by origin,realm");
  444. }
  445. PGresult *res = PQexec(pqc, statement);
  446. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  447. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  448. } else {
  449. int i = 0;
  450. for(i=0;i<PQntuples(res);i++) {
  451. char *oval = PQgetvalue(res,i,0);
  452. if(oval) {
  453. char *rval = PQgetvalue(res,i,1);
  454. if(rval) {
  455. printf("%s ==>> %s\n",oval,rval);
  456. }
  457. }
  458. }
  459. ret = 0;
  460. }
  461. if(res) {
  462. PQclear(res);
  463. }
  464. }
  465. return ret;
  466. }
  467. static int pgsql_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) {
  468. int ret = -1;
  469. char statement[TURN_LONG_STRING_SIZE];
  470. PGconn *pqc = get_pqdb_connection();
  471. if(pqc) {
  472. {
  473. snprintf(statement,sizeof(statement),"delete from turn_realm_option where realm='%s' and opt='%s'",realm,opt);
  474. PGresult *res = PQexec(pqc, statement);
  475. if(res) {
  476. PQclear(res);
  477. }
  478. }
  479. if(value>0) {
  480. snprintf(statement,sizeof(statement),"insert into turn_realm_option (realm,opt,value) values('%s','%s','%lu')",realm,opt,(unsigned long)value);
  481. PGresult *res = PQexec(pqc, statement);
  482. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  483. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting realm option information: %s\n",PQerrorMessage(pqc));
  484. } else {
  485. ret = 0;
  486. }
  487. if(res) {
  488. PQclear(res);
  489. }
  490. }
  491. }
  492. return ret;
  493. }
  494. static int pgsql_list_realm_options(u08bits *realm) {
  495. int ret = -1;
  496. donot_print_connection_success = 1;
  497. char statement[TURN_LONG_STRING_SIZE];
  498. PGconn *pqc = get_pqdb_connection();
  499. if(pqc) {
  500. if(realm && realm[0]) {
  501. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option where realm='%s' order by realm,opt",realm);
  502. } else {
  503. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option order by realm,opt");
  504. }
  505. PGresult *res = PQexec(pqc, statement);
  506. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  507. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  508. } else {
  509. int i = 0;
  510. for(i=0;i<PQntuples(res);i++) {
  511. char *rval = PQgetvalue(res,i,0);
  512. if(rval) {
  513. char *oval = PQgetvalue(res,i,1);
  514. if(oval) {
  515. char *vval = PQgetvalue(res,i,2);
  516. if(vval) {
  517. printf("%s[%s]=%s\n",oval,rval,vval);
  518. }
  519. }
  520. }
  521. }
  522. ret = 0;
  523. }
  524. if(res) {
  525. PQclear(res);
  526. }
  527. }
  528. return ret;
  529. }
  530. static void pgsql_auth_ping(void * rch) {
  531. UNUSED_ARG(rch);
  532. PGconn * pqc = get_pqdb_connection();
  533. if(pqc) {
  534. char statement[TURN_LONG_STRING_SIZE];
  535. STRCPY(statement,"select value from turn_secret");
  536. PGresult *res = PQexec(pqc, statement);
  537. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  538. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  539. }
  540. if(res) {
  541. PQclear(res);
  542. }
  543. }
  544. }
  545. static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list)
  546. {
  547. int ret = -1;
  548. PGconn * pqc = get_pqdb_connection();
  549. if (pqc) {
  550. char statement[TURN_LONG_STRING_SIZE];
  551. snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind);
  552. PGresult *res = PQexec(pqc, statement);
  553. if (!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  554. static int wrong_table_reported = 0;
  555. if(!wrong_table_reported) {
  556. wrong_table_reported = 1;
  557. 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));
  558. }
  559. snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
  560. res = PQexec(pqc, statement);
  561. }
  562. if (res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  563. int i = 0;
  564. for (i = 0; i < PQntuples(res); i++) {
  565. char *kval = PQgetvalue(res, i, 0);
  566. char *rval = PQgetvalue(res, i, 1);
  567. if (kval) {
  568. add_ip_list_range(kval, rval, list);
  569. }
  570. }
  571. ret = 0;
  572. }
  573. if (res) {
  574. PQclear(res);
  575. }
  576. }
  577. return ret;
  578. }
  579. static void pgsql_reread_realms(secrets_list_t * realms_list) {
  580. PGconn * pqc = get_pqdb_connection();
  581. if(pqc) {
  582. char statement[TURN_LONG_STRING_SIZE];
  583. {
  584. snprintf(statement,sizeof(statement),"select origin,realm from turn_origin_to_realm");
  585. PGresult *res = PQexec(pqc, statement);
  586. if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  587. ur_string_map *o_to_realm_new = ur_string_map_create(turn_free_simple);
  588. int i = 0;
  589. for(i=0;i<PQntuples(res);i++) {
  590. char *oval = PQgetvalue(res,i,0);
  591. if(oval) {
  592. char *rval = PQgetvalue(res,i,1);
  593. if(rval) {
  594. get_realm(rval);
  595. ur_string_map_value_type value = turn_strdup(rval);
  596. ur_string_map_put(o_to_realm_new, (const ur_string_map_key_type) oval, value);
  597. }
  598. }
  599. }
  600. update_o_to_realm(o_to_realm_new);
  601. }
  602. if(res) {
  603. PQclear(res);
  604. }
  605. }
  606. {
  607. {
  608. size_t i = 0;
  609. size_t rlsz = 0;
  610. lock_realms();
  611. rlsz = realms_list->sz;
  612. unlock_realms();
  613. for (i = 0; i<rlsz; ++i) {
  614. char *realm = realms_list->secrets[i];
  615. realm_params_t* rp = get_realm(realm);
  616. lock_realms();
  617. rp->options.perf_options.max_bps = turn_params.max_bps;
  618. unlock_realms();
  619. lock_realms();
  620. rp->options.perf_options.total_quota = turn_params.total_quota;
  621. unlock_realms();
  622. lock_realms();
  623. rp->options.perf_options.user_quota = turn_params.user_quota;
  624. unlock_realms();
  625. }
  626. }
  627. snprintf(statement,sizeof(statement),"select realm,opt,value from turn_realm_option");
  628. PGresult *res = PQexec(pqc, statement);
  629. if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
  630. int i = 0;
  631. for(i=0;i<PQntuples(res);i++) {
  632. char *rval = PQgetvalue(res,i,0);
  633. char *oval = PQgetvalue(res,i,1);
  634. char *vval = PQgetvalue(res,i,2);
  635. if(rval && oval && vval) {
  636. realm_params_t* rp = get_realm(rval);
  637. if(!strcmp(oval,"max-bps"))
  638. rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
  639. else if(!strcmp(oval,"total-quota"))
  640. rp->options.perf_options.total_quota = (vint)atoi(vval);
  641. else if(!strcmp(oval,"user-quota"))
  642. rp->options.perf_options.user_quota = (vint)atoi(vval);
  643. else {
  644. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unknown realm option: %s\n", oval);
  645. }
  646. }
  647. }
  648. }
  649. if(res) {
  650. PQclear(res);
  651. }
  652. }
  653. }
  654. }
  655. //////////////////////////////////////////////
  656. static int pgsql_get_admin_user(const u08bits *usname, u08bits *realm, password_t pwd)
  657. {
  658. int ret = -1;
  659. realm[0]=0;
  660. pwd[0]=0;
  661. PGconn * pqc = get_pqdb_connection();
  662. if(pqc) {
  663. char statement[TURN_LONG_STRING_SIZE];
  664. snprintf(statement,sizeof(statement),"select realm,password from admin_user where name='%s'",usname);
  665. PGresult *res = PQexec(pqc, statement);
  666. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res)!=1)) {
  667. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  668. } else {
  669. const char *kval = PQgetvalue(res,0,0);
  670. if(kval) {
  671. strncpy((char*)realm,kval,STUN_MAX_REALM_SIZE);
  672. }
  673. kval = (const char*) PQgetvalue(res,0,1);
  674. if(kval) {
  675. strncpy((char*)pwd,kval,STUN_MAX_PWD_SIZE);
  676. }
  677. ret = 0;
  678. }
  679. if(res)
  680. PQclear(res);
  681. }
  682. return ret;
  683. }
  684. static int pgsql_set_admin_user(const u08bits *usname, const u08bits *realm, const password_t pwd)
  685. {
  686. int ret = -1;
  687. char statement[TURN_LONG_STRING_SIZE];
  688. donot_print_connection_success=1;
  689. PGconn *pqc = get_pqdb_connection();
  690. if(pqc) {
  691. snprintf(statement,sizeof(statement),"insert into admin_user (realm,name,password) values('%s','%s','%s')",realm,usname,pwd);
  692. PGresult *res = PQexec(pqc, statement);
  693. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  694. if(res) {
  695. PQclear(res);
  696. }
  697. snprintf(statement,sizeof(statement),"update admin_user set password='%s',realm='%s' where name='%s'",pwd,realm,usname);
  698. res = PQexec(pqc, statement);
  699. if(!res || (PQresultStatus(res) != PGRES_COMMAND_OK)) {
  700. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error inserting/updating user information: %s\n",PQerrorMessage(pqc));
  701. } else {
  702. ret = 0;
  703. }
  704. }
  705. if(res) {
  706. PQclear(res);
  707. }
  708. }
  709. return ret;
  710. }
  711. static int pgsql_del_admin_user(const u08bits *usname)
  712. {
  713. int ret = -1;
  714. char statement[TURN_LONG_STRING_SIZE];
  715. donot_print_connection_success=1;
  716. PGconn *pqc = get_pqdb_connection();
  717. if(pqc) {
  718. snprintf(statement,sizeof(statement),"delete from admin_user where name='%s'",usname);
  719. PGresult *res = PQexec(pqc, statement);
  720. if(res) {
  721. PQclear(res);
  722. ret = 0;
  723. }
  724. }
  725. return ret;
  726. }
  727. static int pgsql_list_admin_users(void)
  728. {
  729. int ret = -1;
  730. char statement[TURN_LONG_STRING_SIZE];
  731. donot_print_connection_success=1;
  732. PGconn *pqc = get_pqdb_connection();
  733. if(pqc) {
  734. snprintf(statement,sizeof(statement),"select name,realm,password from admin_user order by realm,name");
  735. }
  736. PGresult *res = PQexec(pqc, statement);
  737. if(!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
  738. TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s\n",PQerrorMessage(pqc));
  739. } else {
  740. int i = 0;
  741. for(i=0;i<PQntuples(res);i++) {
  742. char *kval = PQgetvalue(res,i,0);
  743. if(kval) {
  744. char *rval = PQgetvalue(res,i,1);
  745. if(rval && *rval) {
  746. printf("%s[%s]\n",kval,rval);
  747. } else {
  748. printf("%s\n",kval);
  749. }
  750. }
  751. }
  752. ret = 0;
  753. }
  754. if(res) {
  755. PQclear(res);
  756. }
  757. return ret;
  758. }
  759. /////////////////////////////////////////////////////////////
  760. static const turn_dbdriver_t driver = {
  761. &pgsql_get_auth_secrets,
  762. &pgsql_get_user_key,
  763. &pgsql_set_user_key,
  764. &pgsql_del_user,
  765. &pgsql_list_users,
  766. &pgsql_show_secret,
  767. &pgsql_del_secret,
  768. &pgsql_set_secret,
  769. &pgsql_add_origin,
  770. &pgsql_del_origin,
  771. &pgsql_list_origins,
  772. &pgsql_set_realm_option_one,
  773. &pgsql_list_realm_options,
  774. &pgsql_auth_ping,
  775. &pgsql_get_ip_list,
  776. &pgsql_reread_realms,
  777. &pgsql_set_oauth_key,
  778. &pgsql_get_oauth_key,
  779. &pgsql_del_oauth_key,
  780. &pgsql_list_oauth_keys,
  781. &pgsql_get_admin_user,
  782. &pgsql_set_admin_user,
  783. &pgsql_del_admin_user,
  784. &pgsql_list_admin_users
  785. };
  786. const turn_dbdriver_t * get_pgsql_dbdriver(void) {
  787. return &driver;
  788. }
  789. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  790. #else
  791. const turn_dbdriver_t * get_pgsql_dbdriver(void) {
  792. return NULL;
  793. }
  794. #endif