154925bf6Swillf /*
254925bf6Swillf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
354925bf6Swillf  * Use is subject to license terms.
454925bf6Swillf  */
554925bf6Swillf 
654925bf6Swillf /*
754925bf6Swillf  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
854925bf6Swillf  *
954925bf6Swillf  *	Openvision retains the copyright to derivative works of
1054925bf6Swillf  *	this source code.  Do *NOT* create a derivative of this
1154925bf6Swillf  *	source code before consulting with your legal department.
1254925bf6Swillf  *	Do *NOT* integrate *ANY* of this source code into another
1354925bf6Swillf  *	product before consulting with your legal department.
1454925bf6Swillf  *
1554925bf6Swillf  *	For further information, read the top-level Openvision
1654925bf6Swillf  *	copyright which is contained in the top-level MIT Kerberos
1754925bf6Swillf  *	copyright.
1854925bf6Swillf  *
1954925bf6Swillf  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
2054925bf6Swillf  *
2154925bf6Swillf  */
2254925bf6Swillf 
2354925bf6Swillf 
2454925bf6Swillf /*
2554925bf6Swillf  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
2654925bf6Swillf  */
2754925bf6Swillf 
2854925bf6Swillf #include	<sys/file.h>
2954925bf6Swillf #include	<fcntl.h>
3054925bf6Swillf #include	<unistd.h>
3154925bf6Swillf #include        <k5-int.h>
3254925bf6Swillf #include	"policy_db.h"
3354925bf6Swillf #include	<stdlib.h>
3454925bf6Swillf #include        <db.h>
3554925bf6Swillf 
3654925bf6Swillf #define MAX_LOCK_TRIES 5
3754925bf6Swillf 
3854925bf6Swillf struct _locklist {
3954925bf6Swillf      osa_adb_lock_ent lockinfo;
4054925bf6Swillf      struct _locklist *next;
4154925bf6Swillf };
4254925bf6Swillf 
osa_adb_create_db(char * filename,char * lockfilename,int magic)4354925bf6Swillf krb5_error_code osa_adb_create_db(char *filename, char *lockfilename,
4454925bf6Swillf 				  int magic)
4554925bf6Swillf {
4654925bf6Swillf      int lf;
4754925bf6Swillf      DB *db;
4854925bf6Swillf      BTREEINFO btinfo;
4954925bf6Swillf 
5054925bf6Swillf      memset(&btinfo, 0, sizeof(btinfo));
5154925bf6Swillf      btinfo.flags = 0;
5254925bf6Swillf      btinfo.cachesize = 0;
5354925bf6Swillf      btinfo.psize = 4096;
5454925bf6Swillf      btinfo.lorder = 0;
5554925bf6Swillf      btinfo.minkeypage = 0;
5654925bf6Swillf      btinfo.compare = NULL;
5754925bf6Swillf      btinfo.prefix = NULL;
5854925bf6Swillf      db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
5954925bf6Swillf      if (db == NULL)
6054925bf6Swillf 	  return errno;
6154925bf6Swillf      if (db->close(db) < 0)
6254925bf6Swillf 	  return errno;
6354925bf6Swillf 
6454925bf6Swillf      /* only create the lock file if we successfully created the db */
6554925bf6Swillf      lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
6654925bf6Swillf      if (lf == -1)
6754925bf6Swillf 	  return errno;
6854925bf6Swillf      (void) close(lf);
6954925bf6Swillf 
7054925bf6Swillf      return OSA_ADB_OK;
7154925bf6Swillf }
7254925bf6Swillf 
osa_adb_destroy_db(char * filename,char * lockfilename,int magic)7354925bf6Swillf krb5_error_code osa_adb_destroy_db(char *filename, char *lockfilename,
7454925bf6Swillf 				 int magic)
7554925bf6Swillf {
7654925bf6Swillf      /* the admin databases do not contain security-critical data */
7754925bf6Swillf      if (unlink(filename) < 0 ||
7854925bf6Swillf 	 unlink(lockfilename) < 0)
7954925bf6Swillf 	  return errno;
8054925bf6Swillf      return OSA_ADB_OK;
8154925bf6Swillf }
8254925bf6Swillf 
osa_adb_rename_db(char * filefrom,char * lockfrom,char * fileto,char * lockto,int magic)8354925bf6Swillf krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom,
8454925bf6Swillf 				char *fileto, char *lockto, int magic)
8554925bf6Swillf {
8654925bf6Swillf      osa_adb_db_t fromdb, todb;
8754925bf6Swillf      krb5_error_code ret;
8854925bf6Swillf 
8954925bf6Swillf      /* make sure todb exists */
9054925bf6Swillf      /*LINTED*/
9154925bf6Swillf      if ((ret = osa_adb_create_db(fileto, lockto, magic)) &&
9254925bf6Swillf 	 ret != EEXIST)
9354925bf6Swillf 	  return ret;
9454925bf6Swillf 
9554925bf6Swillf      if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic)))
9654925bf6Swillf 	  return ret;
9754925bf6Swillf      if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) {
9854925bf6Swillf 	  (void) osa_adb_fini_db(fromdb, magic);
9954925bf6Swillf 	  return ret;
10054925bf6Swillf      }
10154925bf6Swillf      if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) {
10254925bf6Swillf 	  (void) osa_adb_fini_db(fromdb, magic);
10354925bf6Swillf 	  (void) osa_adb_fini_db(todb, magic);
10454925bf6Swillf 	  return ret;
10554925bf6Swillf      }
10654925bf6Swillf      if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) {
10754925bf6Swillf 	  (void) osa_adb_fini_db(fromdb, magic);
10854925bf6Swillf 	  (void) osa_adb_fini_db(todb, magic);
10954925bf6Swillf 	  return ret;
11054925bf6Swillf      }
11154925bf6Swillf      if ((rename(filefrom, fileto) < 0)) {
11254925bf6Swillf 	  (void) osa_adb_fini_db(fromdb, magic);
11354925bf6Swillf 	  (void) osa_adb_fini_db(todb, magic);
11454925bf6Swillf 	  return errno;
11554925bf6Swillf      }
11654925bf6Swillf      /*
11754925bf6Swillf       * Do not release the lock on fromdb because it is being renamed
11854925bf6Swillf       * out of existence; no one can ever use it again.
11954925bf6Swillf       */
12054925bf6Swillf      if ((ret = osa_adb_release_lock(todb))) {
12154925bf6Swillf 	  (void) osa_adb_fini_db(fromdb, magic);
12254925bf6Swillf 	  (void) osa_adb_fini_db(todb, magic);
12354925bf6Swillf 	  return ret;
12454925bf6Swillf      }
12554925bf6Swillf 
12654925bf6Swillf      (void) osa_adb_fini_db(fromdb, magic);
12754925bf6Swillf      (void) osa_adb_fini_db(todb, magic);
12854925bf6Swillf      return 0;
12954925bf6Swillf }
13054925bf6Swillf 
osa_adb_init_db(osa_adb_db_t * dbp,char * filename,char * lockfilename,int magic)13154925bf6Swillf krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
13254925bf6Swillf 			      char *lockfilename, int magic)
13354925bf6Swillf {
13454925bf6Swillf      osa_adb_db_t db;
13554925bf6Swillf      static struct _locklist *locklist = NULL;
13654925bf6Swillf      struct _locklist *lockp;
13754925bf6Swillf      krb5_error_code code;
13854925bf6Swillf 
13954925bf6Swillf      if (dbp == NULL || filename == NULL)
14054925bf6Swillf 	  return EINVAL;
14154925bf6Swillf 
14254925bf6Swillf      db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
14354925bf6Swillf      if (db == NULL)
14454925bf6Swillf 	  return ENOMEM;
14554925bf6Swillf 
14654925bf6Swillf      memset(db, 0, sizeof(*db));
14754925bf6Swillf      db->info.hash = NULL;
14854925bf6Swillf      db->info.bsize = 256;
14954925bf6Swillf      db->info.ffactor = 8;
15054925bf6Swillf      db->info.nelem = 25000;
15154925bf6Swillf      db->info.lorder = 0;
15254925bf6Swillf 
15354925bf6Swillf      db->btinfo.flags = 0;
15454925bf6Swillf      db->btinfo.cachesize = 0;
15554925bf6Swillf      db->btinfo.psize = 4096;
15654925bf6Swillf      db->btinfo.lorder = 0;
15754925bf6Swillf      db->btinfo.minkeypage = 0;
15854925bf6Swillf      db->btinfo.compare = NULL;
15954925bf6Swillf      db->btinfo.prefix = NULL;
16054925bf6Swillf      /*
16154925bf6Swillf       * A process is allowed to open the same database multiple times
16254925bf6Swillf       * and access it via different handles.  If the handles use
16354925bf6Swillf       * distinct lockinfo structures, things get confused: lock(A),
16454925bf6Swillf       * lock(B), release(B) will result in the kernel unlocking the
16554925bf6Swillf       * lock file but handle A will still think the file is locked.
16654925bf6Swillf       * Therefore, all handles using the same lock file must share a
16754925bf6Swillf       * single lockinfo structure.
16854925bf6Swillf       *
16954925bf6Swillf       * It is not sufficient to have a single lockinfo structure,
17054925bf6Swillf       * however, because a single process may also wish to open
17154925bf6Swillf       * multiple different databases simultaneously, with different
17254925bf6Swillf       * lock files.  This code used to use a single static lockinfo
17354925bf6Swillf       * structure, which means that the second database opened used
17454925bf6Swillf       * the first database's lock file.  This was Bad.
17554925bf6Swillf       *
17654925bf6Swillf       * We now maintain a linked list of lockinfo structures, keyed by
17754925bf6Swillf       * lockfilename.  An entry is added when this function is called
17854925bf6Swillf       * with a new lockfilename, and all subsequent calls with that
17954925bf6Swillf       * lockfilename use the existing entry, updating the refcnt.
18054925bf6Swillf       * When the database is closed with fini_db(), the refcnt is
18154925bf6Swillf       * decremented, and when it is zero the lockinfo structure is
18254925bf6Swillf       * freed and reset.  The entry in the linked list, however, is
18354925bf6Swillf       * never removed; it will just be reinitialized the next time
18454925bf6Swillf       * init_db is called with the right lockfilename.
18554925bf6Swillf       */
18654925bf6Swillf 
18754925bf6Swillf      /* find or create the lockinfo structure for lockfilename */
18854925bf6Swillf      lockp = locklist;
18954925bf6Swillf      while (lockp) {
19054925bf6Swillf 	  if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
19154925bf6Swillf 	       break;
19254925bf6Swillf 	  else
19354925bf6Swillf 	       lockp = lockp->next;
19454925bf6Swillf      }
19554925bf6Swillf      if (lockp == NULL) {
19654925bf6Swillf 	  /* doesn't exist, create it, add to list */
19754925bf6Swillf 	  lockp = (struct _locklist *) malloc(sizeof(*lockp));
19854925bf6Swillf 	  if (lockp == NULL) {
19954925bf6Swillf 	       free(db);
20054925bf6Swillf 	       return ENOMEM;
20154925bf6Swillf 	  }
20254925bf6Swillf 	  memset(lockp, 0, sizeof(*lockp));
20354925bf6Swillf 	  lockp->next = locklist;
20454925bf6Swillf 	  locklist = lockp;
20554925bf6Swillf      }
20654925bf6Swillf 
20754925bf6Swillf      /* now initialize lockp->lockinfo if necessary */
20854925bf6Swillf      if (lockp->lockinfo.lockfile == NULL) {
20954925bf6Swillf 	  if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) {
21054925bf6Swillf 	       free(db);
21154925bf6Swillf 	       return((krb5_error_code) code);
21254925bf6Swillf 	  }
21354925bf6Swillf 
21454925bf6Swillf 	  /*
21554925bf6Swillf 	   * needs be open read/write so that write locking can work with
21654925bf6Swillf 	   * POSIX systems
21754925bf6Swillf 	   */
21854925bf6Swillf 	  lockp->lockinfo.filename = strdup(lockfilename);
21954925bf6Swillf 	  if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+F")) == NULL) {
22054925bf6Swillf 	       /*
22154925bf6Swillf 		* maybe someone took away write permission so we could only
22254925bf6Swillf 		* get shared locks?
22354925bf6Swillf 		*/
22454925bf6Swillf 	       if ((lockp->lockinfo.lockfile = fopen(lockfilename, "rF"))
22554925bf6Swillf 		   == NULL) {
22654925bf6Swillf 		    free(db);
22754925bf6Swillf 		    return OSA_ADB_NOLOCKFILE;
22854925bf6Swillf 	       }
22954925bf6Swillf 	  }
23054925bf6Swillf 	  lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
23154925bf6Swillf      }
23254925bf6Swillf 
23354925bf6Swillf      /* lockp is set, lockinfo is initialized, update the reference count */
23454925bf6Swillf      db->lock = &lockp->lockinfo;
23554925bf6Swillf      db->lock->refcnt++;
23654925bf6Swillf 
23754925bf6Swillf      db->opencnt = 0;
23854925bf6Swillf      db->filename = strdup(filename);
23954925bf6Swillf      db->magic = magic;
24054925bf6Swillf 
24154925bf6Swillf      *dbp = db;
24254925bf6Swillf 
24354925bf6Swillf      return OSA_ADB_OK;
24454925bf6Swillf }
24554925bf6Swillf 
osa_adb_fini_db(osa_adb_db_t db,int magic)24654925bf6Swillf krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic)
24754925bf6Swillf {
24854925bf6Swillf      if (db->magic != magic)
24954925bf6Swillf 	  return EINVAL;
25054925bf6Swillf      if (db->lock->refcnt == 0) {
25154925bf6Swillf 	  /* barry says this can't happen */
25254925bf6Swillf 	  return OSA_ADB_FAILURE;
25354925bf6Swillf      } else {
25454925bf6Swillf 	  db->lock->refcnt--;
25554925bf6Swillf      }
25654925bf6Swillf 
25754925bf6Swillf      if (db->lock->refcnt == 0) {
25854925bf6Swillf 	  /*
25954925bf6Swillf 	   * Don't free db->lock->filename, it is used as a key to
26054925bf6Swillf 	   * find the lockinfo entry in the linked list.  If the
26154925bf6Swillf 	   * lockfile doesn't exist, we must be closing the database
26254925bf6Swillf 	   * after trashing it.  This has to be allowed, so don't
26354925bf6Swillf 	   * generate an error.
26454925bf6Swillf 	   */
26554925bf6Swillf 	  if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT)
26654925bf6Swillf 	       (void) fclose(db->lock->lockfile);
26754925bf6Swillf 	  db->lock->lockfile = NULL;
26854925bf6Swillf 	  krb5_free_context(db->lock->context);
26954925bf6Swillf      }
27054925bf6Swillf 
27154925bf6Swillf      db->magic = 0;
27254925bf6Swillf      free(db->filename);
27354925bf6Swillf      free(db);
27454925bf6Swillf      return OSA_ADB_OK;
27554925bf6Swillf }
27654925bf6Swillf 
osa_adb_get_lock(osa_adb_db_t db,int mode)27754925bf6Swillf krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode)
27854925bf6Swillf {
27954925bf6Swillf      int tries, gotlock, perm, krb5_mode, ret = 0;
28054925bf6Swillf 
28154925bf6Swillf      if (db->lock->lockmode >= mode) {
28254925bf6Swillf 	  /* No need to upgrade lock, just incr refcnt and return */
28354925bf6Swillf 	  db->lock->lockcnt++;
28454925bf6Swillf 	  return(OSA_ADB_OK);
28554925bf6Swillf      }
28654925bf6Swillf 
28754925bf6Swillf      perm = 0;
28854925bf6Swillf      switch (mode) {
28954925bf6Swillf 	case KRB5_DB_LOCKMODE_PERMANENT:
29054925bf6Swillf 	  perm = 1;
291*0b16192fSToomas Soome 	/* FALLTHROUGH */
29254925bf6Swillf 	case KRB5_DB_LOCKMODE_EXCLUSIVE:
29354925bf6Swillf 	  krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
29454925bf6Swillf 	  break;
29554925bf6Swillf 	case KRB5_DB_LOCKMODE_SHARED:
29654925bf6Swillf 	  krb5_mode = KRB5_LOCKMODE_SHARED;
29754925bf6Swillf 	  break;
29854925bf6Swillf 	default:
29954925bf6Swillf 	  return(EINVAL);
30054925bf6Swillf      }
30154925bf6Swillf 
30254925bf6Swillf      for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
30354925bf6Swillf 	  if ((ret = krb5_lock_file(db->lock->context,
30454925bf6Swillf 				    fileno(db->lock->lockfile),
30554925bf6Swillf 				    krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) {
30654925bf6Swillf 	       gotlock++;
30754925bf6Swillf 	       break;
30854925bf6Swillf 	  } else if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
30954925bf6Swillf 	       /* tried to exclusive-lock something we don't have */
31054925bf6Swillf 	       /* write access to */
31154925bf6Swillf 	       return OSA_ADB_NOEXCL_PERM;
31254925bf6Swillf 
31354925bf6Swillf 	  sleep(1);
31454925bf6Swillf      }
31554925bf6Swillf 
31654925bf6Swillf      /* test for all the likely "can't get lock" error codes */
31754925bf6Swillf      if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
31854925bf6Swillf 	  return OSA_ADB_CANTLOCK_DB;
31954925bf6Swillf      else if (ret != 0)
32054925bf6Swillf 	  return ret;
32154925bf6Swillf 
32254925bf6Swillf      /*
32354925bf6Swillf       * If the file no longer exists, someone acquired a permanent
32454925bf6Swillf       * lock.  If that process terminates its exclusive lock is lost,
32554925bf6Swillf       * but if we already had the file open we can (probably) lock it
32654925bf6Swillf       * even though it has been unlinked.  So we need to insist that
32754925bf6Swillf       * it exist.
32854925bf6Swillf       */
32954925bf6Swillf      if (access(db->lock->filename, F_OK) < 0) {
33054925bf6Swillf 	  (void) krb5_lock_file(db->lock->context,
33154925bf6Swillf 				fileno(db->lock->lockfile),
33254925bf6Swillf 				KRB5_LOCKMODE_UNLOCK);
33354925bf6Swillf 	  return OSA_ADB_NOLOCKFILE;
33454925bf6Swillf      }
33554925bf6Swillf 
33654925bf6Swillf      /* we have the shared/exclusive lock */
33754925bf6Swillf 
33854925bf6Swillf      if (perm) {
33954925bf6Swillf 	  if (unlink(db->lock->filename) < 0) {
34054925bf6Swillf 	       /* somehow we can't delete the file, but we already */
34154925bf6Swillf 	       /* have the lock, so release it and return */
34254925bf6Swillf 
34354925bf6Swillf 	       ret = errno;
34454925bf6Swillf 	       (void) krb5_lock_file(db->lock->context,
34554925bf6Swillf 				     fileno(db->lock->lockfile),
34654925bf6Swillf 				     KRB5_LOCKMODE_UNLOCK);
34754925bf6Swillf 
34854925bf6Swillf 	       /* maybe we should return CANTLOCK_DB.. but that would */
34954925bf6Swillf 	       /* look just like the db was already locked */
35054925bf6Swillf 	       return ret;
35154925bf6Swillf 	  }
35254925bf6Swillf 
35354925bf6Swillf 	  /* this releases our exclusive lock.. which is okay because */
35454925bf6Swillf 	  /* now no one else can get one either */
35554925bf6Swillf 	  (void) fclose(db->lock->lockfile);
35654925bf6Swillf      }
35754925bf6Swillf 
35854925bf6Swillf      db->lock->lockmode = mode;
35954925bf6Swillf      db->lock->lockcnt++;
36054925bf6Swillf      return OSA_ADB_OK;
36154925bf6Swillf }
36254925bf6Swillf 
osa_adb_release_lock(osa_adb_db_t db)36354925bf6Swillf krb5_error_code osa_adb_release_lock(osa_adb_db_t db)
36454925bf6Swillf {
36554925bf6Swillf      int ret, fd;
36654925bf6Swillf 
36754925bf6Swillf      if (!db->lock->lockcnt)		/* lock already unlocked */
36854925bf6Swillf 	  return OSA_ADB_NOTLOCKED;
36954925bf6Swillf 
37054925bf6Swillf      if (--db->lock->lockcnt == 0) {
37154925bf6Swillf 	  if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
37254925bf6Swillf 	       /* now we need to create the file since it does not exist */
37354925bf6Swillf                fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
37454925bf6Swillf                                    0600);
37554925bf6Swillf 	       if ((db->lock->lockfile = fdopen(fd, "w+F")) == NULL)
37654925bf6Swillf 		    return OSA_ADB_NOLOCKFILE;
37754925bf6Swillf 	  } else if ((ret = krb5_lock_file(db->lock->context,
37854925bf6Swillf 					  fileno(db->lock->lockfile),
37954925bf6Swillf 					  KRB5_LOCKMODE_UNLOCK)))
38054925bf6Swillf 	       return ret;
38154925bf6Swillf 
38254925bf6Swillf 	  db->lock->lockmode = 0;
38354925bf6Swillf      }
38454925bf6Swillf      return OSA_ADB_OK;
38554925bf6Swillf }
38654925bf6Swillf 
osa_adb_open_and_lock(osa_adb_princ_t db,int locktype)38754925bf6Swillf krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
38854925bf6Swillf {
38954925bf6Swillf      int ret;
39054925bf6Swillf 
39154925bf6Swillf      ret = osa_adb_get_lock(db, locktype);
39254925bf6Swillf      if (ret != OSA_ADB_OK)
39354925bf6Swillf 	  return ret;
39454925bf6Swillf      if (db->opencnt)
39554925bf6Swillf 	  goto open_ok;
39654925bf6Swillf 
39754925bf6Swillf      db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
39854925bf6Swillf      if (db->db != NULL)
39954925bf6Swillf 	 goto open_ok;
40054925bf6Swillf      switch (errno) {
40154925bf6Swillf #ifdef EFTYPE
40254925bf6Swillf      case EFTYPE:
40354925bf6Swillf #endif
40454925bf6Swillf      case EINVAL:
40554925bf6Swillf 	  db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
40654925bf6Swillf 	  if (db->db != NULL)
40754925bf6Swillf 	       goto open_ok;
408*0b16192fSToomas Soome 	  /* FALLTHROUGH */
40954925bf6Swillf      default:
41054925bf6Swillf 	  (void) osa_adb_release_lock(db);
41154925bf6Swillf 	  if (errno == EINVAL)
41254925bf6Swillf 	       return OSA_ADB_BAD_DB;
41354925bf6Swillf 	  return errno;
41454925bf6Swillf      }
41554925bf6Swillf open_ok:
41654925bf6Swillf      db->opencnt++;
41754925bf6Swillf      return OSA_ADB_OK;
41854925bf6Swillf }
41954925bf6Swillf 
osa_adb_close_and_unlock(osa_adb_princ_t db)42054925bf6Swillf krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db)
42154925bf6Swillf {
42254925bf6Swillf      if (--db->opencnt)
42354925bf6Swillf 	  return osa_adb_release_lock(db);
42454925bf6Swillf      if(db->db != NULL && db->db->close(db->db) == -1) {
42554925bf6Swillf 	  (void) osa_adb_release_lock(db);
42654925bf6Swillf 	  return OSA_ADB_FAILURE;
42754925bf6Swillf      }
42854925bf6Swillf 
42954925bf6Swillf      db->db = NULL;
43054925bf6Swillf 
43154925bf6Swillf      return(osa_adb_release_lock(db));
43254925bf6Swillf }
433