1
0

nscert.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  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. * END COPYRIGHT BLOCK **/
  6. /*
  7. * Description (nsadb.c)
  8. *
  9. * This module contains routines for accessing and storing information
  10. * in a Netscape client certificate to username database. This
  11. * database is used to associate a username with a client certificate
  12. * that is presented to a server.
  13. */
  14. #if defined(CLIENT_AUTH)
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <base/systems.h>
  19. #include <netsite.h>
  20. #include <base/file.h>
  21. #include <base/fsmutex.h>
  22. #include <libaccess/nsdbmgmt.h>
  23. #define __PRIVATE_NSADB
  24. #include <libaccess/nsadb.h>
  25. #include <libaccess/nsamgmt.h>
  26. static FSMUTEX nscert_lock = 0;
  27. NSAPI_PUBLIC int nsadbCertInitialize(void)
  28. {
  29. #ifdef XP_UNIX
  30. nscert_lock = fsmutex_init("NSCERTMAP", geteuid(),
  31. FSMUTEX_VISIBLE|FSMUTEX_NEEDCRIT);
  32. #else /* XP_WIN32 */
  33. char winuser[128];
  34. DWORD wulength;
  35. strcpy(winuser, "NSCERTMAP_");
  36. wulength = 128 - 11;
  37. GetUserName(winuser+10, &wulength);
  38. nscert_lock = fsmutex_init(winuser, 0,
  39. FSMUTEX_VISIBLE|FSMUTEX_NEEDCRIT);
  40. #endif
  41. return (nscert_lock == 0) ? -1 : 0;
  42. }
  43. NSAPI_PUBLIC int nsadbDecodeCertRec(int reclen, char * recptr,
  44. CertObj_t * coptr)
  45. {
  46. ATR_t cp = (ATR_t)recptr; /* current pointer into record */
  47. USI_t tag; /* attribute tag */
  48. USI_t len; /* attribute value encoding length */
  49. /* Parse user DB record */
  50. while ((cp - (ATR_t)recptr) < reclen) {
  51. /* Get the attribute tag */
  52. cp = USIDECODE(cp, &tag);
  53. /* Get the length of the encoding of the attribute value */
  54. cp = USIDECODE(cp, &len);
  55. /* Process this attribute */
  56. switch (tag) {
  57. case CAT_USERNAME: /* username associated with cert */
  58. cp = NTSDECODE(cp, (NTS_t *)&coptr->co_username);
  59. break;
  60. case CAT_CERTID: /* certificate-to-user map id */
  61. cp = USIDECODE(cp, &coptr->co_certid);
  62. break;
  63. default: /* unrecognized attribute */
  64. /* Just skip it */
  65. cp += len;
  66. break;
  67. }
  68. }
  69. return 0;
  70. }
  71. /*
  72. * Description (nsadbDecodeCertKey)
  73. *
  74. * This function decodes information from a certificate key.
  75. * Currently a certificate key includes the DER encoding of the
  76. * issuer and subject distinguished names. This is used to
  77. * uniquely identify client certificates, even across certificate
  78. * renewals. SECItems for the issuer and subject are provided
  79. * by the caller. These are updated with the pointers and lengths
  80. * of DER encodings, which can be decoded using nsadbDecodeCertName()
  81. * into SECName structures. The returned SECItems refer to data
  82. * in the provided key buffer.
  83. *
  84. * Arguments:
  85. *
  86. * keylen - length of the certificate key encoding
  87. * keyptr - buffer containing certificate key encoding
  88. * issuer - pointer to SECItem for returning issuer
  89. * subject - pointer to SECItem for returning subject
  90. *
  91. * Returns:
  92. *
  93. * Zero is returned if no errors are encountered. Otherwise -1.
  94. */
  95. NSAPI_PUBLIC int nsadbDecodeCertKey(int keylen, char * keyptr,
  96. SECItem * issuer, SECItem * subject)
  97. {
  98. ATR_t cp = (ATR_t)keyptr; /* current pointer into DB record */
  99. USI_t len; /* attribute value encoding length */
  100. USI_t tag; /* attribute tag */
  101. /* Parse user DB record */
  102. while ((cp - (ATR_t)keyptr) < keylen) {
  103. /* Get the attribute tag */
  104. cp = USIDECODE(cp, &tag);
  105. /* Get the length of the encoding of the attribute value */
  106. cp = USIDECODE(cp, &len);
  107. /* Process this attribute */
  108. switch (tag) {
  109. case KAT_ISSUER: /* issuer DER encoding */
  110. issuer->len = len;
  111. issuer->data = cp;
  112. cp += len;
  113. break;
  114. case KAT_SUBJECT: /* subject name DER encoding */
  115. subject->len = len;
  116. subject->data = cp;
  117. cp += len;
  118. break;
  119. default: /* unrecognized attribute */
  120. /* Just skip it */
  121. cp += len;
  122. break;
  123. }
  124. }
  125. return 0;
  126. }
  127. /*
  128. * Description (nsadbEncodeCertKey)
  129. *
  130. * This function encodes information provided by the caller into
  131. * a certificate key. The certificate key is returned in a
  132. * buffer obtained from MALLOC().
  133. *
  134. * Arguments:
  135. *
  136. * issuer - pointer to SECItem for issuer DER
  137. * subject - pointer to SECItem for subject DER
  138. * keylen - returned length of certificate key
  139. * keyptr - returned pointer to buffer containing
  140. * certificate key encoding
  141. *
  142. * Returns:
  143. *
  144. * Zero is returned if no errors are encountered. Otherwise -1.
  145. */
  146. NSAPI_PUBLIC int nsadbEncodeCertKey(SECItem * issuer, SECItem * subject,
  147. int * keylen, char **keyptr)
  148. {
  149. ATR_t cp; /* pointer into key buffer */
  150. ATR_t kptr; /* pointer to key buffer */
  151. int klen; /* length of key */
  152. int rv = -1;
  153. /* Compute length of key encoding */
  154. klen = 1 + USILENGTH(issuer->len) + issuer->len +
  155. 1 + USILENGTH(subject->len) + subject->len;
  156. /* Allocate buffer to contain the key */
  157. kptr = (ATR_t)MALLOC(klen);
  158. if (kptr) {
  159. /* Encode issuer and subject as attributes */
  160. cp = kptr;
  161. *cp++ = KAT_ISSUER;
  162. cp = USIENCODE(cp, issuer->len);
  163. memcpy(cp, issuer->data, issuer->len);
  164. cp += issuer->len;
  165. *cp++ = KAT_SUBJECT;
  166. cp = USIENCODE(cp, subject->len);
  167. memcpy(cp, subject->data, subject->len);
  168. rv = 0;
  169. }
  170. /* Return length and buffer pointer */
  171. if (keylen) *keylen = klen;
  172. *keyptr = (char *)kptr;
  173. return rv;
  174. }
  175. /*
  176. * Description (nsadbEnumCertsHelp)
  177. *
  178. * This is a local function that is called by NSDB during certificate
  179. * to user database enumeration. It decodes certificate records into
  180. * CertObj_t structures, and presents them to the caller of
  181. * nsadbEnumerateCerts(), via the specified call-back function.
  182. * The call-back function return value may be a negative error code,
  183. * which will cause enumeration to stop, and the error code will be
  184. * returned from nsadbEnumerateCerts(). If the return value of the
  185. * call-back function is not negative, it can contain one or more of
  186. * the following flags:
  187. *
  188. * ADBF_KEEPOBJ - do not free the CertObj_t structure
  189. * that was passed to the call-back function
  190. * ADBF_STOPENUM - stop the enumeration without an error
  191. *
  192. * Arguments:
  193. *
  194. * errp - error frame list pointer (may be null)
  195. * parg - pointer to CertEnumArgs_t structure
  196. * keylen - certificate record key length
  197. * keyptr - certificate record key
  198. * reclen - length of certificate record
  199. * recptr - pointer to certificate record contents
  200. *
  201. * Returns:
  202. *
  203. * If the call-back returns a negative result, that value is
  204. * returned. If the call-back returns ADBF_STOPENUM, then
  205. * -1 is returned, causing the enumeration to stop. Otherwise
  206. * the return value is zero.
  207. */
  208. typedef struct CertEnumArgs_s CertEnumArgs_t;
  209. struct CertEnumArgs_s {
  210. int rv; /* just a return value */
  211. void * client; /* the current key for lookup */
  212. void * authdb; /* the authentication data base */
  213. CertEnumCallback func; /* client's callback function */
  214. };
  215. static int nsadbEnumCertsHelp(NSErr_t * errp, void * parg,
  216. int keylen, char * keyptr,
  217. int reclen, char * recptr)
  218. {
  219. CertEnumArgs_t * ce = (CertEnumArgs_t *)parg;
  220. CertObj_t * coptr;
  221. int rv = NSAERRNOMEM;
  222. /* Allocate a CertObj_t structure and initialize it */
  223. coptr = (CertObj_t *)MALLOC(sizeof(CertObj_t));
  224. if (coptr) {
  225. coptr->co_issuer.data = 0;
  226. coptr->co_subject.data = 0;
  227. coptr->co_username = 0;
  228. coptr->co_certid = 0;
  229. /* Decode the certificate key */
  230. rv = nsadbDecodeCertKey(keylen, keyptr,
  231. &coptr->co_issuer, &coptr->co_subject);
  232. /* Decode the certificate record */
  233. rv = nsadbDecodeCertRec(reclen, recptr, coptr);
  234. /* Pass the CertObj_t to the callback function */
  235. rv = (*ce->func)(errp, ce->authdb, ce->client, coptr);
  236. if (rv >= 0) {
  237. /* Count the number of records seen */
  238. ce->rv += 1;
  239. /* Free the user object unless the call-back says not to */
  240. if (!(rv & ADBF_KEEPOBJ)) {
  241. nsadbFreeCertObj(coptr);
  242. }
  243. /* Return either 0 or -1, depending on ADBF_STOPENUM */
  244. rv = (rv & ADBF_STOPENUM) ? -1 : 0;
  245. }
  246. else {
  247. /* return the error code */
  248. ce->rv = rv;
  249. }
  250. }
  251. return rv;
  252. }
  253. /*
  254. * Description (nsadbEnumerateClients)
  255. *
  256. * (See description for nsadbEnumerateUsers)
  257. */
  258. NSAPI_PUBLIC int nsadbEnumerateCerts(NSErr_t * errp, void * authdb,
  259. void * argp, CertEnumCallback func)
  260. {
  261. AuthDB_t * adb = (AuthDB_t*)authdb;
  262. CertEnumArgs_t helper_data;
  263. int rv;
  264. /* Open the certificate subdatabase for read access */
  265. rv = nsadbOpenCerts(errp, authdb, ADBF_CREAD);
  266. if (rv >= 0) {
  267. helper_data.authdb = authdb;
  268. helper_data.func = func;
  269. helper_data.client = argp;
  270. helper_data.rv = 0;
  271. rv = ndbEnumerate(errp, adb->adb_certdb, NDBF_ENUMNORM,
  272. (void*)&helper_data, nsadbEnumCertsHelp);
  273. }
  274. return (rv < 0) ? rv: helper_data.rv;
  275. }
  276. NSAPI_PUBLIC void nsadbFreeCertObj(CertObj_t * coptr)
  277. {
  278. if (coptr) {
  279. FREE(coptr->co_username);
  280. FREE(coptr);
  281. }
  282. }
  283. NSAPI_PUBLIC int nsadbGetCertById(NSErr_t * errp, void * authdb,
  284. USI_t certid, CertObj_t **coptr)
  285. {
  286. AuthDB_t * adb = (AuthDB_t *)authdb;
  287. CertObj_t * cop = 0;
  288. char * keyptr;
  289. char * recptr;
  290. int keylen;
  291. int reclen;
  292. int rv;
  293. rv = nsadbOpenCerts(errp, authdb, ADBF_CREAD);
  294. if (rv < 0) goto punt;
  295. /* Get the name corresponding to the id */
  296. rv = ndbIdToName(errp, adb->adb_certdb, certid, &keylen, &keyptr);
  297. if (rv < 0) goto punt;
  298. rv = ndbFindName(errp, adb->adb_certdb,
  299. keylen, keyptr, &reclen, &recptr);
  300. if (rv < 0) goto punt;
  301. /* Allocate a CertObj_t structure and initialize it */
  302. cop = (CertObj_t *)MALLOC(sizeof(CertObj_t));
  303. if (cop) {
  304. cop->co_issuer.data = 0;
  305. cop->co_subject.data = 0;
  306. cop->co_username = 0;
  307. cop->co_certid = 0;
  308. /* Decode the certificate key */
  309. rv = nsadbDecodeCertKey(keylen, keyptr,
  310. &cop->co_issuer, &cop->co_subject);
  311. /* Decode the certificate record */
  312. rv = nsadbDecodeCertRec(reclen, recptr, cop);
  313. }
  314. punt:
  315. if (coptr) *coptr = cop;
  316. return rv;
  317. }
  318. /*
  319. * Description (nsadbGetUserByCert)
  320. *
  321. * This function looks up a specified client certificate in the
  322. * authentication database. It returns a pointer to the username
  323. * associated with the client certificate, if any. The username
  324. * buffer remains valid until the authentication database is
  325. * closed.
  326. *
  327. * Arguments:
  328. *
  329. * errp - error frame list pointer (may be null)
  330. * authdb - handle returned by nsadbOpen()
  331. * cert - pointer to client certificate
  332. * username - pointer to returned user name (or null)
  333. *
  334. * Returns:
  335. *
  336. * The return value will be zero if the certificate is found. Also,
  337. * *username will be set to the string value of the associated username
  338. * iff username is not null.
  339. */
  340. NSAPI_PUBLIC int nsadbGetUserByCert(NSErr_t * errp, void * authdb,
  341. CERTCertificate * cert, char **username)
  342. {
  343. AuthDB_t * adb = (AuthDB_t *)authdb;
  344. ATR_t cp; /* current pointer into DB record */
  345. char * user = 0; /* pointer to username */
  346. char * keyptr = 0; /* pointer to cert key */
  347. char * recptr; /* pointer to cert db record */
  348. int keylen; /* length of cert key */
  349. int reclen; /* length of cert db record */
  350. USI_t tag; /* attribute tag */
  351. USI_t len; /* attribute value encoding length */
  352. int rv;
  353. /* Construct the record key from the certificate */
  354. rv = nsadbEncodeCertKey(&cert->derIssuer, &cert->derSubject,
  355. &keylen, &keyptr);
  356. if (adb->adb_certdb == NULL) {
  357. rv = nsadbOpenCerts(errp, authdb, ADBF_CREAD);
  358. if (rv < 0) goto punt;
  359. }
  360. rv = ndbFindName(errp, adb->adb_certdb,
  361. keylen, keyptr, &reclen, &recptr);
  362. if (rv < 0) goto punt;
  363. /* Parse cert DB record */
  364. cp = (ATR_t)recptr;
  365. while ((cp - (ATR_t)recptr) < reclen) {
  366. /* Get the attribute tag */
  367. cp = USIDECODE(cp, &tag);
  368. /* Get the length of the encoding of the attribute value */
  369. cp = USIDECODE(cp, &len);
  370. /* We want the CAT_USERNAME attribute */
  371. if (tag == CAT_USERNAME) {
  372. /* Get the username associated with the cert */
  373. user = (char *)cp;
  374. break;
  375. }
  376. /* Just skip other attributes */
  377. cp += len;
  378. }
  379. punt:
  380. if (keyptr) {
  381. FREE(keyptr);
  382. }
  383. if (username) *username = user;
  384. return rv;
  385. }
  386. /*
  387. * Description (see description for nsadbOpenUsers)
  388. */
  389. int nsadbOpenCerts(NSErr_t * errp, void * authdb, int flags)
  390. {
  391. AuthDB_t *adb = (AuthDB_t*)authdb;
  392. char *dbname = NULL; /* user database name */
  393. int dblen; /* strlen(adb_dbname) */
  394. int version; /* database version */
  395. int eid; /* error id code */
  396. int rv; /* result value */
  397. if (adb == NULL) goto err_inval;
  398. /* Is the user database already open? */
  399. if (adb->adb_certdb != 0) {
  400. /* Yes, is it open for the desired access? */
  401. if (adb->adb_flags & flags) {
  402. /* Yes, that was easy */
  403. return 0;
  404. }
  405. }
  406. else {
  407. /* Allocate space for the user database filename */
  408. dblen = strlen(adb->adb_dbname);
  409. dbname = (char *)MALLOC(dblen + strlen(ADBCERTDBNAME) + 2);
  410. if (dbname == 0) goto err_nomem;
  411. /* Construct user database name */
  412. strcpy(dbname, adb->adb_dbname);
  413. /* Put in a '/' (or '\') if it's not there */
  414. if (dbname[dblen-1] != FILE_PATHSEP) {
  415. dbname[dblen] = FILE_PATHSEP;
  416. dbname[dblen+1] = 0;
  417. ++dblen;
  418. }
  419. strcpy(&dbname[dblen], ADBCERTDBNAME);
  420. if (nscert_lock == 0) {
  421. rv = nsadbCertInitialize();
  422. if (rv < 0) goto err_lock;
  423. }
  424. adb->adb_certlock = nscert_lock;
  425. if (adb->adb_certlock == 0) goto punt;
  426. fsmutex_lock((FSMUTEX)(adb->adb_certlock));
  427. adb->adb_certdb = ndbOpen(errp,
  428. dbname, 0, NDB_TYPE_CLIENTDB, &version);
  429. if (adb->adb_certdb == 0) {
  430. fsmutex_unlock((FSMUTEX)(adb->adb_certlock));
  431. goto err_open;
  432. }
  433. }
  434. /*
  435. * We don't really reopen the database to get the desired
  436. * access mode, since that is handled at the nsdb level.
  437. * But we do update the flags, just for the record.
  438. */
  439. adb->adb_flags &= ~(ADBF_CREAD|ADBF_CWRITE);
  440. if (flags & ADBF_CWRITE) adb->adb_flags |= ADBF_CWRITE;
  441. else adb->adb_flags |= ADBF_CREAD;
  442. rv = 0;
  443. punt:
  444. if (dbname != NULL) FREE(dbname);
  445. return rv;
  446. err_inval:
  447. eid = NSAUERR3400;
  448. rv = NSAERRINVAL;
  449. goto err_ret;
  450. err_nomem:
  451. eid = NSAUERR3420;
  452. rv = NSAERRNOMEM;
  453. goto err_ret;
  454. err_lock:
  455. eid = NSAUERR3430;
  456. rv = NSAERRLOCK;
  457. goto err_ret;
  458. err_open:
  459. eid = NSAUERR3440;
  460. rv = NSAERROPEN;
  461. err_ret:
  462. nserrGenerate(errp, rv, eid, NSAuth_Program, 1, dbname);
  463. goto punt;
  464. }
  465. NSAPI_PUBLIC void nsadbCloseCerts(void * authdb, int flags)
  466. {
  467. AuthDB_t * adb = (AuthDB_t *)authdb;
  468. if (adb->adb_certnm != 0) {
  469. /* Close the username-to-certid database */
  470. nsadbCloseCertUsers(authdb, flags);
  471. }
  472. if (adb->adb_certdb != 0) {
  473. ndbClose(adb->adb_certdb, 0);
  474. adb->adb_certdb = 0;
  475. /*
  476. * A lock is held for the certificate map DB as long as it is
  477. * open, so release the lock now.
  478. */
  479. fsmutex_unlock((FSMUTEX)(adb->adb_certlock));
  480. }
  481. }
  482. /*
  483. * Description (nsadbOpenCertUsers)
  484. *
  485. * This function opens a database that maps user names to client
  486. * certificates. The database appears as "Certs.nm" in the
  487. * authentication database directory. This function requires
  488. * that the primary certificate database be opened (Certs.db)
  489. * first, and will open it if necessary, acquiring a global
  490. * lock in the process. The lock will not be released until
  491. * nsadbCloseCerts() or nsadbClose() is called.
  492. *
  493. * Arguments:
  494. *
  495. * errp - error frame list pointer (may be null)
  496. * authdb - handle returned by nsadbOpen()
  497. * flags - same as nsadbOpenCerts()
  498. *
  499. * Returns:
  500. *
  501. * The return value is zero if the operation is successful.
  502. * Otherwise a negative error code is returned.
  503. */
  504. NSAPI_PUBLIC int nsadbOpenCertUsers(NSErr_t * errp, void * authdb, int flags)
  505. {
  506. AuthDB_t * adb = (AuthDB_t *)authdb;
  507. char * dbname = 0;
  508. int dblen;
  509. int oflags = O_RDONLY; /* assume read-only access */
  510. int eid;
  511. int rv;
  512. /* The primary certificate mapping database must be open first */
  513. if (adb->adb_certdb != 0) {
  514. /* It's open, but is it read-only when we need write? */
  515. if (((flags & adb->adb_flags) == 0) && (flags & ADBF_CWRITE)) {
  516. /* Yes, close it */
  517. nsadbCloseCerts(authdb, 0);
  518. }
  519. }
  520. /* Open it for the desired access if necessary */
  521. if (adb->adb_certdb == 0) {
  522. /*
  523. * Open it for the desired access. Note that this acquires
  524. * a global lock which is not released until nsadbClose() is
  525. * called for the entire authentication database.
  526. */
  527. rv = nsadbOpenCerts(errp, authdb, flags);
  528. if (rv < 0) {
  529. /* Go no further if that failed */
  530. return rv;
  531. }
  532. }
  533. /* Now look at the username-to-certid database in particular */
  534. if (adb->adb_certnm && (adb->adb_flags & flags)) {
  535. /* The database is already open for the desired access */
  536. return 0;
  537. }
  538. dblen = strlen(adb->adb_dbname);
  539. dbname = (char *)MALLOC(dblen + strlen(ADBUMAPDBNAME) + 2);
  540. strcpy(dbname, adb->adb_dbname);
  541. if (dbname[dblen-1] != FILE_PATHSEP) {
  542. dbname[dblen] = FILE_PATHSEP;
  543. dbname[++dblen] = 0;
  544. }
  545. strcpy(&dbname[dblen], ADBUMAPDBNAME);
  546. /* Check for write access and set open flags appropriately if so */
  547. if (flags & ADBF_CWRITE) {
  548. oflags = O_CREAT|O_RDWR;
  549. }
  550. /* Open the username-to-certid database */
  551. // adb->adb_certnm = dbopen(dbname, oflags, 0644, DB_HASH, 0);
  552. adb->adb_certnm = 0;
  553. if (adb->adb_certnm == 0) goto err_open;
  554. punt:
  555. FREE(dbname);
  556. return rv;
  557. err_open:
  558. eid = NSAUERR3600;
  559. rv = NSAERROPEN;
  560. nserrGenerate(errp, rv, eid, NSAuth_Program, 1, dbname);
  561. goto punt;
  562. }
  563. /*
  564. * Description (nsadbFindCertUser)
  565. *
  566. * This function checks to see whether a client certificate is
  567. * registered for a specified user name. If so, it returns the
  568. * certificate mapping id (for use with nsadbGetCertById()).
  569. *
  570. * Arguments:
  571. *
  572. * errp - error frame list pointer (may be null)
  573. * authdb - handle returned by nsadbOpen()
  574. * username - pointer to user name string
  575. * id - pointer to returned certificate mapping id
  576. *
  577. * Returns:
  578. *
  579. * If a certificate is registered for the specified user, the return
  580. * value is zero and the certificate mapping id is returned via 'id'.
  581. * Otherwise the return value is a negative error code (nsautherr.h)
  582. * and an error frame is generated if an error frame list is provided.
  583. */
  584. NSAPI_PUBLIC int nsadbFindCertUser(NSErr_t * errp, void * authdb,
  585. const char * username, USI_t * id)
  586. {
  587. int eid;
  588. int rv;
  589. eid = NSAUERR3700;
  590. rv = NSAERRNAME;
  591. nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
  592. return rv;
  593. }
  594. /*
  595. * Description (nsadbAddCertUser)
  596. *
  597. * This function adds an entry to the username-to-cert id database,
  598. * with a given username and certificate mapping id.
  599. *
  600. * Arguments:
  601. *
  602. * errp - error frame list pointer (may be null)
  603. * authdb - handle returned by nsadbOpen()
  604. * username - pointer to user name string
  605. * id - certificate mapping id
  606. *
  607. * Returns:
  608. *
  609. * If the entry is added successfully, the return value is zero.
  610. * Otherwise the return value is a negative error code (nsautherr.h)
  611. * and an error frame is generated if an error frame list is provided.
  612. */
  613. NSAPI_PUBLIC int nsadbAddCertUser(NSErr_t * errp, void * authdb,
  614. const char * username, USI_t id)
  615. {
  616. /* Need to be ported on NSS 3.2 */
  617. int eid;
  618. int rv;
  619. eid = NSAUERR3800;
  620. rv = NSAERRPUT;
  621. nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
  622. return rv;
  623. }
  624. NSAPI_PUBLIC int nsadbRemoveCertUser(NSErr_t * errp, void * authdb,
  625. char * username)
  626. {
  627. /* Need to be ported on NSS 3.2 */
  628. int eid;
  629. int rv;
  630. eid = NSAUERR3800;
  631. rv = NSAERRPUT;
  632. nserrGenerate(errp, rv, eid, NSAuth_Program, 0);
  633. return rv;
  634. }
  635. NSAPI_PUBLIC void nsadbCloseCertUsers(void * authdb, int flags)
  636. {
  637. /* Need to be ported on NSS 3.2 */
  638. }
  639. /*
  640. * Description (nsadbPutUserByCert)
  641. *
  642. * This function looks up a stores a client certificate mapping
  643. * in the authentication database along with the associated username.
  644. * It assumes that a record with the specified certificate key does
  645. * not already exist, and will replace it if it does.
  646. *
  647. * Arguments:
  648. *
  649. * errp - error frame list pointer (may be null)
  650. * authdb - handle returned by nsadbOpen()
  651. * certLen - length of the certificate key
  652. * cert - certificate key pointer
  653. * user - username to be associated with the
  654. * certificate
  655. *
  656. * Returns:
  657. *
  658. */
  659. NSAPI_PUBLIC int nsadbPutUserByCert(NSErr_t * errp, void * authdb,
  660. CERTCertificate * cert,
  661. const char * username)
  662. {
  663. AuthDB_t * adb = (AuthDB_t *)authdb;
  664. ATR_t cp; /* pointer into cert record contents */
  665. char * keyptr = 0; /* pointer to cert record key */
  666. char * recptr = 0; /* pointer to cert record contents */
  667. int keylen; /* length of cert record key */
  668. int reclen; /* length of cert record contents */
  669. USI_t certid;
  670. int usrlen;
  671. int certidlen;
  672. int eid;
  673. int rv;
  674. /* Construct the record key from the certificate */
  675. rv = nsadbEncodeCertKey(&cert->derIssuer, &cert->derSubject,
  676. &keylen, &keyptr);
  677. /* Open the username-to-cert id database for write */
  678. rv = nsadbOpenCertUsers(errp, authdb, ADBF_CWRITE);
  679. if (rv) goto punt;
  680. /* If the username is already mapped to a cert, it's an error */
  681. certid = 0;
  682. rv = nsadbFindCertUser(errp, authdb, username, &certid);
  683. if (rv == 0) goto err_map;
  684. /*
  685. * Allocate a certificate id and write a record mapping this id
  686. * to the specified certificate key.
  687. */
  688. certid = 0;
  689. rv = ndbAllocId(errp, adb->adb_certdb, keylen, keyptr, &certid);
  690. if (rv) goto punt;
  691. /* Record the username as being mapped to the allocated cert id */
  692. rv = nsadbAddCertUser(errp, authdb, username, certid);
  693. if (rv < 0) goto punt;
  694. nsadbCloseCertUsers(authdb, 0);
  695. /*
  696. * First we need to figure out how long the generated record will be.
  697. * This doesn't have to be exact, but it must not be smaller than the
  698. * actual record size.
  699. */
  700. /* CAT_USERNAME attribute: tag, length, NTS */
  701. usrlen = NTSLENGTH(username);
  702. if (usrlen > 127) goto err_user;
  703. reclen = 2 + usrlen;
  704. /* CAT_CERTID attribute: tag, length, USI */
  705. certidlen = USILENGTH(certid);
  706. reclen += 2 + certidlen;
  707. /* Allocate the attribute record buffer */
  708. recptr = (char *)MALLOC(reclen);
  709. if (recptr) {
  710. cp = (ATR_t)recptr;
  711. /* Encode CAT_USERNAME attribute */
  712. *cp++ = CAT_USERNAME;
  713. *cp++ = usrlen;
  714. cp = NTSENCODE(cp, (NTS_t)username);
  715. /* Encode CAT_CERTID attribute */
  716. *cp++ = CAT_CERTID;
  717. *cp++ = certidlen;
  718. cp = USIENCODE(cp, certid);
  719. }
  720. /* Store the record in the database under the certificate key */
  721. rv = ndbStoreName(errp, adb->adb_certdb,
  722. 0, keylen, keyptr, reclen, recptr);
  723. punt:
  724. if (keyptr) {
  725. FREE(keyptr);
  726. }
  727. if (recptr) {
  728. FREE(recptr);
  729. }
  730. return rv;
  731. err_user:
  732. eid = NSAUERR3500;
  733. rv = NSAERRINVAL;
  734. nserrGenerate(errp, rv, eid, NSAuth_Program, 1, adb->adb_dbname);
  735. goto punt;
  736. err_map:
  737. eid = NSAUERR3520;
  738. rv = NSAERRCMAP;
  739. nsadbCloseCertUsers(authdb, 0);
  740. nserrGenerate(errp, rv, eid, NSAuth_Program, 1, adb->adb_dbname);
  741. goto punt;
  742. }
  743. NSAPI_PUBLIC int nsadbRemoveCert(NSErr_t * errp, void * authdb,
  744. void * username, CertObj_t * coptr)
  745. {
  746. AuthDB_t * adb = (AuthDB_t *)authdb;
  747. char * keyptr = 0; /* pointer to cert record key */
  748. int keylen; /* length of cert record key */
  749. int rv;
  750. int rv2;
  751. /* If a username is specified, require it to match */
  752. if (username && strcmp((char *)username, coptr->co_username)) {
  753. return 0;
  754. }
  755. /* Construct the record key from the certificate */
  756. rv = nsadbEncodeCertKey(&coptr->co_issuer, &coptr->co_subject,
  757. &keylen, &keyptr);
  758. if (adb->adb_certdb == NULL) {
  759. rv = nsadbOpenCerts(errp, authdb, ADBF_CWRITE);
  760. if (rv < 0) goto punt;
  761. }
  762. /* Remove the username-to-cert id entry from Certs.nm */
  763. rv = nsadbOpenCertUsers(errp, authdb, ADBF_CWRITE);
  764. if (rv < 0) goto punt;
  765. rv = nsadbRemoveCertUser(errp, authdb, coptr->co_username);
  766. nsadbCloseCertUsers(authdb, 0);
  767. /* Free the cert id value, if any */
  768. rv = 0;
  769. if (coptr->co_certid != 0) {
  770. rv = ndbFreeId(errp, adb->adb_certdb,
  771. keylen, keyptr, coptr->co_certid);
  772. }
  773. /* Delete the cert record */
  774. rv2 = ndbDeleteName(errp, adb->adb_certdb, 0, keylen, keyptr);
  775. punt:
  776. if (keyptr) {
  777. FREE(keyptr);
  778. }
  779. return (rv) ? rv : rv2;
  780. }
  781. NSAPI_PUBLIC int nsadbRemoveUserCert(NSErr_t * errp,
  782. void * authdb, char * username)
  783. {
  784. CertObj_t * coptr = 0;
  785. USI_t certid = 0;
  786. int rv;
  787. /*
  788. * Open for read access at first. We don't want to create the
  789. * database if it's not already there. This will do nothing
  790. * if the database is already open for write, since that implies
  791. * read access as well.
  792. */
  793. rv = nsadbOpenCertUsers(errp, authdb, ADBF_CREAD);
  794. if (rv < 0) goto punt;
  795. /* Find a certificate mapping id for the given username */
  796. rv = nsadbFindCertUser(errp, authdb, username, &certid);
  797. if (rv < 0) goto punt;
  798. /* Look up the mapping from the mapping id */
  799. rv = nsadbGetCertById(errp, authdb, certid, &coptr);
  800. if (rv < 0) goto punt;
  801. /* It's there, so remove it. This will re-open for write if needed. */
  802. rv = nsadbRemoveCert(errp, authdb, (void *)username, coptr);
  803. punt:
  804. if (coptr != 0) {
  805. nsadbFreeCertObj(coptr);
  806. }
  807. return rv;
  808. }
  809. #endif /* defined(CLIENT_AUTH) */