/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
**
** Licensed under the Apache License, Version 2.0 (the "License"); you may not
** use this file except in compliance with the License. You may obtain a copy
** of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABLITY OR NON-INFRINGEMENT.
**
** See the Apache 2 License for the specific language governing permissions
** and limitations under the License.
**
**==============================================================================
*/
#include <vector>
#include <set>
#include <cstdlib>
#include <iostream>
#include <ut/ut.h>
#include <unittest/utils.h>
#include <protocol/protocol.h>
#include <protocol/sock.h>
#include <base/base.h>
#include <base/paths.h>
#include <base/io.h>
#include <base/user.h>
#include <omiclient/client.h>
using namespace std;
using namespace mi;
inline std::ostream& operator << (std::ostream& ss, const String& str)
{
ss << str.Str();
return ss;
}
static Protocol* s_protocol;
static void setUp()
{
}
static void cleanup()
{
}
BEGIN_EXTERNC
static MI_Boolean _Callback(
Protocol* protocol,
Message* msg,
void* data)
{
data=data;
protocol = protocol;
msg = msg;
return MI_TRUE;
}
END_EXTERNC
struct ProvInfo
{
Uint32 pid_user, pid_requestor, pid_inproc;
String user_user, user_requestor, user_inproc;
String group_user, group_requestor, group_inproc;
};
static void _GetProvInfo(
Client& c,
ProvInfo& info)
{
/* enumerate instances and return values in 'info' struct
inproc/requestor/user */
const Uint64 TIMEOUT = 15 * 1000 * 1000;
Array<DInstance> instances_user, instances_inproc, instances_requestor;
MI_Result result;
UT_ASSERT(c.EnumerateInstances(T("oop/user/test/cpp"), T("x_numberworld"), true,
TIMEOUT, instances_user, String(), String(), result));
UT_ASSERT_EQUAL(result, MI_RESULT_OK);
UT_ASSERT(c.EnumerateInstances(T("oop/requestor/test/cpp"), T("x_numberworld"), true,
TIMEOUT, instances_requestor, String(), String(), result));
UT_ASSERT_EQUAL(result, MI_RESULT_OK);
UT_ASSERT(c.EnumerateInstances(T("test/cpp"), T("x_numberworld"), true,
TIMEOUT, instances_inproc, String(), String(), result));
UT_ASSERT_EQUAL(result, MI_RESULT_OK);
UT_ASSERT_EQUAL(instances_user.GetSize(), 1);
UT_ASSERT_EQUAL(instances_requestor.GetSize(), 1);
UT_ASSERT_EQUAL(instances_inproc.GetSize(), 1);
// extract pid, user, group from all and compare
bool null, key;
UT_ASSERT( instances_user[0].GetUint32("pid", info.pid_user, null, key));
UT_ASSERT( instances_requestor[0].GetUint32("pid", info.pid_requestor, null, key));
UT_ASSERT( instances_inproc[0].GetUint32("pid", info.pid_inproc, null, key));
UT_ASSERT( instances_user[0].GetString("user", info.user_user, null, key));
UT_ASSERT( instances_requestor[0].GetString("user", info.user_requestor, null, key));
UT_ASSERT( instances_inproc[0].GetString("user", info.user_inproc, null, key));
UT_ASSERT( instances_user[0].GetString("group", info.group_user, null, key));
UT_ASSERT( instances_requestor[0].GetString("group", info.group_requestor, null, key));
UT_ASSERT( instances_inproc[0].GetString("group", info.group_inproc, null, key));
/*if (result == MI_RESULT_OK)
{
for (Uint32 i = 0; i < instances_user.GetSize(); i++)
instances_user[i].Print();
}
if (result == MI_RESULT_OK)
{
for (Uint32 i = 0; i < instances_requestor.GetSize(); i++)
instances_requestor[i].Print();
}
if (result == MI_RESULT_OK)
{
for (Uint32 i = 0; i < instances_inproc.GetSize(); i++)
instances_inproc[i].Print();
}*/
}
static void TestAuthExplicitOOPModes()
{
/* use explicit credentials for pre-defined user */
Client c;
ProvInfo info;
const Uint64 TIMEOUT = 15 * 1000 * 1000;
string socketFile = GetPath(ID_SOCKETFILE);
UT_ASSERT(c.Connect(socketFile.c_str(), USER, PASSWORD, TIMEOUT));
_GetProvInfo(c, info);
// Expecting results:
// user/requestor should be the same (omi as user), in-proc expected to be root
UT_ASSERT_EQUAL(info.user_user, info.user_requestor);
UT_ASSERT_EQUAL(info.group_user, info.group_requestor);
UT_ASSERT_EQUAL(info.pid_user, info.pid_requestor);
UT_ASSERT_NOT_EQUAL(info.user_user, info.user_inproc);
UT_ASSERT_NOT_EQUAL(info.group_user, info.group_inproc);
UT_ASSERT_NOT_EQUAL(info.pid_user, info.pid_inproc);
}
static void TestAuthImplicitOOPModes()
{
/* use explicit credentials for pre-defined user */
Client c;
ProvInfo info;
const Uint64 TIMEOUT = 15 * 1000 * 1000;
string socketFile = GetPath(ID_SOCKETFILE);
UT_ASSERT(c.Connect(socketFile.c_str(), "", "", TIMEOUT));
_GetProvInfo(c, info);
// Expecting results:
// user should be omi,
// requestor/in-proc expected to be root
// all pids are dufferent
UT_ASSERT_NOT_EQUAL(info.user_user, info.user_requestor);
UT_ASSERT_NOT_EQUAL(info.group_user, info.group_requestor);
UT_ASSERT_NOT_EQUAL(info.pid_user, info.pid_requestor);
UT_ASSERT_EQUAL(info.user_requestor, info.user_inproc);
UT_ASSERT_EQUAL(info.group_requestor, info.group_inproc);
UT_ASSERT_NOT_EQUAL(info.pid_user, info.pid_inproc);
UT_ASSERT_NOT_EQUAL(info.pid_requestor, info.pid_inproc);
}
static void TestAuthInvalidPassword()
{
/* use explicit credentials for pre-defined user */
Client c;
const Uint64 TIMEOUT = 15 * 1000 * 1000;
string socketFile = GetPath(ID_SOCKETFILE);
Array<DInstance> instances_user;
MI_Result result = MI_RESULT_OK;
bool b = c.Connect(socketFile.c_str(), USER, "?", TIMEOUT);
//printf("b %d\n", (int)b);
b = b && c.EnumerateInstances(T("oop/user/test/cpp"), T("x_numberworld"), true, TIMEOUT, instances_user, String(), String(), result);
// connect maybe ok, since it only tracks socket connection, but enumerate must fail
// printf("res %d, size %d\n", result, instances_user.GetSize());
UT_ASSERT(!b);
UT_ASSERT(instances_user.GetSize() == 0);
}
static void TestAuthNoPassword()
{
/* use explicit credentials for pre-defined user */
Client c;
const Uint64 TIMEOUT = 15 * 1000 * 1000;
string socketFile = GetPath(ID_SOCKETFILE);
Array<DInstance> instances_user;
MI_Result result = MI_RESULT_OK;
bool b = c.Connect(socketFile.c_str(), USER, "", TIMEOUT);
//printf("b %d\n", (int)b);
b = b && c.EnumerateInstances(T("oop/user/test/cpp"), T("x_numberworld"), true, TIMEOUT, instances_user, String(), String(), result);
// connect maybe ok, since it only tracks socket connection, but enumerate must fail
// printf("res %d, size %d\n", result, instances_user.GetSize());
UT_ASSERT(!b);
UT_ASSERT(instances_user.GetSize() == 0);
}
static void AllProviderTests()
{
/* Enable auth so we can verify pre-conditions */
IgnoreAuthCalls(0);
// these tests can be executed only when unit-test is 'root'
// and user omi exists
if (0 != IsRoot())
{
UT_WARNING("auth tests skipped - root level required");
return;
}
if (0 != AuthenticateUser(USER, PASSWORD))
{
UT_WARNING("auth tests skipped - user " USER "/" PASSWORD " not found");
return;
}
Sock_Start();
StartServerAndConnect(false, _Callback, &s_protocol);
UT_TEST(TestAuthExplicitOOPModes);
UT_TEST(TestAuthImplicitOOPModes);
UT_TEST(TestAuthInvalidPassword);
UT_TEST(TestAuthNoPassword);
StopServerAndDisconnect(&s_protocol);
Sock_Stop();
}
UT_ENTRY_POINT(AllProviderTests);