2
0

dso_lib.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "dso_local.h"
  10. #include "internal/refcount.h"
  11. static DSO *DSO_new_method(DSO_METHOD *meth)
  12. {
  13. DSO *ret;
  14. ret = OPENSSL_zalloc(sizeof(*ret));
  15. if (ret == NULL)
  16. return NULL;
  17. ret->meth_data = sk_void_new_null();
  18. if (ret->meth_data == NULL) {
  19. /* sk_new doesn't generate any errors so we do */
  20. ERR_raise(ERR_LIB_DSO, ERR_R_CRYPTO_LIB);
  21. OPENSSL_free(ret);
  22. return NULL;
  23. }
  24. ret->meth = DSO_METHOD_openssl();
  25. ret->references = 1;
  26. ret->lock = CRYPTO_THREAD_lock_new();
  27. if (ret->lock == NULL) {
  28. ERR_raise(ERR_LIB_DSO, ERR_R_CRYPTO_LIB);
  29. sk_void_free(ret->meth_data);
  30. OPENSSL_free(ret);
  31. return NULL;
  32. }
  33. if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
  34. DSO_free(ret);
  35. ret = NULL;
  36. }
  37. return ret;
  38. }
  39. DSO *DSO_new(void)
  40. {
  41. return DSO_new_method(NULL);
  42. }
  43. int DSO_free(DSO *dso)
  44. {
  45. int i;
  46. if (dso == NULL)
  47. return 1;
  48. if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0)
  49. return 0;
  50. REF_PRINT_COUNT("DSO", dso);
  51. if (i > 0)
  52. return 1;
  53. REF_ASSERT_ISNT(i < 0);
  54. if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
  55. if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
  56. ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
  57. return 0;
  58. }
  59. }
  60. if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
  61. ERR_raise(ERR_LIB_DSO, DSO_R_FINISH_FAILED);
  62. return 0;
  63. }
  64. sk_void_free(dso->meth_data);
  65. OPENSSL_free(dso->filename);
  66. OPENSSL_free(dso->loaded_filename);
  67. CRYPTO_THREAD_lock_free(dso->lock);
  68. OPENSSL_free(dso);
  69. return 1;
  70. }
  71. int DSO_flags(DSO *dso)
  72. {
  73. return ((dso == NULL) ? 0 : dso->flags);
  74. }
  75. int DSO_up_ref(DSO *dso)
  76. {
  77. int i;
  78. if (dso == NULL) {
  79. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  80. return 0;
  81. }
  82. if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
  83. return 0;
  84. REF_PRINT_COUNT("DSO", dso);
  85. REF_ASSERT_ISNT(i < 2);
  86. return ((i > 1) ? 1 : 0);
  87. }
  88. DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
  89. {
  90. DSO *ret;
  91. int allocated = 0;
  92. if (dso == NULL) {
  93. ret = DSO_new_method(meth);
  94. if (ret == NULL) {
  95. ERR_raise(ERR_LIB_DSO, ERR_R_DSO_LIB);
  96. goto err;
  97. }
  98. allocated = 1;
  99. /* Pass the provided flags to the new DSO object */
  100. if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
  101. ERR_raise(ERR_LIB_DSO, DSO_R_CTRL_FAILED);
  102. goto err;
  103. }
  104. } else
  105. ret = dso;
  106. /* Don't load if we're currently already loaded */
  107. if (ret->filename != NULL) {
  108. ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
  109. goto err;
  110. }
  111. /*
  112. * filename can only be NULL if we were passed a dso that already has one
  113. * set.
  114. */
  115. if (filename != NULL)
  116. if (!DSO_set_filename(ret, filename)) {
  117. ERR_raise(ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED);
  118. goto err;
  119. }
  120. filename = ret->filename;
  121. if (filename == NULL) {
  122. ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
  123. goto err;
  124. }
  125. if (ret->meth->dso_load == NULL) {
  126. ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
  127. goto err;
  128. }
  129. if (!ret->meth->dso_load(ret)) {
  130. ERR_raise(ERR_LIB_DSO, DSO_R_LOAD_FAILED);
  131. goto err;
  132. }
  133. /* Load succeeded */
  134. return ret;
  135. err:
  136. if (allocated)
  137. DSO_free(ret);
  138. return NULL;
  139. }
  140. DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
  141. {
  142. DSO_FUNC_TYPE ret = NULL;
  143. if ((dso == NULL) || (symname == NULL)) {
  144. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  145. return NULL;
  146. }
  147. if (dso->meth->dso_bind_func == NULL) {
  148. ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
  149. return NULL;
  150. }
  151. if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
  152. ERR_raise(ERR_LIB_DSO, DSO_R_SYM_FAILURE);
  153. return NULL;
  154. }
  155. /* Success */
  156. return ret;
  157. }
  158. /*
  159. * I don't really like these *_ctrl functions very much to be perfectly
  160. * honest. For one thing, I think I have to return a negative value for any
  161. * error because possible DSO_ctrl() commands may return values such as
  162. * "size"s that can legitimately be zero (making the standard
  163. * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
  164. * times. I'd prefer "output" values to be passed by reference and the return
  165. * value as success/failure like usual ... but we conform when we must... :-)
  166. */
  167. long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
  168. {
  169. if (dso == NULL) {
  170. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  171. return -1;
  172. }
  173. /*
  174. * We should intercept certain generic commands and only pass control to
  175. * the method-specific ctrl() function if it's something we don't handle.
  176. */
  177. switch (cmd) {
  178. case DSO_CTRL_GET_FLAGS:
  179. return dso->flags;
  180. case DSO_CTRL_SET_FLAGS:
  181. dso->flags = (int)larg;
  182. return 0;
  183. case DSO_CTRL_OR_FLAGS:
  184. dso->flags |= (int)larg;
  185. return 0;
  186. default:
  187. break;
  188. }
  189. if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
  190. ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
  191. return -1;
  192. }
  193. return dso->meth->dso_ctrl(dso, cmd, larg, parg);
  194. }
  195. const char *DSO_get_filename(DSO *dso)
  196. {
  197. if (dso == NULL) {
  198. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  199. return NULL;
  200. }
  201. return dso->filename;
  202. }
  203. int DSO_set_filename(DSO *dso, const char *filename)
  204. {
  205. char *copied;
  206. if ((dso == NULL) || (filename == NULL)) {
  207. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  208. return 0;
  209. }
  210. if (dso->loaded_filename) {
  211. ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
  212. return 0;
  213. }
  214. /* We'll duplicate filename */
  215. copied = OPENSSL_strdup(filename);
  216. if (copied == NULL)
  217. return 0;
  218. OPENSSL_free(dso->filename);
  219. dso->filename = copied;
  220. return 1;
  221. }
  222. char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
  223. {
  224. char *result = NULL;
  225. if (dso == NULL || filespec1 == NULL) {
  226. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  227. return NULL;
  228. }
  229. if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
  230. if (dso->merger != NULL)
  231. result = dso->merger(dso, filespec1, filespec2);
  232. else if (dso->meth->dso_merger != NULL)
  233. result = dso->meth->dso_merger(dso, filespec1, filespec2);
  234. }
  235. return result;
  236. }
  237. char *DSO_convert_filename(DSO *dso, const char *filename)
  238. {
  239. char *result = NULL;
  240. if (dso == NULL) {
  241. ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
  242. return NULL;
  243. }
  244. if (filename == NULL)
  245. filename = dso->filename;
  246. if (filename == NULL) {
  247. ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
  248. return NULL;
  249. }
  250. if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
  251. if (dso->name_converter != NULL)
  252. result = dso->name_converter(dso, filename);
  253. else if (dso->meth->dso_name_converter != NULL)
  254. result = dso->meth->dso_name_converter(dso, filename);
  255. }
  256. if (result == NULL) {
  257. result = OPENSSL_strdup(filename);
  258. if (result == NULL)
  259. return NULL;
  260. }
  261. return result;
  262. }
  263. int DSO_pathbyaddr(void *addr, char *path, int sz)
  264. {
  265. DSO_METHOD *meth = DSO_METHOD_openssl();
  266. if (meth->pathbyaddr == NULL) {
  267. ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
  268. return -1;
  269. }
  270. return (*meth->pathbyaddr) (addr, path, sz);
  271. }
  272. DSO *DSO_dsobyaddr(void *addr, int flags)
  273. {
  274. DSO *ret = NULL;
  275. char *filename = NULL;
  276. int len = DSO_pathbyaddr(addr, NULL, 0);
  277. if (len < 0)
  278. return NULL;
  279. filename = OPENSSL_malloc(len);
  280. if (filename != NULL
  281. && DSO_pathbyaddr(addr, filename, len) == len)
  282. ret = DSO_load(NULL, filename, NULL, flags);
  283. OPENSSL_free(filename);
  284. return ret;
  285. }
  286. void *DSO_global_lookup(const char *name)
  287. {
  288. DSO_METHOD *meth = DSO_METHOD_openssl();
  289. if (meth->globallookup == NULL) {
  290. ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
  291. return NULL;
  292. }
  293. return (*meth->globallookup) (name);
  294. }