#include #include "KClientProfileIntf.h" KClientProfileInterface::KClientProfileInterface ( profile_t inProfileHandle): mProfile (inProfileHandle) { } KClientProfileInterface::KClientProfileInterface () { } KClientProfileInterface::~KClientProfileInterface () { } #ifdef KClientDeprecated_ void KClientProfileInterface::GetLocalRealm ( char* outRealm) const { UProfileInputList relation ( REALMS_V4_PROF_LIBDEFAULTS_SECTION, REALMS_V4_PROF_LOCAL_REALM ); UProfileOutputList values; mProfile.GetValues (relation, values); strncpy (outRealm, values [0], REALM_SZ); outRealm [REALM_SZ - 1] = 0; try { UProfileInputList relation ( "realms", outRealm, "v4_realm"); mProfile.GetValues (relation, values); // If we have a correpsonding v4 realm, that's good, if the realm is a valid v4 realm if (values [0] != nil) { strncpy (outRealm, values [0], REALM_SZ); outRealm [REALM_SZ - 1] = 0; } } catch (UProfileConfigurationError&) { // If we get a configuration error, there is no corresponding v4 realm } catch (...) { throw; } } void KClientProfileInterface::SetLocalRealm ( const char* inRealm) { UProfile::StProfileChanger profileChanger (mProfile); UProfileInputList relation ( REALMS_V4_PROF_LIBDEFAULTS_SECTION, REALMS_V4_PROF_LOCAL_REALM ); UProfileOutputList values; mProfile.GetValues (relation, values); UProfileInputString name (values [0]); UProfileInputString value (inRealm); mProfile.UpdateRelation (relation, name, value); } void KClientProfileInterface::GetRealmOfHost ( const char* inHost, char* outRealm) const { char* realm = krb_realmofhost (const_cast (inHost)); if ((realm == NULL) || (realm [0] == '\0')) DebugThrow_ (KClientRuntimeError (kcErrInvalidPreferences)); strncpy (outRealm, realm, REALM_SZ); outRealm [REALM_SZ - 1] = '\0'; } void KClientProfileInterface::AddRealmMap ( const char* inDomain, const char* inRealm) { UProfile::StProfileChanger profileChanger (mProfile); UProfileInputList relation ( REALMS_V4_PROF_DOMAIN_SECTION, inDomain ); UProfileOutputList values; // If it already exists, we change it (this is different from old behavior, which would // keep both, but that's just bogus. try { mProfile.GetValues (relation, values); mProfile.UpdateRelation (relation, values [0], inRealm); } catch (UProfileConfigurationError& e) { if (e.Error () != PROF_NO_RELATION) throw; mProfile.AddRelation (relation, inRealm); } } void KClientProfileInterface::DeleteRealmMap ( const char* inHost) { UProfile::StProfileChanger profileChanger (mProfile); UProfileInputList relation ( REALMS_V4_PROF_DOMAIN_SECTION, inHost ); mProfile.ClearRelation (relation); } void KClientProfileInterface::GetNthRealmMap ( SInt32 inIndex, char* outHost, char* outRealm) const { if (inIndex < 1) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthRealmMap: inIndex < 1")); UProfileInputList section ( REALMS_V4_PROF_DOMAIN_SECTION); UProfileOutputString name; UProfileOutputString value; UInt32 index = 0; Boolean found = false; UProfileIterator iterator = mProfile. NewIterator (section, PROFILE_ITER_LIST_SECTION); while (iterator.Next (name, value)) { index++; if ((SInt32) index == inIndex) { strncpy (outRealm, value.Get (), REALM_SZ); strncpy (outHost, name.Get (), MAXHOSTNAMELEN); outRealm [REALM_SZ - 1] = '\0'; outHost [MAXHOSTNAMELEN - 1] = '\0'; found = true; break; } } if (!found) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthRealmMap: inIndex too large")); } void KClientProfileInterface::GetNthServer ( SInt32 inIndex, const char* inRealm, Boolean inAdmin, char* outHost) const { if (inIndex < 1) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServer: inIndex < 1")); UProfileOutputString name; UProfileOutputString value; SInt32 index = 0; Boolean found = false; if (!inAdmin) { UProfileInputList kdcRelation ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_KDC ); UProfileIterator iterator = mProfile.NewIterator (kdcRelation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { index++; if (index == inIndex) { found = true; // Remove port from output UInt32 hostLength; char* colon = strchr (value.Get (), ':'); if (colon == nil) { hostLength = strlen (value.Get ()); } else { hostLength = (UInt32) (colon - value.Get ()); } if (hostLength > MAXHOSTNAMELEN - 1) hostLength = MAXHOSTNAMELEN - 1; strncpy (outHost, value.Get (), hostLength); outHost [hostLength] = '\0'; break; } } } else { UProfileInputList adminRelation ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_ADMIN_KDC ); UProfileIterator iterator = mProfile.NewIterator (adminRelation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { index++; if (index == inIndex) { found = true; strncpy (outHost, value.Get (), MAXHOSTNAMELEN); outHost [MAXHOSTNAMELEN - 1] = '\0'; break; } } } if (!found) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServer: inIndex too large")); } void KClientProfileInterface::AddServerMap ( const char* inHost, const char* inRealm, Boolean inAdmin) { UProfile::StProfileChanger profileChanger (mProfile); UProfileInputList kdcRelation ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_KDC ); UProfileOutputList values; UProfileOutputString name; UProfileOutputString value; // If it already exists, we do nothing. Existence check must parse hostname:port Boolean found = false; try { UProfileIterator iterator = mProfile.NewIterator (kdcRelation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { UInt32 hostLength; char* colon = strchr (value.Get (), ':'); if (colon == nil) { hostLength = strlen (value.Get ()); } else { hostLength = (UInt32) (colon - value.Get ()); } if (strncmp (inHost, value.Get (), hostLength) == 0) { found = true; break; } } } catch (UProfileConfigurationError& e) { if (e.Error () != PROF_NO_RELATION) throw; } if (!found) mProfile.AddRelation (kdcRelation, inHost); UProfileInputList adminRelation ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_ADMIN_KDC ); if (!inAdmin) { // If we are adding as non-admin a server that is already an admin, // remove it from admin found = false; UProfileIterator iterator = mProfile.NewIterator (adminRelation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { if (strcmp (inHost, value.Get ()) == 0) { mProfile.UpdateRelation (adminRelation, value, nil); break; } } return; } try { found = false; UProfileIterator iterator = mProfile.NewIterator (adminRelation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { if (strcmp (inHost, value.Get ()) == 0) { found = true; break; } } } catch (UProfileConfigurationError& e) { if (e.Error () != PROF_NO_RELATION) throw; } if (!found) mProfile.AddRelation (adminRelation, inHost); } void KClientProfileInterface::DeleteServerMap ( const char* inRealm, const char* inHost) { UProfile::StProfileChanger profileChanger (mProfile); UProfileInputList relation ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_KDC ); UProfileOutputString name; UProfileOutputString value; // This is annoying. Since KDCs are specified as hostname:port, I can't just // call UpdateRelation (nameServer, inHost, nil). I need to look at each KDC, // parse the hostname UProfileIterator iterator = mProfile.NewIterator (relation, PROFILE_ITER_RELATIONS_ONLY); while (iterator.Next (name, value)) { // Find : char* colon = strchr (value.Get (), ':'); if (colon != nil) { // : found, compare hostname UInt32 colonIndex = (UInt32) (colon - value.Get ()); if (strncmp (value.Get (), inHost, colonIndex) == 0) { mProfile.UpdateRelation (relation, value.Get (), nil); break; } } } // remove the corresponding admin entry, if it exists. admin entries don't have port. UProfileInputList nameAdmin ( REALMS_V4_PROF_REALMS_SECTION, inRealm, REALMS_V4_PROF_ADMIN_KDC ); try { mProfile.UpdateRelation (nameAdmin, inHost, nil); } catch (UProfileConfigurationError& e) { if (e.Error () != PROF_NO_RELATION) throw; } } /* One word: bogus! Whose idea was it to provide API to enumerate servers _and_ realms in * one call?! */ void KClientProfileInterface::GetNthServerMap ( SInt32 inIndex, char* outHost, char* outRealm, Boolean& outAdmin) const { if (inIndex < 1) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServerMap: inIndex < 1")); SInt32 index = 0; Boolean found = false; UProfileInputList realmRelation ( REALMS_V4_PROF_REALMS_SECTION ); UProfileIterator realmIterator = mProfile.NewIterator (realmRelation, PROFILE_ITER_LIST_SECTION); UProfileOutputString name; UProfileOutputString realmName; while (realmIterator.Next (realmName, name)) { // This inner block creates a new kdcIterator every time through the loop { UProfileInputList kdcRelation ( REALMS_V4_PROF_REALMS_SECTION, realmName.Get (), REALMS_V4_PROF_KDC ); UProfileIterator kdcIterator = mProfile.NewIterator (kdcRelation, PROFILE_ITER_RELATIONS_ONLY); UProfileOutputString kdcName; while (kdcIterator.Next (name, kdcName)) { index++; if (index == inIndex) { strncpy (outRealm, realmName.Get (), REALM_SZ); outRealm [REALM_SZ - 1] = '\0'; // Remove port from kdcName char* colon = strchr (kdcName.Get (), ':'); UInt32 hostLength; if (colon == nil) { hostLength = strlen (kdcName.Get ()); } else { hostLength = (UInt32) (colon - kdcName.Get ()); } if (hostLength > MAXHOSTNAMELEN - 1) hostLength = MAXHOSTNAMELEN - 1; strncpy (outHost, kdcName.Get (), hostLength); outHost [hostLength] = '\0'; found = true; break; } } if (found) break; } } if (!found) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServerMap: inIndex too large")); // If found, look if it's an admin server UProfileInputList adminRelation ( REALMS_V4_PROF_REALMS_SECTION, outRealm, REALMS_V4_PROF_ADMIN_KDC ); UProfileIterator adminIterator = mProfile.NewIterator (adminRelation, PROFILE_ITER_RELATIONS_ONLY); UProfileOutputString adminName; Boolean admin = false; while (adminIterator.Next (name, adminName)) { if (strcmp (adminName.Get (), outHost) == 0) { admin = true; } } outAdmin = admin; } UInt16 KClientProfileInterface::GetNthServerPort ( SInt32 inIndex) const { if (inIndex < 1) DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServerPort: inIndex < 1")); SInt32 index = 0; UProfileInputList realmRelation ( REALMS_V4_PROF_REALMS_SECTION ); UProfileIterator realmIterator = mProfile.NewIterator (realmRelation, PROFILE_ITER_LIST_SECTION); UProfileOutputString name; UProfileOutputString realmName; while (realmIterator.Next (realmName, name)) { // This inner block creates a new kdcIterator every time through the loop { UProfileInputList kdcRelation ( REALMS_V4_PROF_REALMS_SECTION, realmName.Get (), REALMS_V4_PROF_KDC ); UProfileIterator kdcIterator = mProfile.NewIterator (kdcRelation, PROFILE_ITER_RELATIONS_ONLY); UProfileOutputString kdcName; while (kdcIterator.Next (name, kdcName)) { index++; if (index == inIndex) { char* colon = strchr (kdcName.Get (), ':'); if (colon == nil) { // Is this correct? return 0; } else { return (UInt16) atoi (colon + 1); } } } } } DebugThrow_ (std::range_error ("KClientProfileInterface::GetNthServerPort: inIndex too large")); return 0; // silence the warning } void KClientProfileInterface::SetNthServerPort ( SInt32 inIndex, UInt16 inPort) { if (inIndex < 1) DebugThrow_ (std::range_error ("KClientProfileInterface::SetNthServerPort: inIndex < 1")); UProfile::StProfileChanger profileChanger (mProfile); SInt32 index = 0; Boolean found = false; UProfileInputList realmRelation ( REALMS_V4_PROF_REALMS_SECTION ); UProfileIterator realmIterator = mProfile.NewIterator (realmRelation, PROFILE_ITER_LIST_SECTION); UProfileOutputString name; UProfileOutputString realmName; while (realmIterator.Next (realmName, name)) { // This inner block creates a new kdcIterator every time through the loop { UProfileInputList kdcRelation ( REALMS_V4_PROF_REALMS_SECTION, realmName.Get (), REALMS_V4_PROF_KDC ); UProfileIterator kdcIterator = mProfile.NewIterator (kdcRelation, PROFILE_ITER_RELATIONS_ONLY); UProfileOutputString kdcName; while (kdcIterator.Next (name, kdcName)) { index++; if (index == inIndex) { char hostnameWithPort [MAXHOSTNAMELEN + 1 /* : */ + 5 /* port */]; char* colon = strchr (kdcName.Get (), ':'); UInt32 hostLength; if (colon == nil) { hostLength = strlen (kdcName.Get ()); } else { hostLength = (UInt32) (colon - kdcName.Get ()); } if (hostLength > MAXHOSTNAMELEN - 1) hostLength = MAXHOSTNAMELEN - 1; strncpy (hostnameWithPort, kdcName.Get (), hostLength); hostnameWithPort [hostLength] = '\0'; if (inPort != 0) { sprintf (hostnameWithPort + hostLength, ":%u", inPort); } mProfile.UpdateRelation (kdcRelation, kdcName, hostnameWithPort); found = true; break; } } if (found) break; } } if (!found) DebugThrow_ (std::range_error ("KClientProfileInterface::SetNthServerPort: inIndex too large")); } #endif // KClientDeprecated_