Exemplo n.º 1
0
/**
 * Returns the total number of PTS users, belonging to the cell denoted
 * by cellHandle, that are not in KAS.
 *
 *  env      the Java environment
 *  cls      the current Java class
 *  cellHandle    the handle of the cell to which the users belong
 *  returns total number of users that are in PTS and not KAS
 */
JNIEXPORT jint JNICALL 
Java_org_openafs_jafs_Cell_getPtsOnlyUserCount (JNIEnv *env, jclass cls, 
						   jlong cellHandle) {

  afs_status_t ast;
  void *iterationId;
  kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
  kas_principalEntry_t kasEntry;
  char *userName;
  int i = 0;

  if( !who ) {
    throwAFSException( env, JAFSADMNOMEM );
    return -1;
  }

  if( !pts_UserListBegin( (void *) cellHandle, &iterationId, &ast ) ) {
    free( who );
    throwAFSException( env, ast );
    return -1;
  }

  userName = malloc( sizeof(char)*PTS_MAX_NAME_LEN);
    
  if( !userName ) {
    free( who );
    throwAFSException( env, JAFSADMNOMEM );
    return -1;
  }

  while ( pts_UserListNext( (void *) iterationId, userName, &ast ) ) {
    if( strcmp( userName, "anonymous" ) != 0 ) {
      // make sure the name is within the allowed bounds
      if( strlen( userName ) > KAS_MAX_NAME_LEN ) {
	    free( who );
	    free( userName );
	    throwAFSException( env, ADMPTSUSERNAMETOOLONG );
	    return -1;
	  }
  
      // if there is a kas entry, recurse
      internal_makeKasIdentity( userName, who );
      if( !kas_PrincipalGet( (void *) cellHandle, NULL, who, 
			     &kasEntry, &ast ) ) i++;
	}
  }

  free( userName );
  free( who );

  if( ast != ADMITERATORDONE ) {
    throwAFSException( env, ast );
    return -1;
  }

  return i;
}
Exemplo n.º 2
0
BOOL AfsAppLib_IsUserAdmin (UINT_PTR hCreds, LPTSTR pszUser)
{
#ifndef USE_KASERVER
    return TRUE;
#else
   BOOL rc = FALSE;
   afs_status_t status;

   UINT_PTR idClient;
   if ((idClient = AfsAppLib_GetAdminServerClientID()) != 0)
      {
      TCHAR szCell[ cchRESOURCE ];
      TCHAR szUser[ cchRESOURCE ];
      SYSTEMTIME stExpire;
      if (asc_CredentialsCrack (idClient, hCreds, szCell, szUser, &stExpire, (ULONG*)&status))
         {
         ASID idCell;
         if (asc_CellOpen (idClient, hCreds, szCell, AFSADMSVR_SCOPE_USERS, &idCell, (ULONG*)&status))
            {
            ASID idUser;
            if (asc_ObjectFind (idClient, idCell, TYPE_USER, pszUser, &idUser, (ULONG*)&status))
               {
               ASOBJPROP Info;
               if (asc_ObjectPropertiesGet (idClient, GET_ALL_DATA, idCell, idUser, &Info, (ULONG*)&status))
                  {
                  if (Info.u.UserProperties.fHaveKasInfo)
                     {
                     rc = Info.u.UserProperties.KASINFO.fIsAdmin;
                     }
                  }
               }
            asc_CellClose (idClient, idCell, (ULONG*)&status);
            }
         }
      }
   else if (OpenClientLibrary())
      {
      if (OpenKasLibrary())
         {
         char szUserA[ cchRESOURCE ], szUser2A[ cchRESOURCE ];
         char szCellA[ cchRESOURCE ];
         unsigned long dateExpire;
         int fHasKasToken;

         if (afsclient_TokenQuery (hCreds, &dateExpire, szUserA, szUser2A, szCellA, &fHasKasToken, (afs_status_p)&status))
            {
            PVOID hCell;
            if (afsclient_CellOpen (szCellA, hCreds, &hCell, &status))
               {
               kas_identity_t Identity;
               memset (&Identity, 0x00, sizeof(Identity));
               CopyStringToAnsi (Identity.principal, pszUser);

               kas_principalEntry_t Entry;
               if (kas_PrincipalGet (hCell, NULL, &Identity, &Entry, &status))
                  {
                  if (Entry.adminSetting == KAS_ADMIN)
                     rc = TRUE;
                  }

               afsclient_CellClose (hCell, (afs_status_p)&status);
               }
            }

         CloseKasLibrary();
         }

      CloseClientLibrary();
      }

   return rc;
#endif /* USE_KASERVER */
}
Exemplo n.º 3
0
/**
 * Renames the given user.  Does not update the info fields of the kas entry
 *  -- the calling code is responsible for that.
 *
 * env      the Java environment
 * cls      the current Java class
 * cellHandle    the handle of the cell to which the user belongs
 * joldName     the name of the user to rename
 * jnewName     the new name for the user
 */
JNIEXPORT void JNICALL 
Java_org_openafs_jafs_User_rename
  (JNIEnv *env, jclass cls, jlong cellHandle, jstring joldName, jstring jnewName)
{

    const char *oldName;
    const char *newName;
    kas_identity_p whoOld = (kas_identity_p) malloc( sizeof(kas_identity_t) );
    kas_identity_p whoNew = (kas_identity_p) malloc( sizeof(kas_identity_t) );
    kas_principalEntry_t kasEntry;
    pts_UserEntry_t ptsEntry;
    afs_status_t ast;
    int kas;

    if( !whoOld || !whoNew ) {
      if( whoOld ) {
	free( whoOld );
      }
      if( whoNew ) {
	free( whoNew );
      } 
      throwAFSException( env, JAFSADMNOMEM );
      return;    
    }

    if( joldName != NULL ) {
	oldName = (*env)->GetStringUTFChars(env, joldName, 0);
	if( !oldName ) {
	    throwAFSException( env, JAFSADMNOMEM );
	    return;    
	}
    } else {
	oldName = NULL;
    }
    if( jnewName != NULL ) {
	newName = (*env)->GetStringUTFChars(env, jnewName, 0);
	if( !newName ) {
	  if( oldName != NULL ) {
	    (*env)->ReleaseStringUTFChars(env, joldName, oldName);
	  }
	  throwAFSException( env, JAFSADMNOMEM );
	  return;    
	}
    } else {
	newName = NULL;
    }

    // make sure the names are within the allowed bounds
    if( oldName != NULL && strlen( oldName ) > KAS_MAX_NAME_LEN ) {
	free( whoOld );
	free( whoNew );
	if( oldName != NULL ) {
	    (*env)->ReleaseStringUTFChars(env, joldName, oldName);
	}
	if( newName != NULL ) {
	    (*env)->ReleaseStringUTFChars(env, jnewName, newName);
	}
	throwAFSException( env, ADMPTSUSERNAMETOOLONG );
	return;
    }
    if( newName != NULL && strlen( newName ) > KAS_MAX_NAME_LEN ) {
	free( whoOld );
	free( whoNew );
	if( oldName != NULL ) {
	    (*env)->ReleaseStringUTFChars(env, joldName, oldName);
	}
	if( newName != NULL ) {
	    (*env)->ReleaseStringUTFChars(env, jnewName, newName);
	}
	throwAFSException( env, ADMPTSUSERNAMETOOLONG );
	return;
    }
    
    if( oldName != NULL ) {
	internal_makeKasIdentity( oldName, whoOld );
    }
    if( newName != NULL ) {
	internal_makeKasIdentity( newName, whoNew );
    }

    // retrieve the old kas info
    if( !kas_PrincipalGet( (void *) cellHandle, NULL, whoOld, 
			   &kasEntry, &ast ) ) {
	if( ast != KANOENT ) {
	    free( whoOld );
	    free( whoNew );
	    if( oldName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, joldName, oldName);
	    }
	    if( newName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, jnewName, newName);
	    }
	    throwAFSException( env, ast );
	    return;
	} else {
	    kas = FALSE;
	}
    } else {
	kas = TRUE;
    }   
	
    if( kas ) {
	// create a new kas entry
	// temporarily set the password equal to the new name
	if (!kas_PrincipalCreate( (void *) cellHandle, NULL, whoNew, 
				  newName, &ast ) ) {	    
	    free( whoOld );
	    free( whoNew );
	    if( oldName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, joldName, oldName);
	    }
	    if( newName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, jnewName, newName);
	    }
	    throwAFSException( env, ast );
	    return;
	} 

	// set the password 
	ast = 0;
	// For some reason kas_PrincipalKeySet doesn't set the return code 
	// correctly.  It always returns 0.
	// So instead of checking the return code, we see if there's an 
	// error in the status variable.
	kas_PrincipalKeySet( (void *) cellHandle, NULL, whoNew, 0, 
			     &(kasEntry.key), &ast );
	if( ast ) {
	    afs_status_t ast_kd;
	    kas_PrincipalDelete( (void *) cellHandle, NULL, whoNew, &ast_kd );
	    free( whoOld );
	    free( whoNew );
	    if( oldName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, joldName, oldName);
	    }
	    if( newName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, jnewName, newName);
	    }
	    throwAFSException( env, ast );
	    return;
	}
    }

    // rename the pts entry
    if( !pts_UserRename( (void *) cellHandle, oldName, newName, &ast ) ) {
	// throw exception if there was no such pts user only if 
        // there was also no such kas user
	if( (ast == ADMPTSFAILEDNAMETRANSLATE && !kas ) || 
	    ast != ADMPTSFAILEDNAMETRANSLATE ) {
	    afs_status_t ast_kd;
	    if( kas ) {
		kas_PrincipalDelete( (void *) cellHandle, NULL, whoNew, 
				     &ast_kd );
	    }
	    free( whoOld );
	    free( whoNew );
	    if( oldName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, joldName, oldName);
	    }
	    if( newName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, jnewName, newName);
	    }
	    throwAFSException( env, ast );
	    return;
	}
    }

    if( kas ) {
	// delete the old kas entry
	if( !kas_PrincipalDelete( (void *) cellHandle, NULL, whoOld, &ast ) ) {
	    free( whoOld );
	    free( whoNew );
	    if( oldName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, joldName, oldName);
	    }
	    if( newName != NULL ) {
		(*env)->ReleaseStringUTFChars(env, jnewName, newName);
	    }
	    throwAFSException( env, ast );
	    return;
	}
    }    

    free( whoOld );
    free( whoNew );
    if( oldName != NULL ) {
	(*env)->ReleaseStringUTFChars(env, joldName, oldName);
    }
    if( newName != NULL ) {
	(*env)->ReleaseStringUTFChars(env, jnewName, newName);
    }
}
Exemplo n.º 4
0
/**
 * Retrieve the information for the specified user and populate the
 * given object
 *
 * env      the Java environment
 * cellHandle    the handle of the cell to which the user belongs
 * name      the name of the user for which to get the info
 * user      the User object to populate with the info
 */
void getUserInfoChar
  (JNIEnv *env, void *cellHandle, const char *name, jobject user)
{
  jstring jowner;
  jstring jcreator;
  jstring jlastModName;
  jstring jencryptionKey;
  jboolean pts;
  jboolean kas;
  pts_UserEntry_t ptsEntry;
  afs_status_t ast;
  kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
  kas_principalEntry_t kasEntry;
  unsigned int lockedUntil;

  if( !who ) {
    throwAFSException( env, JAFSADMNOMEM );
    return;    
  }

  // make sure the name is within the allowed bounds
  if( name != NULL && strlen( name ) > KAS_MAX_NAME_LEN ) {
    free( who );
    throwAFSException( env, ADMPTSUSERNAMETOOLONG );
    return;
  }
  
  if( name != NULL ) {
      internal_makeKasIdentity( name, who );
  }

  // get all the field ids, if you haven't done so already
  if( userCls == 0 ) {
    internal_getUserClass( env, user );
  }

  // get the pts entry
  if ( !pts_UserGet( cellHandle, name, &ptsEntry, &ast ) ) {
    // if the user has no pts ptsEntry
    if( ast == ADMPTSFAILEDNAMETRANSLATE ) {
	pts = FALSE;	
    } else {
	free( who );
	throwAFSException( env, ast );
	return;
    }
  } else {
      pts = TRUE;
  }
  

  // get the kas entry
  if( !kas_PrincipalGet( cellHandle, NULL, who, &kasEntry, &ast ) ) {
    // no kas entry
    if( ast == KANOENT ) { 
	if( !pts ) {
	    free( who );
	    throwAFSException( env, ast );
	    return;
	} else {
	    kas = FALSE;
	}
    // other
    } else {
	free( who );
	throwAFSException( env, ast );
	return;
    }
  } else {
      kas = TRUE;
  }

  // get the lock status
  if( kas && !kas_PrincipalLockStatusGet( cellHandle, NULL, who, 
					  &lockedUntil, &ast ) ) {
    free( who );
    throwAFSException( env, ast );
    return;
  }

  (*env)->SetBooleanField(env, user, user_ptsField, pts);
  (*env)->SetBooleanField(env, user, user_kasField, kas);

  // set the pts fields
  if( pts ) {
      (*env)->SetIntField(env, user, user_nameUidField, ptsEntry.nameUid);
      (*env)->SetIntField(env, user, user_ownerUidField, ptsEntry.ownerUid);
      (*env)->SetIntField(env, user, user_creatorUidField, 
			  ptsEntry.creatorUid);
      (*env)->SetIntField(env, user, user_groupCreationQuotaField, 
			  ptsEntry.groupCreationQuota);
      (*env)->SetIntField(env, user, user_groupMembershipCountField, 
			  ptsEntry.groupMembershipCount);
      
      if( ptsEntry.listStatus == PTS_USER_OWNER_ACCESS ) {
	  (*env)->SetIntField(env, user, user_listStatusField, 
			      org_openafs_jafs_User_USER_OWNER_ACCESS);
      } else {
	  (*env)->SetIntField(env, user, user_listStatusField, 
			      org_openafs_jafs_User_USER_ANYUSER_ACCESS);
      }
      if( ptsEntry.listGroupsOwned == PTS_USER_OWNER_ACCESS ) {
	  (*env)->SetIntField(env, user, user_listGroupsOwnedField, 
			      org_openafs_jafs_User_USER_OWNER_ACCESS);
      } else {
	  (*env)->SetIntField(env, user, user_listGroupsOwnedField, 
			      org_openafs_jafs_User_USER_ANYUSER_ACCESS);
      }
      if( ptsEntry.listMembership == PTS_USER_OWNER_ACCESS ) {
	  (*env)->SetIntField(env, user, user_listMembershipField, 
			      org_openafs_jafs_User_USER_OWNER_ACCESS);
      } else {
	  (*env)->SetIntField(env, user, user_listMembershipField, 
			      org_openafs_jafs_User_USER_ANYUSER_ACCESS);
      }
      
      jowner = (*env)->NewStringUTF(env, ptsEntry.owner);
      jcreator =  (*env)->NewStringUTF(env, ptsEntry.creator);
      
      (*env)->SetObjectField(env, user, user_ownerField, jowner);
      (*env)->SetObjectField(env, user, user_creatorField, jcreator);

  }

  // set the kas fields
  if( kas ) {
      char *convertedKey;
      int i;
      if( kasEntry.adminSetting == KAS_ADMIN ) {
	  (*env)->SetIntField(env, user, user_adminSettingField, 
			      org_openafs_jafs_User_ADMIN);
      } else {
	  (*env)->SetIntField(env, user, user_adminSettingField, 
			      org_openafs_jafs_User_NO_ADMIN);
      }
      if( kasEntry.tgsSetting == TGS ) {
	  (*env)->SetIntField(env, user, user_tgsSettingField, 
			      org_openafs_jafs_User_GRANT_TICKETS);
      } else {
	  (*env)->SetIntField(env, user, user_tgsSettingField, 
			      org_openafs_jafs_User_NO_GRANT_TICKETS);
      }
      if( kasEntry.encSetting != NO_ENCRYPT ) {
	  (*env)->SetIntField(env, user, user_encSettingField, 
			      org_openafs_jafs_User_ENCRYPT);
      } else {
	  (*env)->SetIntField(env, user, user_encSettingField, 
			      org_openafs_jafs_User_NO_ENCRYPT);
      }
      if( kasEntry.cpwSetting == CHANGE_PASSWORD ) {
	  (*env)->SetIntField(env, user, user_cpwSettingField, 
			      org_openafs_jafs_User_CHANGE_PASSWORD);
      } else {
	  (*env)->SetIntField(env, user, user_cpwSettingField, 
			      org_openafs_jafs_User_NO_CHANGE_PASSWORD);
      }
      if( kasEntry.rpwSetting == REUSE_PASSWORD ) {
	  (*env)->SetIntField(env, user, user_rpwSettingField, 
			      org_openafs_jafs_User_REUSE_PASSWORD);
      } else {
	  (*env)->SetIntField(env, user, user_rpwSettingField, 
			      org_openafs_jafs_User_NO_REUSE_PASSWORD);
      }
      (*env)->SetIntField(env, user, user_userExpirationField, 
			  kasEntry.userExpiration);
      (*env)->SetIntField(env, user, user_lastModTimeField, 
			  kasEntry.lastModTime);
      (*env)->SetIntField(env, user, user_lastChangePasswordTimeField, 
			  kasEntry.lastChangePasswordTime);
      (*env)->SetIntField(env, user, user_maxTicketLifetimeField, 
			  kasEntry.maxTicketLifetime);
      (*env)->SetIntField(env, user, user_keyVersionField, 
			  kasEntry.keyVersion);
      (*env)->SetLongField(env, user, user_keyCheckSumField, 
			   (unsigned int) kasEntry.keyCheckSum);
      (*env)->SetIntField(env, user, user_daysToPasswordExpireField, 
			  kasEntry.daysToPasswordExpire);
      (*env)->SetIntField(env, user, user_failLoginCountField, 
			  kasEntry.failLoginCount);
      (*env)->SetIntField(env, user, user_lockTimeField, kasEntry.lockTime);
      (*env)->SetIntField(env, user, user_lockedUntilField, lockedUntil);
      
      jlastModName = (*env)->NewStringUTF(env, 
					  kasEntry.lastModPrincipal.principal);
      (*env)->SetObjectField(env, user, user_lastModNameField, jlastModName);

      convertedKey = (char *) malloc( sizeof(char *)*
				      (sizeof(kasEntry.key.key)*4+1) );
      if( !convertedKey ) {
	throwAFSException( env, JAFSADMNOMEM );
	return;    
      }
      for( i = 0; i < sizeof(kasEntry.key.key); i++ ) {
	sprintf( &(convertedKey[i*4]), "\\%0.3o", kasEntry.key.key[i] );
      }
      jencryptionKey =  (*env)->NewStringUTF(env, convertedKey);
      (*env)->SetObjectField(env, user, user_encryptionKeyField, 
			     jencryptionKey);
      free( convertedKey );
  }
  free(who);
}
Exemplo n.º 5
0
/**
 * Fills the next pts user (who does not have a kas entry) object of 
 * the cell.  Returns 0 if there are no more users, != 0 otherwise.
 *
 *  env      the Java environment
 *  cls      the current Java class
 *  cellHandle    the handle of the cell to which the users belong
 *  iterationId   the iteration ID of this iteration
 *  juserObject   a User object to be populated with the values of 
 *                  the next pts (with no kas) user
 *  returns 0 if there are no more users, != 0 otherwise
 */
JNIEXPORT jint JNICALL 
Java_org_openafs_jafs_Cell_getPtsOnlyUsersNext (JNIEnv *env, jclass cls, 
						   jlong cellHandle, 
						   jlong iterationId, 
						   jobject juserObject ) {

  kas_identity_p who = (kas_identity_p) malloc( sizeof(kas_identity_t) );
  kas_principalEntry_t kasEntry;
  afs_status_t ast;
  char *userName;
  jstring juser;

  if( !who ) {
    throwAFSException( env, JAFSADMNOMEM );
    return 0;    
  }
  
  userName = malloc( sizeof(char)*PTS_MAX_NAME_LEN);

  if( !userName ) {
    free( who );
    throwAFSException( env, JAFSADMNOMEM );
    return 0;    
  }

  while( 1 ) {

      if( !pts_UserListNext( (void *) iterationId, userName, &ast ) ) {
	  free( userName );
	  free( who );
	  if( ast == ADMITERATORDONE ) {
	      return 0;
	  } else {
	      throwAFSException( env, ast );
	      return 0;
	  }
      }
      
      if( strcmp( userName, "anonymous" ) == 0 ) {
	  continue;
      }
      
      // make sure the name is within the allowed bounds
      if( strlen( userName ) > KAS_MAX_NAME_LEN ) {
	  free( userName );
	  free( who );
	  throwAFSException( env, ADMPTSUSERNAMETOOLONG );
	  return 0;
      }
      
      if( userCls == 0 ) {
	  internal_getUserClass( env, juserObject );
      }
      
      
      // if there is a kas entry, recurse
      internal_makeKasIdentity( userName, who );
      if( kas_PrincipalGet( (void *) cellHandle, NULL, who, 
			    &kasEntry, &ast ) ) {
	  continue;
      } 
      
      juser = (*env)->NewStringUTF(env, userName);
      
      (*env)->SetObjectField(env, juserObject, user_nameField, juser);
      getUserInfoChar( env, (void *) cellHandle, userName, juserObject );
      (*env)->SetBooleanField( env, juserObject, user_cachedInfoField, TRUE );
      
      free( who );
      free( userName );
      return 1;
      
  }

}
Exemplo n.º 6
0
/*
 * cfg_HostSetAfsPrincipal() -- Put AFS server principal (afs) key in
 *     host's KeyFile; principal is created if it does not exist.
 *
 *     If first server host in cell, passwd must be initial password for
 *     the afs principal; the afs principal is created.
 *
 *     If additional server host, passwd can be specified or NULL; the
 *     afs principal must already exist by definition.  If passwd is NULL
 *     then an attempt is made to fetch the afs key.  If the key fetch fails
 *     because pre 3.5 database servers are in use (which will only return a
 *     key checksum) then the function fails with a return status of
 *     ADMCFGAFSKEYNOTAVAILABLE; in this case the function should be called
 *     again with passwd specified.  If passwd is specified (not NULL) but the
 *     password key fails a checksum comparison with the current afs key
 *     then the function fails with a return status of ADMCFGAFSPASSWDINVALID.
 *
 * ASSUMPTIONS: Client configured and BOS server started; if first host in
 *     cell then Authentication server must be started as well.
 */
int ADMINAPI
cfg_HostSetAfsPrincipal(void *hostHandle,	/* host config handle */
			short isFirst,	/* first server in cell flag */
			const char *passwd,	/* afs initial password */
			afs_status_p st)
{				/* completion status */
    int rc = 1;
    afs_status_t tst2, tst = 0;
    cfg_host_p cfg_host = (cfg_host_p) hostHandle;

    /* validate parameters */

    if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
	tst = tst2;
    } else if ((isFirst && passwd == NULL)
	       || (passwd != NULL && *passwd == '\0')) {
	tst = ADMCFGPASSWDNULL;
    }

    /* put afs key in host's KeyFile */

    if (tst == 0) {
	kas_identity_t afsIdentity;
	kas_encryptionKey_t afsKey;
	int afsKvno = 0;

	strcpy(afsIdentity.principal, "afs");
	afsIdentity.instance[0] = '\0';

	if (isFirst) {
	    /* create afs principal */
	    if (!kas_PrincipalCreate
		(cfg_host->cellHandle, NULL, &afsIdentity, passwd, &tst2)
		&& tst2 != KAEXIST) {
		/* failed to create principal (and not because existed) */
		tst = tst2;
	    }
	}

	if (tst == 0) {
	    /* retrive afs principal information to verify or obtain key */
	    kas_principalEntry_t afsEntry;

	    if (!kas_PrincipalGet
		(cfg_host->cellHandle, NULL, &afsIdentity, &afsEntry,
		 &tst2)) {
		tst = tst2;
	    } else {
		if (passwd != NULL) {
		    /* password given; form key and verify as most recent */
		    kas_encryptionKey_t passwdKey;
		    unsigned int passwdKeyCksum;

		    if (!kas_StringToKey
			(cfg_host->cellName, passwd, &passwdKey, &tst2)
			|| !kas_KeyCheckSum(&passwdKey, &passwdKeyCksum,
					    &tst2)) {
			/* failed to form key or key checksum */
			tst = tst2;

		    } else if (passwdKeyCksum != afsEntry.keyCheckSum) {
			/* passwd string does not generate most recent key;
			 * check if passwd string embeds key directly.
			 */
			if (KasKeyEmbeddedInString(passwd, &passwdKey)) {
			    /* passwd string embeds kas key */
			    if (!kas_KeyCheckSum
				(&passwdKey, &passwdKeyCksum, &tst2)) {
				tst = tst2;
			    } else if (passwdKeyCksum != afsEntry.keyCheckSum) {
				/* passwd string does not embed valid key */
				tst = ADMCFGAFSPASSWDINVALID;
			    }
			} else {
			    /* passwd string does NOT embed key */
			    tst = ADMCFGAFSPASSWDINVALID;
			}
		    }

		    if (tst == 0) {
			/* passwd seems to generate/embed most recent key */
			afsKey = passwdKey;
			afsKvno = afsEntry.keyVersion;
		    }

		} else {
		    /* password NOT given; check if key retrieved since
		     * pre 3.5 database servers only return key checksum
		     */
		    if (KasKeyIsZero(&afsEntry.key)) {
			tst = ADMCFGAFSKEYNOTAVAILABLE;
		    } else {
			afsKey = afsEntry.key;
			afsKvno = afsEntry.keyVersion;
		    }
		}
	    }
	}

	if (tst == 0) {
	    /* add key to host's KeyFile; RPC must be unauthenticated;
	     * bosserver is presumed to be in noauth mode.
	     */
	    void *cellHandle, *bosHandle;

	    if (!afsclient_NullCellOpen(&cellHandle, &tst2)) {
		tst = tst2;
	    } else {
		if (!bos_ServerOpen
		    (cellHandle, cfg_host->hostName, &bosHandle, &tst2)) {
		    tst = tst2;
		} else {
		    if (!bos_KeyCreate(bosHandle, afsKvno, &afsKey, &tst2)
			&& tst2 != BZKEYINUSE) {
			/* failed to add key (and not because existed) */
			tst = tst2;
		    }

		    if (!bos_ServerClose(bosHandle, &tst2)) {
			tst = tst2;
		    }
		}

		if (!afsclient_CellClose(cellHandle, &tst2)) {
		    tst = tst2;
		}
	    }
	}
    }

    if (tst != 0) {
	rc = 0;
    }
    if (st != NULL) {
	*st = tst;
    }
    return rc;
}