plugin.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include "certmap.h" /* Public Certmap API */
  16. #include "plugin.h" /* must define extern "C" functions */
  17. CertSearchFn_t default_searchfn = 0;
  18. /* plugin_ereport -
  19. This function prints an error message to stderr. It prints the issuerDN
  20. and subjectDN alongwith the given message.
  21. */
  22. static void
  23. plugin_ereport(const char *msg, void *cert)
  24. {
  25. int rv;
  26. char *subjectDN;
  27. char *issuerDN;
  28. char *default_subjectDN = "Failed to get the subject DN";
  29. char *default_issuerDN = "Failed to get the issuer DN";
  30. rv = ldapu_get_cert_subject_dn(cert, &subjectDN);
  31. if (rv != LDAPU_SUCCESS || !subjectDN) {
  32. subjectDN = default_subjectDN;
  33. }
  34. rv = ldapu_get_cert_issuer_dn(cert, &issuerDN);
  35. if (rv != LDAPU_SUCCESS || !issuerDN) {
  36. issuerDN = default_issuerDN;
  37. }
  38. fprintf(stderr, "%s. Issuer: %s, Subject: %s\n", msg, issuerDN,
  39. subjectDN);
  40. if (default_subjectDN != subjectDN)
  41. ldapu_free(subjectDN);
  42. if (default_issuerDN != issuerDN)
  43. ldapu_free(issuerDN);
  44. }
  45. /* plugin_mapping_fn -
  46. This mapping function extracts "CN", "O" and "C" attributes from the
  47. subject DN to form ldapDN. It inserts "ou=<defaultOU>" between the
  48. "CN" and the "O" attr-value pair. The <defaultOU> can be configured in
  49. the certmap.conf config file.
  50. If the "C" attr is absent, it defaults to "US".
  51. It extracts the "E" attribute to form the filter.
  52. */
  53. int
  54. plugin_mapping_fn(void *cert, LDAP *ld, void *certmap_info, char **ldapDN, char **filter)
  55. {
  56. char **cn_val; /* get this from the cert */
  57. char **o_val; /* get this from the cert */
  58. char **c_val; /* get this from the cert */
  59. char **e_val; /* get this from the cert */
  60. char *ou_val; /* get this from the config file */
  61. int len;
  62. int rv;
  63. fprintf(stderr, "plugin_mapping_fn called.\n");
  64. rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "CN", &cn_val);
  65. if (rv != LDAPU_SUCCESS || !cn_val) {
  66. plugin_ereport("plugin_mapping_fn: Failed to extract \"CN\" from the cert", cert);
  67. return LDAPU_CERT_MAP_FUNCTION_FAILED;
  68. }
  69. rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "O", &o_val);
  70. if (rv != LDAPU_SUCCESS || !o_val) {
  71. plugin_ereport("plugin_mapping_fn: Failed to extract \"O\" from the cert", cert);
  72. return LDAPU_CERT_MAP_FUNCTION_FAILED;
  73. }
  74. rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "C", &c_val);
  75. if (rv != LDAPU_SUCCESS || !c_val) {
  76. plugin_ereport("plugin_mapping_fn: Failed to extract \"C\" from the cert", cert);
  77. }
  78. rv = ldapu_get_cert_ava_val(cert, LDAPU_SUBJECT_DN, "E", &e_val);
  79. if (rv != LDAPU_SUCCESS || !e_val) {
  80. /* Don't return error -- just print the warning */
  81. plugin_ereport("plugin_mapping_fn: Failed to extract \"E\" from the cert", cert);
  82. }
  83. /* Get the "OU" from the "defaultOU" property from the config file */
  84. rv = ldapu_certmap_info_attrval(certmap_info, "defaultOU", &ou_val);
  85. if (rv != LDAPU_SUCCESS || !ou_val) {
  86. plugin_ereport("plugin_mapping_fn: Failed to get \"defaultOU\" from the configuration", cert);
  87. return LDAPU_CERT_MAP_FUNCTION_FAILED;
  88. }
  89. len = strlen("cn=, ou=, o=, c=") + strlen(cn_val[0]) + strlen(ou_val) +
  90. strlen(o_val[0]) + (c_val ? strlen(c_val[0]) : strlen("US")) + 1;
  91. *ldapDN = (char *)ldapu_malloc(len);
  92. if (!*ldapDN) {
  93. plugin_ereport("plugin_mapping_fn: Ran out of memory", cert);
  94. return LDAPU_CERT_MAP_FUNCTION_FAILED;
  95. }
  96. if (e_val) {
  97. len = strlen("mail=") + strlen(e_val[0]) + 1;
  98. *filter = (char *)ldapu_malloc(len);
  99. if (!*filter) {
  100. free(*ldapDN);
  101. plugin_ereport("plugin_mapping_fn: Ran out of memory", cert);
  102. return LDAPU_CERT_MAP_FUNCTION_FAILED;
  103. }
  104. sprintf(*filter, "mail=%s", e_val[0]);
  105. } else {
  106. *filter = 0;
  107. }
  108. sprintf(*ldapDN, "cn=%s, ou=%s, o=%s, c=%s", cn_val[0], ou_val,
  109. o_val[0], c_val ? c_val[0] : "US");
  110. ldapu_free_cert_ava_val(cn_val);
  111. ldapu_free_cert_ava_val(o_val);
  112. ldapu_free_cert_ava_val(c_val);
  113. ldapu_free_cert_ava_val(e_val);
  114. ldapu_free(ou_val);
  115. fprintf(stderr, "plugin_mapping_fn Returned:\n\tldapDN: \"%s\"\n\tfilter: \"%s\"\n",
  116. *ldapDN, *filter ? *filter : "<NULL>");
  117. return LDAPU_SUCCESS;
  118. }
  119. int
  120. plugin_cert_serial_number(void *cert)
  121. {
  122. /* Just a stub function. You can get the DER encoded cert by using the
  123. function ldapu_get_cert_der:
  124. */
  125. unsigned char *derCert;
  126. unsigned int len;
  127. int rv;
  128. int sno;
  129. rv = ldapu_get_cert_der(cert, &derCert, &len);
  130. /* extract the serial number from derCert */
  131. sno = 43534754; /* a fake value for now */
  132. ldapu_free((char *)derCert);
  133. return sno;
  134. }
  135. /* plugin_search_fn -
  136. This function first does a search based on the cert's serial number.
  137. If that fails, it calls the default search function.
  138. */
  139. int
  140. plugin_search_fn(void *cert, LDAP *ld, void *certmap_info, const char *suffix, const char *ldapdn, const char *filter, const char **attrs, LDAPMessage **res)
  141. {
  142. int rv;
  143. char snoFilter[256];
  144. fprintf(stderr, "plugin_search_fn called.\n");
  145. sprintf(snoFilter, "certSerialNumber=%d",
  146. plugin_cert_serial_number(cert));
  147. /* Search the entire LDAP tree for "certSerialNumber=<serial No.>" */
  148. rv = ldap_search_s(ld, suffix, LDAP_SCOPE_SUBTREE, snoFilter,
  149. (char **)attrs, 0, res);
  150. /* ldap_search_s returns LDAP_SUCCESS (rather than LDAPU_SUCCESS)
  151. if there is no error but there may not be any matching entries.
  152. */
  153. if (rv == LDAP_SUCCESS) {
  154. /* There was no error but check if any entries matched */
  155. int numEntries = ldap_count_entries(ld, *res);
  156. if (numEntries > 0) {
  157. /* at least one entry matched */
  158. /* change the return value to LDAPU_SUCCESS from LDAP_SUCCESS */
  159. rv = LDAPU_SUCCESS;
  160. } else {
  161. /* Try the default search function */
  162. rv = (*default_searchfn)(cert, ld, certmap_info, suffix, ldapdn,
  163. filter, attrs, res);
  164. }
  165. }
  166. /* It's ok to return the error code from ldap_search_s */
  167. return rv;
  168. }
  169. /*
  170. plugin_verify_fn -
  171. This function returns success if only one entry exists in 'res'.
  172. */
  173. int
  174. plugin_verify_fn(void *cert, LDAP *ld, void *certmap_info, LDAPMessage *res, LDAPMessage **entry)
  175. {
  176. int rv;
  177. int numEntries;
  178. fprintf(stderr, "plugin_verify_fn called.\n");
  179. numEntries = ldap_count_entries(ld, res);
  180. if (numEntries == 1) {
  181. *entry = ldap_first_entry(ld, res);
  182. rv = LDAPU_SUCCESS;
  183. } else {
  184. plugin_ereport("plugin_verify_fn: Failing because multiple entries matched.",
  185. cert);
  186. *entry = 0;
  187. rv = LDAPU_CERT_VERIFY_FUNCTION_FAILED;
  188. }
  189. return rv;
  190. }