certmap.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  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. /* This was malloc.h - but it's moved to stdlib.h on most platforms, and FBSD is strict */
  16. /* Make it stdlib.h, and revert to malloc.h with ifdefs if we have issues here. WB 2016 */
  17. #include <stdlib.h>
  18. /* removed for ns security integration
  19. #include <sec.h>
  20. */
  21. #include <plstr.h>
  22. #include <prlink.h>
  23. #include <prprf.h>
  24. #include <keyhi.h>
  25. #include <cert.h>
  26. #define DEFINE_LDAPU_STRINGS 1
  27. #include <ldaputil/certmap.h>
  28. #include <ldaputil/ldapauth.h>
  29. #include <ldaputil/errors.h>
  30. #include <ldaputil/ldaputil.h>
  31. #include "ldaputili.h"
  32. #ifndef BIG_LINE
  33. #define BIG_LINE 1024
  34. #endif
  35. /* This is hack, the function is defined in cert/alg1485.c */
  36. #ifdef __cplusplus
  37. extern "C" {
  38. #endif
  39. #ifdef __cplusplus
  40. }
  41. #endif
  42. static char this_dllname[256];
  43. static const char *LIB_DIRECTIVE = "certmap";
  44. static const int LIB_DIRECTIVE_LEN = 7; /* strlen("LIB_DIRECTIVE") */
  45. static void *ldapu_propval_free(void *propval_in, void *arg);
  46. typedef struct
  47. {
  48. FILE *fp;
  49. void *arg;
  50. } LDAPUPrintInfo_t;
  51. static LDAPUCertMapListInfo_t *certmap_listinfo = 0;
  52. static LDAPUCertMapInfo_t *default_certmap_info = 0;
  53. static const char *certmap_attrs[] = {
  54. 0,
  55. 0,
  56. 0,
  57. 0};
  58. const long CERTMAP_BIT_POS_UNKNOWN = 0; /* unknown OID */
  59. const long CERTMAP_BIT_POS_CN = 1L << 1; /* Common Name */
  60. const long CERTMAP_BIT_POS_OU = 1L << 2; /* Organization unit */
  61. const long CERTMAP_BIT_POS_O = 1L << 3; /* Organization */
  62. const long CERTMAP_BIT_POS_C = 1L << 4; /* Country */
  63. const long CERTMAP_BIT_POS_L = 1L << 5; /* Locality */
  64. const long CERTMAP_BIT_POS_ST = 1L << 6; /* State or Province */
  65. const long CERTMAP_BIT_POS_MAIL = 1L << 7; /* E-mail Address */
  66. const long CERTMAP_BIT_POS_UID = 1L << 8; /* UID */
  67. const long CERTMAP_BIT_POS_DC = 1L << 9; /* DC */
  68. const int SEC_OID_AVA_UNKNOWN = 0; /* unknown OID */
  69. /*
  70. * Size of escaped character to represent a dn in a filter
  71. * 1 ==> c
  72. * 3 ==> \xx
  73. */
  74. const static char value2filter_sizes[128] = {
  75. 3, 3, 3, 3, 3, 3, 3, 3,
  76. 3, 3, 3, 3, 3, 3, 3, 3,
  77. 3, 3, 3, 3, 3, 3, 3, 3,
  78. 3, 3, 3, 3, 3, 3, 3, 3,
  79. 1, 1, 1, 1, 1, 1, 1, 1,
  80. 3, 3, 3, 1, 1, 1, 1, 1, /* ( ) * */
  81. 1, 1, 1, 1, 1, 1, 1, 1,
  82. 1, 1, 1, 1, 1, 1, 1, 1,
  83. 1, 1, 1, 1, 1, 1, 1, 1,
  84. 1, 1, 1, 1, 1, 1, 1, 1,
  85. 1, 1, 1, 1, 1, 1, 1, 1,
  86. 1, 1, 1, 1, 3, 1, 1, 1, /* \ */
  87. 1, 1, 1, 1, 1, 1, 1, 1,
  88. 1, 1, 1, 1, 1, 1, 1, 1,
  89. 1, 1, 1, 1, 1, 1, 1, 1,
  90. 1, 1, 1, 1, 1, 1, 1, 3
  91. };
  92. const static char b2hex[] = "0123456789ABCDEF";
  93. static int
  94. value2filter(char *dst, size_t dstlen, const char *src, size_t srclen)
  95. {
  96. /*
  97. * Escape the dn to store it as a value in a filter
  98. * To be sure that the function is successfull caller should
  99. * ensure that dstlen >= 3*srclen+1
  100. */
  101. if (dstlen < 1) {
  102. return LDAPU_ERR_OUT_OF_MEMORY;
  103. }
  104. while (dstlen >= 2 && srclen > 0) {
  105. char c = *src++;
  106. int ecsize = (c & 0x80) ? 3 : value2filter_sizes[c & 0x7f];
  107. srclen--;
  108. dstlen -= ecsize;
  109. if (dstlen < 1) {
  110. /* Not enough space to write the final \0 */
  111. return LDAPU_ERR_OUT_OF_MEMORY;
  112. }
  113. switch ( ecsize ) {
  114. default:
  115. return LDAPU_ERR_INTERNAL;
  116. case 1:
  117. *dst++ = c;
  118. break;
  119. case 3:
  120. *dst ++ = '\\';
  121. *dst ++ = b2hex[(c >> 4) & 0xf];
  122. *dst ++ = b2hex[c & 0xf];
  123. break;
  124. }
  125. }
  126. if (srclen > 0) {
  127. return LDAPU_ERR_OUT_OF_MEMORY;
  128. }
  129. *dst = 0;
  130. return LDAPU_SUCCESS;
  131. }
  132. static long
  133. certmap_secoid_to_bit_pos(int oid)
  134. {
  135. switch (oid) {
  136. case SEC_OID_AVA_COUNTRY_NAME:
  137. return CERTMAP_BIT_POS_C;
  138. case SEC_OID_AVA_ORGANIZATION_NAME:
  139. return CERTMAP_BIT_POS_O;
  140. case SEC_OID_AVA_COMMON_NAME:
  141. return CERTMAP_BIT_POS_CN;
  142. case SEC_OID_AVA_LOCALITY:
  143. return CERTMAP_BIT_POS_L;
  144. case SEC_OID_AVA_STATE_OR_PROVINCE:
  145. return CERTMAP_BIT_POS_ST;
  146. case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
  147. return CERTMAP_BIT_POS_OU;
  148. case SEC_OID_RFC1274_UID:
  149. return CERTMAP_BIT_POS_UID;
  150. /* Map "E" and "MAIL" to the same bit position */
  151. case SEC_OID_PKCS9_EMAIL_ADDRESS:
  152. return CERTMAP_BIT_POS_MAIL;
  153. case SEC_OID_RFC1274_MAIL:
  154. return CERTMAP_BIT_POS_MAIL;
  155. case SEC_OID_AVA_DC:
  156. return CERTMAP_BIT_POS_DC;
  157. default:
  158. return CERTMAP_BIT_POS_UNKNOWN;
  159. }
  160. }
  161. static const char *
  162. certmap_secoid_to_name(int oid)
  163. {
  164. switch (oid) {
  165. case SEC_OID_AVA_COUNTRY_NAME:
  166. return "C";
  167. case SEC_OID_AVA_ORGANIZATION_NAME:
  168. return "O";
  169. case SEC_OID_AVA_COMMON_NAME:
  170. return "CN";
  171. case SEC_OID_AVA_LOCALITY:
  172. return "L";
  173. case SEC_OID_AVA_STATE_OR_PROVINCE:
  174. return "ST";
  175. case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
  176. return "OU";
  177. case SEC_OID_RFC1274_UID:
  178. return "UID";
  179. /* Map both 'e' and 'mail' to 'mail' in LDAP */
  180. case SEC_OID_PKCS9_EMAIL_ADDRESS:
  181. return "MAIL";
  182. case SEC_OID_RFC1274_MAIL:
  183. return "MAIL";
  184. case SEC_OID_AVA_DC:
  185. return "DC";
  186. default:
  187. return 0;
  188. }
  189. }
  190. static void
  191. tolower_string(char *str)
  192. {
  193. if (str) {
  194. while (*str) {
  195. *str = tolower(*str);
  196. str++;
  197. }
  198. }
  199. }
  200. static long
  201. certmap_name_to_bit_pos(const char *str)
  202. {
  203. if (!ldapu_strcasecmp(str, "c"))
  204. return CERTMAP_BIT_POS_C;
  205. if (!ldapu_strcasecmp(str, "o"))
  206. return CERTMAP_BIT_POS_O;
  207. if (!ldapu_strcasecmp(str, "cn"))
  208. return CERTMAP_BIT_POS_CN;
  209. if (!ldapu_strcasecmp(str, "l"))
  210. return CERTMAP_BIT_POS_L;
  211. if (!ldapu_strcasecmp(str, "st"))
  212. return CERTMAP_BIT_POS_ST;
  213. if (!ldapu_strcasecmp(str, "ou"))
  214. return CERTMAP_BIT_POS_OU;
  215. if (!ldapu_strcasecmp(str, "uid"))
  216. return CERTMAP_BIT_POS_UID;
  217. /* Map "E" and "MAIL" to the same bit position */
  218. if (!ldapu_strcasecmp(str, "e"))
  219. return CERTMAP_BIT_POS_MAIL;
  220. if (!ldapu_strcasecmp(str, "mail"))
  221. return CERTMAP_BIT_POS_MAIL;
  222. if (!ldapu_strcasecmp(str, "dc"))
  223. return CERTMAP_BIT_POS_DC;
  224. return CERTMAP_BIT_POS_UNKNOWN;
  225. }
  226. #if 0 /* may need this in the future */
  227. static int certmap_name_to_secoid (const char *str)
  228. {
  229. if (!ldapu_strcasecmp(str, "c")) return SEC_OID_AVA_COUNTRY_NAME;
  230. if (!ldapu_strcasecmp(str, "o")) return SEC_OID_AVA_ORGANIZATION_NAME;
  231. if (!ldapu_strcasecmp(str, "cn")) return SEC_OID_AVA_COMMON_NAME;
  232. if (!ldapu_strcasecmp(str, "l")) return SEC_OID_AVA_LOCALITY;
  233. if (!ldapu_strcasecmp(str, "st")) return SEC_OID_AVA_STATE_OR_PROVINCE;
  234. if (!ldapu_strcasecmp(str, "ou")) return SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME;
  235. if (!ldapu_strcasecmp(str, "uid")) return SEC_OID_RFC1274_UID;
  236. if (!ldapu_strcasecmp(str, "e")) return SEC_OID_PKCS9_EMAIL_ADDRESS;
  237. if (!ldapu_strcasecmp(str, "mail")) return SEC_OID_RFC1274_MAIL;
  238. if (!ldapu_strcasecmp(str, "dc")) return SEC_OID_AVA_DC;
  239. return SEC_OID_AVA_UNKNOWN; /* return invalid OID */
  240. }
  241. #endif
  242. NSAPI_PUBLIC int
  243. ldapu_list_alloc(LDAPUList_t **list)
  244. {
  245. *list = (LDAPUList_t *)calloc(1, sizeof(LDAPUList_t));
  246. if (!*list)
  247. return LDAPU_ERR_OUT_OF_MEMORY;
  248. return LDAPU_SUCCESS;
  249. }
  250. static int
  251. ldapu_list_add_node(LDAPUList_t *list, LDAPUListNode_t *node)
  252. {
  253. if (list->head) {
  254. node->prev = list->tail;
  255. list->tail->next = node;
  256. } else {
  257. node->prev = 0;
  258. list->head = node;
  259. }
  260. node->next = 0;
  261. list->tail = node;
  262. return LDAPU_SUCCESS;
  263. }
  264. NSAPI_PUBLIC int
  265. ldapu_list_add_info(LDAPUList_t *list, void *info)
  266. {
  267. LDAPUListNode_t *node;
  268. /* Allocate the list node and set info in the node. */
  269. node = (LDAPUListNode_t *)calloc(1, sizeof(LDAPUListNode_t));
  270. if (!node) {
  271. return LDAPU_ERR_OUT_OF_MEMORY;
  272. }
  273. node->info = info;
  274. return ldapu_list_add_node(list, node);
  275. }
  276. static void
  277. ldapu_list_free(LDAPUList_t *list, LDAPUListNodeFn_t free_fn)
  278. {
  279. if (list) {
  280. auto LDAPUListNode_t *node = list->head;
  281. while (node) {
  282. auto LDAPUListNode_t *next = node->next;
  283. if (free_fn) {
  284. (*free_fn)(node->info, 0);
  285. node->info = 0;
  286. }
  287. node->info = 0;
  288. free(node);
  289. node = next;
  290. }
  291. list->head = 0;
  292. list->tail = 0;
  293. }
  294. return;
  295. }
  296. NSAPI_PUBLIC int
  297. ldapu_propval_alloc(const char *prop, const char *val, LDAPUPropVal_t **propval)
  298. {
  299. *propval = (LDAPUPropVal_t *)malloc(sizeof(LDAPUPropVal_t));
  300. if (!*propval)
  301. return LDAPU_ERR_OUT_OF_MEMORY;
  302. (*propval)->prop = prop ? strdup(prop) : 0;
  303. (*propval)->val = val ? strdup(val) : 0;
  304. if ((!prop || (*propval)->prop) && (!val || (*propval)->val)) {
  305. /* strdup worked */
  306. return LDAPU_SUCCESS;
  307. } else {
  308. return LDAPU_ERR_OUT_OF_MEMORY;
  309. }
  310. }
  311. static int
  312. PresentInComps(long comps_bitmask, int tag)
  313. {
  314. long bit = certmap_secoid_to_bit_pos(tag);
  315. if (comps_bitmask & bit)
  316. return 1;
  317. else
  318. return 0;
  319. }
  320. static int
  321. dbconf_to_certmap_err(int err)
  322. {
  323. switch (err) {
  324. case LDAPU_ERR_DBNAME_IS_MISSING:
  325. return LDAPU_ERR_CANAME_IS_MISSING;
  326. case LDAPU_ERR_PROP_IS_MISSING:
  327. return LDAPU_ERR_CAPROP_IS_MISSING;
  328. default:
  329. return err;
  330. }
  331. }
  332. /* CAUTION: this function hijacks some substructures from db_info and make
  333. * the pointers to it NULL in the db_info. It is safe to deallocate db_info.
  334. */
  335. static int
  336. dbinfo_to_certinfo(DBConfDBInfo_t *db_info,
  337. LDAPUCertMapInfo_t **certinfo_out)
  338. {
  339. LDAPUCertMapInfo_t *certinfo = NULL;
  340. LDAPUPropValList_t *propval_list = NULL;
  341. int rv = LDAPU_SUCCESS;
  342. *certinfo_out = 0;
  343. certinfo = (LDAPUCertMapInfo_t *)calloc(1, sizeof(LDAPUCertMapInfo_t));
  344. if (!certinfo) {
  345. rv = LDAPU_ERR_OUT_OF_MEMORY;
  346. goto error;
  347. }
  348. /* hijack few structures rather then copy. Make the pointers to the
  349. structures NULL in the original structure so that they don't freed up
  350. when db_info is freed. */
  351. certinfo->issuerName = db_info->dbname;
  352. db_info->dbname = 0;
  353. /* Parse the Issuer DN. */
  354. certinfo->issuerDN = CERT_AsciiToName(db_info->url);
  355. if (NULL == certinfo->issuerDN /* invalid DN */
  356. && ldapu_strcasecmp(db_info->url, "default") != 0 /* not "default" */) {
  357. rv = LDAPU_ERR_MALFORMED_SUBJECT_DN;
  358. goto error;
  359. }
  360. /* hijack actual prop-vals from dbinfo -- to avoid strdup calls */
  361. if (db_info->firstprop) {
  362. LDAPUPropVal_t *propval;
  363. DBPropVal_t *dbpropval;
  364. dbpropval = db_info->firstprop;
  365. rv = ldapu_list_alloc(&propval_list);
  366. if (rv != LDAPU_SUCCESS) {
  367. goto error;
  368. }
  369. while (dbpropval) {
  370. propval = (LDAPUPropVal_t *)malloc(sizeof(LDAPUPropVal_t));
  371. if (!propval) {
  372. rv = LDAPU_ERR_OUT_OF_MEMORY;
  373. goto error;
  374. }
  375. propval->prop = dbpropval->prop;
  376. dbpropval->prop = 0;
  377. propval->val = dbpropval->val;
  378. dbpropval->val = 0;
  379. rv = ldapu_list_add_info(propval_list, propval);
  380. if (rv != LDAPU_SUCCESS) {
  381. ldapu_propval_free((void *)propval, (void *)propval);
  382. goto error;
  383. }
  384. dbpropval = dbpropval->next;
  385. }
  386. certinfo->propval = propval_list;
  387. }
  388. *certinfo_out = certinfo;
  389. goto done;
  390. error:
  391. if (propval_list)
  392. ldapu_propval_list_free(propval_list);
  393. if (certinfo)
  394. free(certinfo);
  395. done:
  396. return rv;
  397. }
  398. static int
  399. ldapu_binary_cmp_certs(void *subject_cert,
  400. void *entry_cert_binary,
  401. unsigned long entry_cert_len)
  402. {
  403. SECItem derCert = ((CERTCertificate *)subject_cert)->derCert;
  404. int rv;
  405. /* binary compare the two certs */
  406. if (derCert.len == entry_cert_len &&
  407. !memcmp(derCert.data, entry_cert_binary, entry_cert_len)) {
  408. rv = LDAPU_SUCCESS;
  409. } else {
  410. rv = LDAPU_ERR_CERT_VERIFY_FAILED;
  411. }
  412. return rv;
  413. }
  414. static int
  415. ldapu_cert_verifyfn_default(void *subject_cert, LDAP *ld, void *certmap_info __attribute__((unused)), LDAPMessage *res, LDAPMessage **entry_out)
  416. {
  417. LDAPMessage *entry;
  418. struct berval **bvals;
  419. int i;
  420. int rv = LDAPU_ERR_CERT_VERIFY_FAILED;
  421. char *cert_attr = ldapu_strings[LDAPU_STR_ATTR_CERT];
  422. char *cert_attr_nosubtype = ldapu_strings[LDAPU_STR_ATTR_CERT_NOSUBTYPE];
  423. *entry_out = 0;
  424. for (entry = ldapu_first_entry(ld, res); entry != NULL;
  425. entry = ldapu_next_entry(ld, entry)) {
  426. if (((bvals = ldapu_get_values_len(ld, entry, cert_attr)) == NULL) &&
  427. ((bvals = ldapu_get_values_len(ld, entry, cert_attr_nosubtype)) == NULL)) {
  428. rv = LDAPU_ERR_CERT_VERIFY_NO_CERTS;
  429. continue;
  430. }
  431. for (i = 0; bvals[i] != NULL; i++) {
  432. rv = ldapu_binary_cmp_certs(subject_cert,
  433. bvals[i]->bv_val,
  434. bvals[i]->bv_len);
  435. if (rv == LDAPU_SUCCESS) {
  436. break;
  437. }
  438. }
  439. ldapu_value_free_len(ld, bvals);
  440. if (rv == LDAPU_SUCCESS) {
  441. *entry_out = entry;
  442. break;
  443. }
  444. }
  445. return rv;
  446. }
  447. static int
  448. parse_into_bitmask(const char *comps_in, long *bitmask_out, long default_val)
  449. {
  450. long bitmask = default_val;
  451. char *comps = comps_in ? strdup(comps_in) : 0;
  452. if (!comps) {
  453. /* Not present in the config file */
  454. bitmask = default_val;
  455. } else if (!*comps) {
  456. /* present but empty */
  457. bitmask = 0;
  458. } else {
  459. char *delim = " \t\r\n,";
  460. char *saveptr = NULL;
  461. for (char *name = strtok_r(comps, delim, &saveptr);
  462. name!=NULL; name = strtok_r(NULL, delim, &saveptr)) {
  463. long bit = certmap_name_to_bit_pos(name);
  464. bitmask |= bit;
  465. }
  466. }
  467. if (comps)
  468. free(comps);
  469. *bitmask_out = bitmask;
  470. /* print_oid_bitmask(bitmask); */
  471. return LDAPU_SUCCESS;
  472. }
  473. static int
  474. process_certinfo(LDAPUCertMapInfo_t *certinfo)
  475. {
  476. int rv = LDAPU_SUCCESS;
  477. char *dncomps = 0;
  478. char *filtercomps = 0;
  479. char *libname = 0;
  480. char *verify = 0;
  481. char *fname = 0;
  482. char *searchAttr = 0;
  483. if (!ldapu_strcasecmp(certinfo->issuerName, "default")) {
  484. default_certmap_info = certinfo;
  485. } else if (!certinfo->issuerDN) {
  486. return LDAPU_ERR_NO_ISSUERDN_IN_CONFIG_FILE;
  487. } else {
  488. rv = ldapu_list_add_info(certmap_listinfo, certinfo);
  489. }
  490. if (rv != LDAPU_SUCCESS)
  491. return rv;
  492. /* look for dncomps property and parse it into the dncomps bitmask */
  493. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_DNCOMPS, &dncomps);
  494. if (rv == LDAPU_SUCCESS && dncomps) {
  495. certinfo->dncompsState = COMPS_HAS_ATTRS;
  496. tolower_string(dncomps);
  497. } else if (rv == LDAPU_FAILED) {
  498. certinfo->dncompsState = COMPS_COMMENTED_OUT;
  499. rv = LDAPU_SUCCESS;
  500. } else if (rv == LDAPU_SUCCESS && !dncomps) {
  501. certinfo->dncompsState = COMPS_EMPTY;
  502. dncomps = strdup(""); /* present but empty */
  503. }
  504. rv = parse_into_bitmask(dncomps, &certinfo->dncomps, -1);
  505. free(dncomps);
  506. dncomps = NULL;
  507. if (rv != LDAPU_SUCCESS)
  508. return rv;
  509. /* look for filtercomps property and parse it into the filtercomps bitmask */
  510. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_FILTERCOMPS,
  511. &filtercomps);
  512. if (rv == LDAPU_SUCCESS && filtercomps) {
  513. certinfo->filtercompsState = COMPS_HAS_ATTRS;
  514. tolower_string(filtercomps);
  515. } else if (rv == LDAPU_FAILED) {
  516. certinfo->filtercompsState = COMPS_COMMENTED_OUT;
  517. rv = LDAPU_SUCCESS;
  518. } else if (rv == LDAPU_SUCCESS && !filtercomps) {
  519. certinfo->filtercompsState = COMPS_EMPTY;
  520. filtercomps = strdup(""); /* present but empty */
  521. }
  522. rv = parse_into_bitmask(filtercomps, &certinfo->filtercomps, 0);
  523. free(filtercomps);
  524. filtercomps = NULL;
  525. if (rv != LDAPU_SUCCESS)
  526. return rv;
  527. /* look for "CmapLdapAttr" property and store it into searchAttr */
  528. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_CERTMAP_LDAP_ATTR,
  529. &searchAttr);
  530. if (rv == LDAPU_FAILED || !searchAttr) {
  531. rv = LDAPU_SUCCESS;
  532. } else {
  533. certinfo->searchAttr = searchAttr;
  534. if (searchAttr && !certinfo->searchAttr)
  535. rv = LDAPU_ERR_OUT_OF_MEMORY;
  536. else
  537. rv = LDAPU_SUCCESS;
  538. }
  539. if (rv != LDAPU_SUCCESS)
  540. return rv;
  541. /* look for verifycert property and set the default verify function */
  542. /* The value of the verifycert property is ignored */
  543. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_VERIFYCERT, &verify);
  544. if (rv == LDAPU_SUCCESS) {
  545. if (!ldapu_strcasecmp(verify, "on"))
  546. certinfo->verifyCert = 1;
  547. else if (!ldapu_strcasecmp(verify, "off"))
  548. certinfo->verifyCert = 0;
  549. else if (!verify || !*verify) /* for mail/news backward compatibilty */
  550. certinfo->verifyCert = 1; /* otherwise, this should be an error */
  551. else
  552. rv = LDAPU_ERR_MISSING_VERIFYCERT_VAL;
  553. } else if (rv == LDAPU_FAILED)
  554. rv = LDAPU_SUCCESS;
  555. if (verify)
  556. free(verify);
  557. if (rv != LDAPU_SUCCESS)
  558. return rv;
  559. {
  560. PRLibrary *lib = 0;
  561. /* look for the library property and load it */
  562. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_LIBRARY, &libname);
  563. if (rv == LDAPU_SUCCESS) {
  564. if (libname && *libname) {
  565. lib = PR_LoadLibrary(libname);
  566. if (!lib)
  567. rv = LDAPU_ERR_UNABLE_TO_LOAD_PLUGIN;
  568. } else {
  569. rv = LDAPU_ERR_MISSING_LIBNAME;
  570. }
  571. } else if (rv == LDAPU_FAILED)
  572. rv = LDAPU_SUCCESS;
  573. if (libname)
  574. free(libname);
  575. if (rv != LDAPU_SUCCESS)
  576. return rv;
  577. /* look for the InitFn property, find it in the libray and call it */
  578. rv = ldapu_certmap_info_attrval(certinfo, LDAPU_ATTR_INITFN, &fname);
  579. if (rv == LDAPU_SUCCESS) {
  580. if (fname && *fname) {
  581. /* If lib is NULL, PR_FindSymbol will search all libs loaded
  582. * through PR_LoadLibrary.
  583. */
  584. CertMapInitFn_t fn = (CertMapInitFn_t)PR_FindSymbol(lib, fname);
  585. if (!fn) {
  586. rv = LDAPU_ERR_MISSING_INIT_FN_IN_LIB;
  587. } else {
  588. rv = (*fn)(certinfo, certinfo->issuerName,
  589. certinfo->issuerDN, this_dllname);
  590. }
  591. } else {
  592. rv = LDAPU_ERR_MISSING_INIT_FN_NAME;
  593. }
  594. } else if (lib) {
  595. /* If library is specified, init function must be specified */
  596. /* If init fn is specified, library may not be specified */
  597. rv = LDAPU_ERR_MISSING_INIT_FN_IN_CONFIG;
  598. } else if (rv == LDAPU_FAILED) {
  599. rv = LDAPU_SUCCESS;
  600. }
  601. if (fname)
  602. free(fname);
  603. if (rv != LDAPU_SUCCESS)
  604. return rv;
  605. }
  606. return rv;
  607. }
  608. /* This function will read multiple certmap directives and set the information
  609. * in the global certmap_listinfo structure.
  610. */
  611. int
  612. certmap_read_certconfig_file(const char *file)
  613. {
  614. DBConfInfo_t *conf_info = 0;
  615. int rv;
  616. /* Read the config file */
  617. rv = dbconf_read_config_file_sub(file, LIB_DIRECTIVE, LIB_DIRECTIVE_LEN,
  618. &conf_info);
  619. /* Convert the conf_info into certmap_listinfo. Some of the
  620. * sub-structures are simply hijacked rather than copied since we are
  621. * going to (carefully) free the conf_info anyway.
  622. */
  623. if (rv == LDAPU_SUCCESS && conf_info) {
  624. DBConfDBInfo_t *nextdb;
  625. DBConfDBInfo_t *curdb;
  626. LDAPUCertMapInfo_t *certinfo;
  627. curdb = conf_info->firstdb;
  628. while (curdb) {
  629. nextdb = curdb->next;
  630. rv = dbinfo_to_certinfo(curdb, &certinfo);
  631. if (rv != LDAPU_SUCCESS) {
  632. dbconf_free_confinfo(conf_info);
  633. return rv;
  634. }
  635. rv = process_certinfo(certinfo);
  636. if (rv != LDAPU_SUCCESS) {
  637. ldapu_certinfo_free(certinfo);
  638. dbconf_free_confinfo(conf_info);
  639. return rv;
  640. }
  641. curdb = nextdb;
  642. }
  643. dbconf_free_confinfo(conf_info);
  644. } else {
  645. rv = dbconf_to_certmap_err(rv);
  646. }
  647. return rv;
  648. }
  649. /* This function will read the "certmap default" directive from the config
  650. * file and set the information in the global certmap_info.
  651. */
  652. int
  653. certmap_read_default_certinfo(const char *file)
  654. {
  655. DBConfDBInfo_t *db_info = 0;
  656. int rv;
  657. rv = dbconf_read_default_dbinfo_sub(file, LIB_DIRECTIVE, LIB_DIRECTIVE_LEN,
  658. &db_info);
  659. if (rv != LDAPU_SUCCESS)
  660. return rv;
  661. rv = dbinfo_to_certinfo(db_info, &default_certmap_info);
  662. dbconf_free_dbinfo(db_info);
  663. return rv;
  664. }
  665. static int
  666. ldapu_cert_searchfn_default(void *cert, LDAP *ld, void *certmap_info_in, const char *basedn, const char *dn, const char *filter, const char **attrs, LDAPMessage ***res)
  667. {
  668. int rv = LDAPU_FAILED;
  669. const char *ldapdn;
  670. LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;
  671. LDAPMessage *single_res = NULL;
  672. LDAPMessage **multiple_res = NULL;
  673. if (certmap_info && certmap_info->searchAttr) {
  674. char *subjectDN = 0;
  675. rv = ldapu_get_cert_subject_dn(cert, &subjectDN);
  676. if (rv != LDAPU_SUCCESS || !subjectDN) {
  677. return rv;
  678. }
  679. size_t subjectDN_len = strlen(subjectDN);
  680. size_t eqout_len = 3 * subjectDN_len + 1; /* big enough for worst case (and final \0) */
  681. size_t searchAttr_len = strlen(certmap_info->searchAttr);
  682. size_t len = searchAttr_len + 1 + eqout_len;
  683. char *certFilter = (char *)ldapu_malloc(len * sizeof(char));
  684. if (!certFilter) {
  685. free(subjectDN);
  686. return LDAPU_ERR_OUT_OF_MEMORY;
  687. }
  688. strcpy(certFilter, certmap_info->searchAttr);
  689. certFilter[searchAttr_len] = '=';
  690. rv = value2filter(certFilter+searchAttr_len+1, eqout_len, subjectDN, subjectDN_len);
  691. free(subjectDN);
  692. len = strlen(certFilter);
  693. if (rv != LDAPU_SUCCESS || len <= 0) {
  694. ldapu_free((void *)certFilter);
  695. return LDAPU_ERR_INVALID_ARGUMENT;
  696. }
  697. if (ldapu_strcasecmp(basedn, "")) {
  698. rv = ldapu_find(ld, basedn, LDAP_SCOPE_SUBTREE, certFilter, attrs, 0, &single_res);
  699. ldapu_free((void *)certFilter);
  700. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  701. *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));
  702. (*res)[0] = single_res;
  703. (*res)[1] = NULL;
  704. return rv;
  705. } else if (single_res) {
  706. ldapu_msgfree(ld, single_res);
  707. single_res = 0;
  708. }
  709. } else {
  710. rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, certFilter, attrs, 0, &multiple_res);
  711. ldapu_free((void *)certFilter);
  712. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  713. *res = multiple_res;
  714. return rv;
  715. } else if (multiple_res) {
  716. int n;
  717. for (n = 0; multiple_res[n] != NULL; n++)
  718. ldapu_msgfree(ld, multiple_res[n]);
  719. ldapu_memfree(ld, multiple_res);
  720. }
  721. }
  722. }
  723. if (dn && *dn) {
  724. /* First do the base level search --- NOT ANY MORE!! */
  725. /* We actually do the search on the whole subtree hanging from "ldapdn" since we want to
  726. * find all the entries that match the filter.
  727. * If we get more than one matching entry in return, it'll be at verify time that we'll
  728. * choose the correct one among them all.
  729. * However, if certificate verify is not active, certificate mapping will fail and will
  730. * consequently display an error message (something done at 'handle_handshake_done' level,
  731. * for instance). */
  732. ldapdn = dn;
  733. if (ldapu_strcasecmp(ldapdn, "")) {
  734. rv = ldapu_find(ld, ldapdn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &single_res);
  735. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  736. *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));
  737. (*res)[0] = single_res;
  738. (*res)[1] = NULL;
  739. return rv;
  740. } else if (single_res) {
  741. ldapu_msgfree(ld, single_res);
  742. single_res = 0;
  743. }
  744. } else {
  745. rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &multiple_res);
  746. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  747. *res = multiple_res;
  748. return rv;
  749. } else if (multiple_res) {
  750. int n;
  751. for (n = 0; multiple_res[n] != NULL; n++)
  752. ldapu_msgfree(ld, multiple_res[n]);
  753. ldapu_memfree(ld, multiple_res);
  754. }
  755. }
  756. } else {
  757. /* default the dn and filter for subtree search */
  758. ldapdn = basedn;
  759. if (!filter || !*filter) {
  760. if (certmap_info && certmap_info->searchAttr) {
  761. /* dn & filter returned by the mapping function are both NULL
  762. and 'searchAttr' based search has failed. Don't do brute
  763. force search if 'searchAttr' is being used. Otherwise,
  764. this search will result in all LDAP entries being
  765. returned.
  766. */
  767. } else {
  768. filter = "objectclass=*";
  769. }
  770. }
  771. }
  772. /* For local LDAP DB, the LDAP_SCOPE_BASE search may fail for dn == basedn
  773. * since that object doesn't actually exists.
  774. */
  775. if ((rv == LDAPU_FAILED || rv == LDAP_NO_SUCH_OBJECT) && filter && (!dn || !*dn)) {
  776. /* Try the subtree search only if the filter is non-NULL */
  777. if (ldapu_strcasecmp(ldapdn, "")) {
  778. rv = ldapu_find(ld, ldapdn, LDAP_SCOPE_SUBTREE, filter, 0, 0, &single_res);
  779. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  780. *res = (LDAPMessage **)ldapu_malloc(2 * sizeof(LDAPMessage *));
  781. (*res)[0] = single_res;
  782. (*res)[1] = NULL;
  783. return rv;
  784. } else if (single_res) {
  785. ldapu_msgfree(ld, single_res);
  786. single_res = 0;
  787. }
  788. } else {
  789. rv = ldapu_find_entire_tree(ld, LDAP_SCOPE_SUBTREE, filter, 0, 0, &multiple_res);
  790. if (rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  791. *res = multiple_res;
  792. return rv;
  793. } else if (multiple_res) {
  794. int n;
  795. for (n = 0; multiple_res[n] != NULL; n++)
  796. ldapu_msgfree(ld, multiple_res[n]);
  797. ldapu_memfree(ld, multiple_res);
  798. }
  799. }
  800. }
  801. if (rv == LDAPU_FAILED) {
  802. /* Not an error but couldn't map the cert */
  803. rv = LDAPU_ERR_MAPPED_ENTRY_NOT_FOUND;
  804. } else if ((!dn || !*dn) && (rv == LDAP_NO_SUCH_OBJECT)) {
  805. rv = LDAPU_ERR_INVALID_SUFFIX;
  806. }
  807. return rv;
  808. }
  809. NSAPI_PUBLIC int
  810. ldapu_issuer_certinfo(const CERTName *issuerDN, void **certmap_info)
  811. {
  812. *certmap_info = 0;
  813. if (certmap_listinfo) {
  814. LDAPUListNode_t *cur = certmap_listinfo->head;
  815. while (cur) {
  816. LDAPUCertMapInfo_t *info = (LDAPUCertMapInfo_t *)cur->info;
  817. if (NULL == info->issuerDN) {
  818. /* no DN to compare to (probably the default certmap info) */
  819. cur = cur->next;
  820. continue;
  821. }
  822. if (CERT_CompareName(issuerDN, info->issuerDN) == SECEqual) {
  823. *certmap_info = cur->info;
  824. break;
  825. }
  826. cur = cur->next;
  827. }
  828. }
  829. return *certmap_info ? LDAPU_SUCCESS : LDAPU_FAILED;
  830. }
  831. NSAPI_PUBLIC int
  832. ldapu_certmap_info_attrval(void *certmap_info_in,
  833. const char *attr,
  834. char **val)
  835. {
  836. /* Look for given attr in the certmap_info and return its value */
  837. LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;
  838. LDAPUListNode_t *curprop = certmap_info->propval ? certmap_info->propval->head : 0;
  839. LDAPUPropVal_t *propval;
  840. int rv = LDAPU_FAILED;
  841. *val = 0;
  842. while (curprop) {
  843. propval = (LDAPUPropVal_t *)curprop->info;
  844. if (!ldapu_strcasecmp(propval->prop, attr)) {
  845. *val = propval->val ? strdup(propval->val) : 0;
  846. rv = LDAPU_SUCCESS;
  847. break;
  848. }
  849. curprop = curprop->next;
  850. }
  851. return rv;
  852. }
  853. static int
  854. AddAVAToBuf(char *buf, int size, int *len, const char *tagName, CERTAVA *ava, int is_filter)
  855. {
  856. int lenLen;
  857. int taglen;
  858. SECStatus rv;
  859. int available_space;
  860. /* Check if we're already at the buffer limit */
  861. if (*len >= size) {
  862. return LDAPU_FAILED;
  863. }
  864. buf += *len;
  865. available_space = size - *len;
  866. /* Copied from ns/lib/libsec ...
  867. * XXX this code is incorrect in general
  868. * -- should use a DER template.
  869. */
  870. lenLen = 2;
  871. if (ava->value.len >= 128)
  872. lenLen = 3;
  873. taglen = PL_strlen(tagName);
  874. /* Check if there's enough space for tagName and '=' */
  875. if (taglen + 1 > available_space) {
  876. return LDAPU_FAILED;
  877. }
  878. memcpy(buf, tagName, taglen);
  879. buf[taglen++] = '=';
  880. if (is_filter != 0) {
  881. /* values should not be quoted in filter but * must be escaped */
  882. rv = value2filter(buf + taglen,
  883. available_space - taglen,
  884. (char *)ava->value.data + lenLen,
  885. ava->value.len - lenLen);
  886. *len += strlen(buf);
  887. return rv;
  888. } else {
  889. rv = CERT_RFC1485_EscapeAndQuote(buf + taglen,
  890. available_space - taglen,
  891. (char *)ava->value.data + lenLen,
  892. ava->value.len - lenLen);
  893. *len += strlen(buf);
  894. return (rv == SECSuccess ? LDAPU_SUCCESS : LDAPU_FAILED);
  895. } }
  896. static int
  897. AddToLdapDN(char *ldapdn, int size, int *dnlen, const char *tagName, CERTAVA *ava)
  898. {
  899. char *dn = ldapdn + *dnlen;
  900. if (*dnlen) {
  901. /* Check if there's enough space for ", " */
  902. if (*dnlen + 2 >= size) {
  903. return LDAPU_FAILED;
  904. }
  905. strcat(dn, ", ");
  906. dn += 2;
  907. *dnlen += 2;
  908. }
  909. return AddAVAToBuf(ldapdn, size, dnlen, tagName, ava, 0);
  910. }
  911. static int
  912. AddToFilter(char *filter, int size, int *flen, const char *tagName, CERTAVA *ava)
  913. {
  914. int rv;
  915. /* Check if there's enough space for " (" */
  916. if (*flen + 2 >= size) {
  917. return LDAPU_FAILED;
  918. }
  919. /* Append opening parenthesis */
  920. strcat(filter + *flen, " (");
  921. *flen += 2;
  922. rv = AddAVAToBuf(filter, size, flen, tagName, ava, 1);
  923. if (rv != LDAPU_SUCCESS)
  924. return rv;
  925. /* Check if there's enough space for ")" */
  926. if (*flen + 1 >= size) {
  927. return LDAPU_FAILED;
  928. }
  929. /* Append closing parenthesis */
  930. strcat(filter + *flen, ")");
  931. (*flen)++;
  932. return rv;
  933. }
  934. NSAPI_PUBLIC int
  935. ldapu_free_cert_ava_val(char **val)
  936. {
  937. char **ptr = val;
  938. if (!val)
  939. return LDAPU_SUCCESS;
  940. while (*ptr)
  941. free(*ptr++);
  942. free(val);
  943. return LDAPU_SUCCESS;
  944. }
  945. static int
  946. ldapu_cert_mapfn_default(void *cert_in, LDAP *ld __attribute__((unused)), void *certmap_info_in, char **ldapDN_out, char **filter_out)
  947. {
  948. CERTCertificate *cert = (CERTCertificate *)cert_in;
  949. LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)certmap_info_in;
  950. int rv = LDAPU_SUCCESS;
  951. *ldapDN_out = *filter_out = 0;
  952. if (!certmap_info) {
  953. /* Use subject DN as is -- identity mapping function */
  954. rv = ldapu_get_cert_subject_dn(cert, ldapDN_out);
  955. return rv;
  956. } else {
  957. /*
  958. * Iterate over rdns from the subject and collect AVAs depending on
  959. * dnComps and filtercomps to form ldapDN and filter respectively.
  960. * certmap_info->dncomps
  961. */
  962. CERTName *subject = &cert->subject;
  963. CERTRDN **rdns = subject->rdns;
  964. CERTRDN **lastRdn;
  965. CERTRDN **rdn;
  966. CERTAVA **avas;
  967. CERTAVA *ava;
  968. char ldapdn[BIG_LINE];
  969. char filter[BIG_LINE];
  970. int dnlen = 0; /* ldap DN length */
  971. int flen = 0; /* filter length */
  972. int numfavas = 0; /* no of avas added to filter */
  973. if (rdns == NULL) {
  974. /* error */
  975. return LDAPU_ERR_INTERNAL;
  976. }
  977. /* find last RDN */
  978. lastRdn = rdns;
  979. while (*lastRdn)
  980. lastRdn++;
  981. lastRdn--;
  982. /* Initialize filter to "(&" */
  983. strcpy(filter, "(&");
  984. flen = 2;
  985. /*
  986. * Loop over subject rdns in the _reverse_ order while forming ldapDN
  987. * and filter.
  988. */
  989. for (rdn = lastRdn; rdn >= rdns; rdn--) {
  990. avas = (*rdn)->avas;
  991. while ((ava = *avas++) != NULL) {
  992. int tag = CERT_GetAVATag(ava);
  993. const char *tagName = certmap_secoid_to_name(tag);
  994. if (PresentInComps(certmap_info->dncomps, tag)) {
  995. rv = AddToLdapDN(ldapdn, BIG_LINE, &dnlen, tagName, ava);
  996. if (rv != LDAPU_SUCCESS)
  997. return rv;
  998. }
  999. if (PresentInComps(certmap_info->filtercomps, tag)) {
  1000. rv = AddToFilter(filter, BIG_LINE, &flen, tagName, ava);
  1001. if (rv != LDAPU_SUCCESS)
  1002. return rv;
  1003. numfavas++;
  1004. }
  1005. }
  1006. }
  1007. if (numfavas == 0) {
  1008. /* nothing added to filter */
  1009. *filter = 0;
  1010. } else if (numfavas == 1) {
  1011. /* one ava added to filter -- remove "(& (" from the front and ")"
  1012. * from the end.
  1013. */
  1014. *filter_out = strdup(filter + 4);
  1015. if (!*filter_out)
  1016. return LDAPU_ERR_OUT_OF_MEMORY;
  1017. (*filter_out)[strlen(*filter_out) - 1] = 0;
  1018. } else {
  1019. /* Add the closing parenthesis to filter */
  1020. strcat(filter + flen, ")");
  1021. *filter_out = strdup(filter);
  1022. }
  1023. if (dnlen >= BIG_LINE)
  1024. return LDAPU_FAILED;
  1025. ldapdn[dnlen] = 0;
  1026. *ldapDN_out = *ldapdn ? strdup(ldapdn) : 0;
  1027. if ((numfavas && !*filter_out) || (dnlen && !*ldapDN_out)) {
  1028. /* strdup failed */
  1029. return LDAPU_ERR_OUT_OF_MEMORY;
  1030. }
  1031. if ((certmap_info->dncompsState == COMPS_HAS_ATTRS && dnlen == 0) ||
  1032. (certmap_info->filtercompsState == COMPS_HAS_ATTRS &&
  1033. numfavas == 0)) {
  1034. /* At least one attr in DNComps should be present in the cert */
  1035. /* Same is true for FilterComps */
  1036. rv = LDAPU_ERR_MAPPED_ENTRY_NOT_FOUND;
  1037. }
  1038. }
  1039. return rv;
  1040. }
  1041. NSAPI_PUBLIC int
  1042. ldapu_set_cert_mapfn(const CERTName *issuerDN,
  1043. CertMapFn_t mapfn)
  1044. {
  1045. LDAPUCertMapInfo_t *certmap_info;
  1046. int rv;
  1047. /* don't free the certmap_info -- its a pointer to an internal structure */
  1048. rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1049. /* Don't set the mapping function if certmap_info doesen't exist */
  1050. if (rv != LDAPU_SUCCESS)
  1051. return rv;
  1052. certmap_info->mapfn = mapfn;
  1053. return LDAPU_SUCCESS;
  1054. }
  1055. static CertMapFn_t
  1056. ldapu_get_cert_mapfn_sub(LDAPUCertMapInfo_t *certmap_info)
  1057. {
  1058. CertMapFn_t mapfn;
  1059. if (certmap_info && certmap_info->mapfn)
  1060. mapfn = certmap_info->mapfn;
  1061. else if (default_certmap_info && default_certmap_info->mapfn)
  1062. mapfn = default_certmap_info->mapfn;
  1063. else
  1064. mapfn = ldapu_cert_mapfn_default;
  1065. return mapfn;
  1066. }
  1067. NSAPI_PUBLIC CertMapFn_t
  1068. ldapu_get_cert_mapfn(const CERTName *issuerDN)
  1069. {
  1070. LDAPUCertMapInfo_t *certmap_info = 0;
  1071. /* don't free the certmap_info -- its a pointer to an internal structure */
  1072. ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1073. /* certmap_info may be NULL -- use the default */
  1074. return ldapu_get_cert_mapfn_sub(certmap_info);
  1075. }
  1076. NSAPI_PUBLIC int
  1077. ldapu_set_cert_searchfn(const CERTName *issuerDN,
  1078. CertSearchFn_t searchfn)
  1079. {
  1080. LDAPUCertMapInfo_t *certmap_info;
  1081. int rv;
  1082. /* don't free the certmap_info -- its a pointer to an internal structure */
  1083. rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1084. /* Don't set the mapping function if certmap_info doesen't exist */
  1085. if (rv != LDAPU_SUCCESS)
  1086. return rv;
  1087. certmap_info->searchfn = searchfn;
  1088. return LDAPU_SUCCESS;
  1089. }
  1090. static CertSearchFn_t
  1091. ldapu_get_cert_searchfn_sub(LDAPUCertMapInfo_t *certmap_info)
  1092. {
  1093. CertSearchFn_t searchfn;
  1094. if (certmap_info && certmap_info->searchfn)
  1095. searchfn = certmap_info->searchfn;
  1096. else if (default_certmap_info && default_certmap_info->searchfn)
  1097. searchfn = default_certmap_info->searchfn;
  1098. else
  1099. searchfn = ldapu_cert_searchfn_default;
  1100. return searchfn;
  1101. }
  1102. NSAPI_PUBLIC CertSearchFn_t
  1103. ldapu_get_cert_searchfn(const CERTName *issuerDN)
  1104. {
  1105. LDAPUCertMapInfo_t *certmap_info = 0;
  1106. /* don't free the certmap_info -- its a pointer to an internal structure */
  1107. ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1108. /* certmap_info may be NULL -- use the default */
  1109. return ldapu_get_cert_searchfn_sub(certmap_info);
  1110. }
  1111. NSAPI_PUBLIC int
  1112. ldapu_set_cert_verifyfn(const CERTName *issuerDN,
  1113. CertVerifyFn_t verifyfn)
  1114. {
  1115. LDAPUCertMapInfo_t *certmap_info;
  1116. int rv;
  1117. /* don't free the certmap_info -- its a pointer to an internal structure */
  1118. rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1119. /* Don't set the verify function if certmap_info doesen't exist */
  1120. if (rv != LDAPU_SUCCESS)
  1121. return rv;
  1122. certmap_info->verifyfn = verifyfn;
  1123. return LDAPU_SUCCESS;
  1124. }
  1125. static CertVerifyFn_t
  1126. ldapu_get_cert_verifyfn_sub(LDAPUCertMapInfo_t *certmap_info)
  1127. {
  1128. CertVerifyFn_t verifyfn;
  1129. if (certmap_info && certmap_info->verifyfn)
  1130. verifyfn = certmap_info->verifyfn;
  1131. else if (default_certmap_info && default_certmap_info->verifyfn)
  1132. verifyfn = default_certmap_info->verifyfn;
  1133. else
  1134. verifyfn = ldapu_cert_verifyfn_default;
  1135. return verifyfn;
  1136. }
  1137. NSAPI_PUBLIC CertVerifyFn_t
  1138. ldapu_get_cert_verifyfn(const CERTName *issuerDN)
  1139. {
  1140. LDAPUCertMapInfo_t *certmap_info = 0;
  1141. /* don't free the certmap_info -- its a pointer to an internal structure */
  1142. ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1143. /* certmap_info may be NULL -- use the default */
  1144. return ldapu_get_cert_verifyfn_sub(certmap_info);
  1145. }
  1146. #if 0 /* may need this in the future */
  1147. static int ldapu_certinfo_copy (const LDAPUCertMapInfo_t *from,
  1148. const char *newIssuerName,
  1149. const char *newIssuerDN,
  1150. LDAPUCertMapInfo_t *to)
  1151. {
  1152. /* This function is not tested and is not used */
  1153. int rv;
  1154. to->issuerName = newIssuerName ? strdup(newIssuerName) : 0;
  1155. to->issuerDN = newIssuerDN ? strdup(newIssuerDN) : 0;
  1156. if (from->propval) {
  1157. rv = ldapu_list_copy(from->propval, &to->propval, ldapu_propval_copy);
  1158. if (rv != LDAPU_SUCCESS) return rv;
  1159. }
  1160. else {
  1161. to->propval = 0;
  1162. }
  1163. return process_certinfo(to);
  1164. }
  1165. #endif
  1166. NSAPI_PUBLIC int
  1167. ldapu_cert_to_ldap_entry(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res)
  1168. {
  1169. char *ldapDN = 0;
  1170. char *filter = 0;
  1171. LDAPUCertMapInfo_t *certmap_info;
  1172. LDAPMessage **res_array = NULL;
  1173. CertMapFn_t mapfn;
  1174. CertVerifyFn_t verifyfn;
  1175. CertSearchFn_t searchfn;
  1176. int rv, i, j;
  1177. *res = 0;
  1178. if (!certmap_attrs[0]) {
  1179. /* Initialize certmap_attrs */
  1180. certmap_attrs[0] = ldapu_strings[LDAPU_STR_ATTR_USER];
  1181. certmap_attrs[1] = ldapu_strings[LDAPU_STR_ATTR_CERT];
  1182. certmap_attrs[2] = ldapu_strings[LDAPU_STR_ATTR_CERT_NOSUBTYPE];
  1183. certmap_attrs[3] = 0;
  1184. }
  1185. CERTName *issuerDN = ldapu_get_cert_issuer_dn_as_CERTName(cert);
  1186. /* ^ don't need to free this; it will be freed with ^ the cert */
  1187. if (NULL == issuerDN)
  1188. return LDAPU_ERR_NO_ISSUERDN_IN_CERT;
  1189. /* don't free the certmap_info -- its a pointer to an internal structure */
  1190. rv = ldapu_issuer_certinfo(issuerDN, (void **)&certmap_info);
  1191. if (!certmap_info)
  1192. certmap_info = default_certmap_info;
  1193. /* Get the mapping function from the certmap_info */
  1194. mapfn = ldapu_get_cert_mapfn_sub(certmap_info);
  1195. rv = (*mapfn)(cert, ld, certmap_info, &ldapDN, &filter);
  1196. if (rv != LDAPU_SUCCESS) {
  1197. free(ldapDN);
  1198. free(filter);
  1199. return rv;
  1200. }
  1201. /* Get the search function from the certmap_info - certinfo maybe NULL */
  1202. searchfn = ldapu_get_cert_searchfn_sub(certmap_info);
  1203. rv = (*searchfn)(cert, ld, certmap_info, basedn, ldapDN, filter,
  1204. certmap_attrs, &res_array);
  1205. free(ldapDN);
  1206. free(filter);
  1207. /*
  1208. * Get the verify cert function & call it.
  1209. */
  1210. j = 0;
  1211. if ((rv == LDAPU_SUCCESS || rv == LDAPU_ERR_MULTIPLE_MATCHES) &&
  1212. (certmap_info ? certmap_info->verifyCert : 0)) {
  1213. verifyfn = ldapu_get_cert_verifyfn_sub(certmap_info);
  1214. if (verifyfn) {
  1215. int verify_rv;
  1216. i = 0;
  1217. do {
  1218. LDAPMessage *entry;
  1219. verify_rv = (*verifyfn)(cert, ld, certmap_info, res_array[i], &entry);
  1220. if (rv == LDAPU_ERR_MULTIPLE_MATCHES) {
  1221. if (verify_rv == LDAPU_SUCCESS) {
  1222. /* 'entry' points to the matched entry */
  1223. /* Get the 'res' which only contains this entry */
  1224. char *dn = ldapu_get_dn(ld, entry);
  1225. if (*res)
  1226. ldapu_msgfree(ld, *res);
  1227. rv = ldapu_find(ld, dn, LDAP_SCOPE_BASE, 0, certmap_attrs, 0, res);
  1228. ldapu_memfree(ld, dn);
  1229. } else {
  1230. /* Verify failed for multiple matches -- keep rv */
  1231. /* multiple matches err is probably more interesting to
  1232. the caller then any other error returned by the verify
  1233. fn */
  1234. }
  1235. } else /* rv == LDAPU_SUCCESS */ {
  1236. if (verify_rv == LDAPU_SUCCESS) {
  1237. *res = res_array[0];
  1238. j = 1;
  1239. } else {
  1240. rv = verify_rv;
  1241. }
  1242. }
  1243. } while ((verify_rv != LDAPU_SUCCESS) && (res_array[++i] != NULL));
  1244. }
  1245. } else {
  1246. if (rv == LDAPU_SUCCESS) {
  1247. *res = res_array[0];
  1248. j = 1;
  1249. }
  1250. }
  1251. if (rv != LDAPU_SUCCESS) {
  1252. if (*res) {
  1253. ldapu_msgfree(ld, *res);
  1254. *res = 0;
  1255. }
  1256. }
  1257. i = j; /* ugaston - if the search had been successful, despite verifyCert being "off",
  1258. * mapping is considered successful, so we keep the first (and only) response message.
  1259. * If, on the other hand, the search had returned multiple matches, the fact
  1260. * of having verifyCert "off" automatically turns the mapping faulty, so we
  1261. * don't need to care about keeping any response at all.
  1262. */
  1263. if (res_array) {
  1264. while (res_array[i] != NULL) {
  1265. ldapu_msgfree(ld, res_array[i]);
  1266. res_array[i++] = 0;
  1267. }
  1268. ldapu_memfree(ld, res_array);
  1269. }
  1270. return rv;
  1271. }
  1272. /* The caller shouldn't free the entry */
  1273. NSAPI_PUBLIC int
  1274. ldapu_cert_to_user(void *cert, LDAP *ld, const char *basedn, LDAPMessage **res_out, char **user)
  1275. {
  1276. int rv;
  1277. LDAPMessage *res;
  1278. LDAPMessage *entry;
  1279. int numEntries;
  1280. char **attrVals = NULL;
  1281. *res_out = 0;
  1282. *user = 0;
  1283. rv = ldapu_cert_to_ldap_entry(cert, ld, basedn, &res);
  1284. if (rv != LDAPU_SUCCESS) {
  1285. goto done;
  1286. }
  1287. if (!res) {
  1288. rv = LDAPU_ERR_EMPTY_LDAP_RESULT;
  1289. goto done;
  1290. }
  1291. /* Extract user login (the 'uid' attr) from 'res' */
  1292. numEntries = ldapu_count_entries(ld, res);
  1293. if (numEntries != 1) {
  1294. rv = LDAPU_ERR_MULTIPLE_MATCHES;
  1295. goto done;
  1296. }
  1297. entry = ldapu_first_entry(ld, res);
  1298. if (!entry) {
  1299. rv = LDAPU_ERR_MISSING_RES_ENTRY;
  1300. goto done;
  1301. }
  1302. attrVals = ldapu_get_values(ld, entry,
  1303. ldapu_strings[LDAPU_STR_ATTR_USER]);
  1304. if (!attrVals || !attrVals[0]) {
  1305. rv = LDAPU_ERR_MISSING_UID_ATTR;
  1306. goto done;
  1307. }
  1308. *user = strdup(attrVals[0]);
  1309. /* ldapu_msgfree(res); */
  1310. if (!*user) {
  1311. rv = LDAPU_ERR_OUT_OF_MEMORY;
  1312. goto done;
  1313. }
  1314. *res_out = res;
  1315. done:
  1316. if (attrVals) {
  1317. ldapu_value_free(ld, attrVals);
  1318. }
  1319. return rv;
  1320. }
  1321. static void *
  1322. ldapu_propval_free(void *propval_in, void *arg __attribute__((unused)))
  1323. {
  1324. LDAPUPropVal_t *propval = (LDAPUPropVal_t *)propval_in;
  1325. if (propval->prop)
  1326. free(propval->prop);
  1327. if (propval->val)
  1328. free(propval->val);
  1329. memset((void *)propval, 0, sizeof(LDAPUPropVal_t));
  1330. free(propval);
  1331. return 0;
  1332. }
  1333. void
  1334. ldapu_certinfo_free(void *info_in)
  1335. {
  1336. LDAPUCertMapInfo_t *certmap_info = (LDAPUCertMapInfo_t *)info_in;
  1337. if (certmap_info->issuerName)
  1338. free(certmap_info->issuerName);
  1339. if (certmap_info->issuerDN)
  1340. free(certmap_info->issuerDN);
  1341. if (certmap_info->propval)
  1342. ldapu_list_free(certmap_info->propval, ldapu_propval_free);
  1343. if (certmap_info->searchAttr)
  1344. free(certmap_info->searchAttr);
  1345. memset((void *)certmap_info, 0, sizeof(LDAPUCertMapInfo_t));
  1346. free(certmap_info);
  1347. }
  1348. static void *
  1349. ldapu_certinfo_free_helper(void *info, void *arg __attribute__((unused)))
  1350. {
  1351. ldapu_certinfo_free(info);
  1352. return (void *)LDAPU_SUCCESS;
  1353. }
  1354. void
  1355. ldapu_certmap_listinfo_free(void *_certmap_listinfo)
  1356. {
  1357. LDAPUCertMapListInfo_t *list = (LDAPUCertMapListInfo_t *)_certmap_listinfo;
  1358. ldapu_list_free(list, ldapu_certinfo_free_helper);
  1359. }
  1360. void
  1361. ldapu_propval_list_free(void *propval_list)
  1362. {
  1363. LDAPUPropValList_t *list = (LDAPUPropValList_t *)propval_list;
  1364. ldapu_list_free(list, ldapu_propval_free);
  1365. free(list);
  1366. }
  1367. int
  1368. ldapu_certmap_init(const char *config_file,
  1369. const char *dllname,
  1370. LDAPUCertMapListInfo_t **certmap_list,
  1371. LDAPUCertMapInfo_t **certmap_default)
  1372. {
  1373. int rv;
  1374. certmap_listinfo = (LDAPUCertMapListInfo_t *)calloc(1, sizeof(LDAPUCertMapListInfo_t));
  1375. *certmap_list = 0;
  1376. *certmap_default = 0;
  1377. PR_snprintf(this_dllname, sizeof(this_dllname), "%s", dllname);
  1378. if (!certmap_listinfo)
  1379. return LDAPU_ERR_OUT_OF_MEMORY;
  1380. rv = certmap_read_certconfig_file(config_file);
  1381. if (rv == LDAPU_SUCCESS) {
  1382. *certmap_list = certmap_listinfo;
  1383. *certmap_default = default_certmap_info;
  1384. }
  1385. return rv;
  1386. }
  1387. NSAPI_PUBLIC int
  1388. ldaputil_exit()
  1389. {
  1390. if (default_certmap_info) {
  1391. ldapu_certinfo_free(default_certmap_info);
  1392. default_certmap_info = 0;
  1393. }
  1394. if (certmap_listinfo) {
  1395. ldapu_certmap_listinfo_free(certmap_listinfo);
  1396. certmap_listinfo = 0;
  1397. }
  1398. return LDAPU_SUCCESS;
  1399. }
  1400. NSAPI_PUBLIC void
  1401. ldapu_free(void *ptr)
  1402. {
  1403. if (ptr)
  1404. free(ptr);
  1405. }
  1406. NSAPI_PUBLIC void
  1407. ldapu_free_old(char *ptr)
  1408. {
  1409. free((void *)ptr);
  1410. }
  1411. NSAPI_PUBLIC void *
  1412. ldapu_malloc(int size)
  1413. {
  1414. return malloc(size);
  1415. }
  1416. NSAPI_PUBLIC char *
  1417. ldapu_strdup(const char *ptr)
  1418. {
  1419. return strdup(ptr);
  1420. }
  1421. NSAPI_PUBLIC void *
  1422. ldapu_realloc(void *ptr, int size)
  1423. {
  1424. return realloc(ptr, size);
  1425. }