dso_lib.c 8.4 KB

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