options.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /* See http://www.python-ldap.org/ for details.
  2. * $Id: options.c,v 1.38 2010/10/01 18:23:18 stroeder Exp $ */
  3. #include "common.h"
  4. #include "errors.h"
  5. #include "LDAPObject.h"
  6. #include "ldapcontrol.h"
  7. #include "options.h"
  8. void
  9. set_timeval_from_double( struct timeval *tv, double d ) {
  10. tv->tv_usec = (long) ( fmod(d, 1.0) * 1000000.0 );
  11. tv->tv_sec = (long) floor(d);
  12. }
  13. /**
  14. * Converts a return code from ldap_set_option() or ldap_get_option()
  15. * into a python error, and returns NULL.
  16. */
  17. static PyObject *
  18. option_error(int res, const char *fn)
  19. {
  20. if (res == LDAP_OPT_ERROR)
  21. PyErr_SetString(PyExc_ValueError, "option error");
  22. else if (res == LDAP_PARAM_ERROR)
  23. PyErr_SetString(PyExc_ValueError, "parameter error");
  24. else if (res == LDAP_NO_MEMORY)
  25. PyErr_NoMemory();
  26. else
  27. PyErr_Format(PyExc_SystemError, "error %d from %s", res, fn);
  28. return NULL;
  29. }
  30. /**
  31. * Sets an LDAP option.
  32. * Returns 0 on failure, 1 on success
  33. */
  34. int
  35. LDAP_set_option(LDAPObject *self, int option, PyObject *value)
  36. {
  37. int res;
  38. int intval;
  39. double doubleval;
  40. char *strval;
  41. struct timeval tv;
  42. void *ptr;
  43. LDAP *ld;
  44. LDAPControl **controls = NULL;
  45. ld = self ? self->ldap : NULL;
  46. switch(option) {
  47. case LDAP_OPT_API_INFO:
  48. case LDAP_OPT_API_FEATURE_INFO:
  49. #ifdef HAVE_SASL
  50. case LDAP_OPT_X_SASL_SSF:
  51. #endif
  52. /* Read-only options */
  53. PyErr_SetString(PyExc_ValueError, "read-only option");
  54. return 0;
  55. case LDAP_OPT_REFERRALS:
  56. case LDAP_OPT_RESTART:
  57. #ifdef LDAP_OPT_X_SASL_NOCANON
  58. case LDAP_OPT_X_SASL_NOCANON:
  59. #endif
  60. #ifdef LDAP_OPT_CONNECT_ASYNC
  61. case LDAP_OPT_CONNECT_ASYNC:
  62. #endif
  63. /* Truth-value options */
  64. ptr = PyObject_IsTrue(value) ? LDAP_OPT_ON : LDAP_OPT_OFF;
  65. break;
  66. case LDAP_OPT_DEREF:
  67. case LDAP_OPT_SIZELIMIT:
  68. case LDAP_OPT_TIMELIMIT:
  69. case LDAP_OPT_PROTOCOL_VERSION:
  70. case LDAP_OPT_ERROR_NUMBER:
  71. case LDAP_OPT_DEBUG_LEVEL:
  72. #ifdef HAVE_TLS
  73. case LDAP_OPT_X_TLS:
  74. case LDAP_OPT_X_TLS_REQUIRE_CERT:
  75. #ifdef LDAP_OPT_X_TLS_CRLCHECK
  76. case LDAP_OPT_X_TLS_CRLCHECK:
  77. #endif
  78. #ifdef LDAP_OPT_X_TLS_NEWCTX
  79. case LDAP_OPT_X_TLS_NEWCTX:
  80. #endif
  81. #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
  82. case LDAP_OPT_X_TLS_PROTOCOL_MIN:
  83. #endif
  84. #endif
  85. #ifdef HAVE_SASL
  86. case LDAP_OPT_X_SASL_SSF_MIN:
  87. case LDAP_OPT_X_SASL_SSF_MAX:
  88. #endif
  89. #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
  90. case LDAP_OPT_X_KEEPALIVE_IDLE:
  91. #endif
  92. #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
  93. case LDAP_OPT_X_KEEPALIVE_PROBES:
  94. #endif
  95. #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
  96. case LDAP_OPT_X_KEEPALIVE_INTERVAL:
  97. #endif
  98. /* integer value options */
  99. if (!PyArg_Parse(value, "i:set_option", &intval))
  100. return 0;
  101. ptr = &intval;
  102. break;
  103. case LDAP_OPT_HOST_NAME:
  104. case LDAP_OPT_URI:
  105. #ifdef LDAP_OPT_DEFBASE
  106. case LDAP_OPT_DEFBASE:
  107. #endif
  108. case LDAP_OPT_ERROR_STRING:
  109. case LDAP_OPT_MATCHED_DN:
  110. #ifdef HAVE_TLS
  111. case LDAP_OPT_X_TLS_CACERTFILE:
  112. case LDAP_OPT_X_TLS_CACERTDIR:
  113. case LDAP_OPT_X_TLS_CERTFILE:
  114. case LDAP_OPT_X_TLS_KEYFILE:
  115. case LDAP_OPT_X_TLS_CIPHER_SUITE:
  116. case LDAP_OPT_X_TLS_RANDOM_FILE:
  117. case LDAP_OPT_X_TLS_DHFILE:
  118. #ifdef LDAP_OPT_X_TLS_CRLFILE
  119. case LDAP_OPT_X_TLS_CRLFILE:
  120. #endif
  121. #endif
  122. #ifdef HAVE_SASL
  123. case LDAP_OPT_X_SASL_SECPROPS:
  124. #endif
  125. /* String valued options */
  126. if (!PyArg_Parse(value, "s:set_option", &strval))
  127. return 0;
  128. ptr = strval;
  129. break;
  130. case LDAP_OPT_TIMEOUT:
  131. case LDAP_OPT_NETWORK_TIMEOUT:
  132. /* Float valued timeval options */
  133. if (!PyArg_Parse(value, "d:set_option", &doubleval))
  134. return 0;
  135. if (doubleval >= 0) {
  136. set_timeval_from_double( &tv, doubleval );
  137. ptr = &tv;
  138. } else {
  139. ptr = NULL;
  140. }
  141. break;
  142. case LDAP_OPT_SERVER_CONTROLS:
  143. case LDAP_OPT_CLIENT_CONTROLS:
  144. if (!LDAPControls_from_object(value, &controls))
  145. return 0;
  146. ptr = controls;
  147. break;
  148. default:
  149. PyErr_Format(PyExc_ValueError, "unknown option %d", option);
  150. return 0;
  151. }
  152. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  153. res = ldap_set_option(ld, option, ptr);
  154. if (self) LDAP_END_ALLOW_THREADS(self);
  155. if ((option == LDAP_OPT_SERVER_CONTROLS) || (option == LDAP_OPT_CLIENT_CONTROLS))
  156. LDAPControl_List_DEL(controls);
  157. if (res != LDAP_OPT_SUCCESS) {
  158. option_error(res, "ldap_set_option");
  159. return 0;
  160. }
  161. return 1;
  162. }
  163. PyObject *
  164. LDAP_get_option(LDAPObject *self, int option)
  165. {
  166. int res;
  167. int intval;
  168. struct timeval *tv;
  169. LDAPAPIInfo apiinfo;
  170. LDAPControl **lcs;
  171. LDAPControl *lc;
  172. char *strval;
  173. PyObject *extensions, *v, *tup;
  174. Py_ssize_t i, num_extensions, num_controls;
  175. LDAP *ld;
  176. ld = self ? self->ldap : NULL;
  177. switch(option) {
  178. case LDAP_OPT_API_INFO:
  179. apiinfo.ldapai_info_version = LDAP_API_INFO_VERSION;
  180. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  181. res = ldap_get_option( ld, option, &apiinfo );
  182. if (self) LDAP_END_ALLOW_THREADS(self);
  183. if (res != LDAP_OPT_SUCCESS)
  184. return option_error(res, "ldap_get_option");
  185. /* put the extensions into tuple form */
  186. num_extensions = 0;
  187. while (apiinfo.ldapai_extensions[num_extensions])
  188. num_extensions++;
  189. extensions = PyTuple_New(num_extensions);
  190. for (i = 0; i < num_extensions; i++)
  191. PyTuple_SET_ITEM(extensions, i,
  192. PyString_FromString(apiinfo.ldapai_extensions[i]));
  193. /* return api info as a dictionary */
  194. v = Py_BuildValue("{s:i, s:i, s:i, s:s, s:i, s:O}",
  195. "info_version", apiinfo.ldapai_info_version,
  196. "api_version", apiinfo.ldapai_api_version,
  197. "protocol_version", apiinfo.ldapai_protocol_version,
  198. "vendor_name", apiinfo.ldapai_vendor_name,
  199. "vendor_version", apiinfo.ldapai_vendor_version,
  200. "extensions", extensions);
  201. if (apiinfo.ldapai_vendor_name)
  202. ldap_memfree(apiinfo.ldapai_vendor_name);
  203. for (i = 0; i < num_extensions; i++)
  204. ldap_memfree(apiinfo.ldapai_extensions[i]);
  205. ldap_memfree(apiinfo.ldapai_extensions);
  206. Py_DECREF(extensions);
  207. return v;
  208. #ifdef HAVE_SASL
  209. case LDAP_OPT_X_SASL_SSF:
  210. #endif
  211. case LDAP_OPT_REFERRALS:
  212. case LDAP_OPT_RESTART:
  213. case LDAP_OPT_DEREF:
  214. case LDAP_OPT_SIZELIMIT:
  215. case LDAP_OPT_TIMELIMIT:
  216. case LDAP_OPT_PROTOCOL_VERSION:
  217. case LDAP_OPT_ERROR_NUMBER:
  218. case LDAP_OPT_DEBUG_LEVEL:
  219. #ifdef HAVE_TLS
  220. case LDAP_OPT_X_TLS:
  221. case LDAP_OPT_X_TLS_REQUIRE_CERT:
  222. #ifdef LDAP_OPT_X_TLS_CRLCHECK
  223. case LDAP_OPT_X_TLS_CRLCHECK:
  224. #endif
  225. #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
  226. case LDAP_OPT_X_TLS_PROTOCOL_MIN:
  227. #endif
  228. #endif
  229. #ifdef HAVE_SASL
  230. case LDAP_OPT_X_SASL_SSF_MIN:
  231. case LDAP_OPT_X_SASL_SSF_MAX:
  232. #endif
  233. #ifdef LDAP_OPT_X_SASL_NOCANON
  234. case LDAP_OPT_X_SASL_NOCANON:
  235. #endif
  236. #ifdef LDAP_OPT_CONNECT_ASYNC
  237. case LDAP_OPT_CONNECT_ASYNC:
  238. #endif
  239. #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
  240. case LDAP_OPT_X_KEEPALIVE_IDLE:
  241. #endif
  242. #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
  243. case LDAP_OPT_X_KEEPALIVE_PROBES:
  244. #endif
  245. #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
  246. case LDAP_OPT_X_KEEPALIVE_INTERVAL:
  247. #endif
  248. /* Integer-valued options */
  249. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  250. res = ldap_get_option(ld, option, &intval);
  251. if (self) LDAP_END_ALLOW_THREADS(self);
  252. if (res != LDAP_OPT_SUCCESS)
  253. return option_error(res, "ldap_get_option");
  254. return PyInt_FromLong(intval);
  255. case LDAP_OPT_HOST_NAME:
  256. case LDAP_OPT_URI:
  257. #ifdef LDAP_OPT_DEFBASE
  258. case LDAP_OPT_DEFBASE:
  259. #endif
  260. case LDAP_OPT_ERROR_STRING:
  261. case LDAP_OPT_MATCHED_DN:
  262. #ifdef HAVE_TLS
  263. case LDAP_OPT_X_TLS_CACERTFILE:
  264. case LDAP_OPT_X_TLS_CACERTDIR:
  265. case LDAP_OPT_X_TLS_CERTFILE:
  266. case LDAP_OPT_X_TLS_KEYFILE:
  267. case LDAP_OPT_X_TLS_CIPHER_SUITE:
  268. case LDAP_OPT_X_TLS_RANDOM_FILE:
  269. case LDAP_OPT_X_TLS_DHFILE:
  270. #ifdef LDAP_OPT_X_TLS_CRLFILE
  271. case LDAP_OPT_X_TLS_CRLFILE:
  272. #endif
  273. #endif
  274. #ifdef HAVE_SASL
  275. case LDAP_OPT_X_SASL_SECPROPS:
  276. case LDAP_OPT_X_SASL_MECH:
  277. case LDAP_OPT_X_SASL_REALM:
  278. case LDAP_OPT_X_SASL_AUTHCID:
  279. case LDAP_OPT_X_SASL_AUTHZID:
  280. #ifdef LDAP_OPT_X_SASL_USERNAME
  281. case LDAP_OPT_X_SASL_USERNAME:
  282. #endif
  283. #endif
  284. /* String-valued options */
  285. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  286. res = ldap_get_option(ld, option, &strval);
  287. if (self) LDAP_END_ALLOW_THREADS(self);
  288. if (res != LDAP_OPT_SUCCESS)
  289. return option_error(res, "ldap_get_option");
  290. if (strval == NULL) {
  291. Py_INCREF(Py_None);
  292. return Py_None;
  293. }
  294. v = PyString_FromString(strval);
  295. ldap_memfree(strval);
  296. return v;
  297. case LDAP_OPT_TIMEOUT:
  298. case LDAP_OPT_NETWORK_TIMEOUT:
  299. /* Double-valued timeval options */
  300. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  301. res = ldap_get_option(ld, option, &tv);
  302. if (self) LDAP_END_ALLOW_THREADS(self);
  303. if (res != LDAP_OPT_SUCCESS)
  304. return option_error(res, "ldap_get_option");
  305. if (tv == NULL) {
  306. Py_INCREF(Py_None);
  307. return Py_None;
  308. }
  309. v = PyFloat_FromDouble(
  310. (double) tv->tv_sec + ( (double) tv->tv_usec / 1000000.0 )
  311. );
  312. ldap_memfree(tv);
  313. return v;
  314. case LDAP_OPT_SERVER_CONTROLS:
  315. case LDAP_OPT_CLIENT_CONTROLS:
  316. if (self) LDAP_BEGIN_ALLOW_THREADS(self);
  317. res = ldap_get_option(ld, option, &lcs);
  318. if (self) LDAP_END_ALLOW_THREADS(self);
  319. if (res != LDAP_OPT_SUCCESS)
  320. return option_error(res, "ldap_get_option");
  321. if (lcs == NULL)
  322. return PyList_New(0);
  323. /* Get the number of controls */
  324. num_controls = 0;
  325. while (lcs[num_controls])
  326. num_controls++;
  327. /* We'll build a list of controls, with each control a tuple */
  328. v = PyList_New(num_controls);
  329. for (i = 0; i < num_controls; i++) {
  330. lc = lcs[i];
  331. tup = Py_BuildValue("(sbs)",
  332. lc->ldctl_oid,
  333. lc->ldctl_iscritical,
  334. lc->ldctl_value.bv_val);
  335. PyList_SET_ITEM(v, i, tup);
  336. }
  337. ldap_controls_free(lcs);
  338. return v;
  339. default:
  340. PyErr_Format(PyExc_ValueError, "unknown option %d", option);
  341. return NULL;
  342. }
  343. }