blob: 973840d3fc9736054feaabdeb9f36707736813b2 [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos_login_helpers.h" // NOLINT
#include <base/basictypes.h>
#include <base/logging.h>
#include <base/string_util.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <chromeos/dbus/dbus.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/glib/object.h>
#include <chromeos/string.h>
#include <vector>
#include "marshal.glibmarshal.h" // NOLINT
namespace {
#define SCOPED_SAFE_MESSAGE(e) (e->message ? e->message : "unknown error")
struct RetrievePropertyContext {
RetrievePropertyContext(const char* name,
chromeos::RetrievePropertyCallback cb,
void* data)
: property_name(name),
callback(cb),
user_data(data),
proxy(chromeos::ChromeOSLoginHelpers::CreateProxy()) {
}
std::string property_name;
chromeos::RetrievePropertyCallback callback;
void* user_data;
chromeos::dbus::Proxy proxy;
};
void RetrievePropertyNotify(DBusGProxy* proxy,
DBusGProxyCall* call_id,
void* user_data) {
RetrievePropertyContext* context =
static_cast<RetrievePropertyContext*>(user_data);
DCHECK(context);
chromeos::glib::ScopedError error;
gchar* value;
GArray* sig;
if (!::dbus_g_proxy_end_call(proxy,
call_id,
&chromeos::Resetter(&error).lvalue(),
G_TYPE_STRING, &value,
DBUS_TYPE_G_UCHAR_ARRAY, &sig,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerRetrieveProperty
<< " failed: " << SCOPED_SAFE_MESSAGE(error);
context->callback(context->user_data, false, NULL);
} else {
chromeos::CryptoBlob sig_blob = {
reinterpret_cast<const uint8*>(sig->data),
sig->len
};
chromeos::Property property = {
context->property_name.c_str(),
value,
&sig_blob
};
context->callback(context->user_data, true, &property);
g_array_free(sig, true);
g_free(value);
}
}
void FreeRetrievePropertyContext(gpointer data) {
delete static_cast<RetrievePropertyContext*>(data);
}
} // namespace
namespace chromeos { // NOLINT
ChromeOSLoginHelpers::ChromeOSLoginHelpers() {}
ChromeOSLoginHelpers::~ChromeOSLoginHelpers() {}
// static
dbus::Proxy ChromeOSLoginHelpers::CreateProxy() {
dbus::BusConnection bus = dbus::GetSystemBusConnection();
return dbus::Proxy(bus,
login_manager::kSessionManagerServiceName,
login_manager::kSessionManagerServicePath,
login_manager::kSessionManagerInterface);
}
// Memory allocated by this method should be freed with delete, not delete [].
// static
uint8* ChromeOSLoginHelpers::NewBufferCopy(const uint8* x, int len) {
uint8* result = static_cast<uint8*>(::operator new(len));
std::memcpy(result, x, len);
return result;
}
// static
GArray* ChromeOSLoginHelpers::CreateGArrayFromBytes(const uint8* in,
const int in_len) {
GArray* ary = g_array_sized_new(FALSE, FALSE, 1, in_len);
g_array_append_vals(ary, in, in_len);
return ary;
}
// static
bool ChromeOSLoginHelpers::CheckWhitelistHelper(const char* email,
GArray** sig) {
dbus::Proxy proxy = CreateProxy();
glib::ScopedError error;
if (!::dbus_g_proxy_call(proxy.gproxy(),
login_manager::kSessionManagerCheckWhitelist,
&Resetter(&error).lvalue(),
G_TYPE_STRING, email,
G_TYPE_INVALID,
DBUS_TYPE_G_UCHAR_ARRAY, sig,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerCheckWhitelist << " failed: "
<< SCOPED_SAFE_MESSAGE(error);
return false;
}
return true;
}
// static
bool ChromeOSLoginHelpers::EnumerateWhitelistedHelper(gchar*** whitelisted) {
dbus::Proxy proxy = ChromeOSLoginHelpers::CreateProxy();
glib::ScopedError error;
if (!::dbus_g_proxy_call(proxy.gproxy(),
login_manager::kSessionManagerEnumerateWhitelisted,
&Resetter(&error).lvalue(),
G_TYPE_INVALID,
G_TYPE_STRV, whitelisted,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerEnumerateWhitelisted
<< " failed: " << SCOPED_SAFE_MESSAGE(error);
return false;
}
return true;
}
// static
void ChromeOSLoginHelpers::RequestRetrievePropertyHelper(const char* name,
RetrievePropertyCallback callback, void* user_data) {
RetrievePropertyContext* context = new RetrievePropertyContext(name,
callback, user_data);
DBusGProxyCall* call_id = ::dbus_g_proxy_begin_call(context->proxy.gproxy(),
login_manager::kSessionManagerRetrieveProperty,
&RetrievePropertyNotify,
context,
&FreeRetrievePropertyContext,
G_TYPE_STRING, name,
G_TYPE_INVALID);
if (!call_id) {
LOG(WARNING) << login_manager::kSessionManagerRetrieveProperty
<< " dbus_g_proxy_begin_call failed";
delete context;
callback(user_data, false, NULL);
}
}
// static
bool ChromeOSLoginHelpers::RetrievePropertyHelper(const char* name,
gchar** value,
GArray** sig) {
dbus::Proxy proxy = ChromeOSLoginHelpers::CreateProxy();
glib::ScopedError error;
if (!::dbus_g_proxy_call(proxy.gproxy(),
login_manager::kSessionManagerRetrieveProperty,
&Resetter(&error).lvalue(),
G_TYPE_STRING, name,
G_TYPE_INVALID,
G_TYPE_STRING, value,
DBUS_TYPE_G_UCHAR_ARRAY, sig,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerRetrieveProperty
<< " failed: " << SCOPED_SAFE_MESSAGE(error);
return false;
}
return true;
}
// static
bool ChromeOSLoginHelpers::SetOwnerKeyHelper(GArray* key_der) {
dbus::Proxy proxy = ChromeOSLoginHelpers::CreateProxy();
glib::ScopedError error;
if (!::dbus_g_proxy_call(proxy.gproxy(),
login_manager::kSessionManagerSetOwnerKey,
&Resetter(&error).lvalue(),
DBUS_TYPE_G_UCHAR_ARRAY, key_der,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerSetOwnerKey << " failed: "
<< SCOPED_SAFE_MESSAGE(error);
return false;
}
return true;
}
// static
bool ChromeOSLoginHelpers::StorePropertyHelper(const char* name,
const char* value,
GArray* sig) {
dbus::Proxy proxy = ChromeOSLoginHelpers::CreateProxy();
glib::ScopedError error;
if (!::dbus_g_proxy_call(proxy.gproxy(),
login_manager::kSessionManagerStoreProperty,
&Resetter(&error).lvalue(),
G_TYPE_STRING, name,
G_TYPE_STRING, value,
DBUS_TYPE_G_UCHAR_ARRAY, sig,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
LOG(WARNING) << login_manager::kSessionManagerStoreProperty << " failed: "
<< SCOPED_SAFE_MESSAGE(error);
return false;
}
return true;
}
// static
bool ChromeOSLoginHelpers::WhitelistOpHelper(
const char* op,
const char* email,
const std::vector<uint8>& signature) {
dbus::Proxy proxy = ChromeOSLoginHelpers::CreateProxy();
glib::ScopedError error;
GArray* sig = CreateGArrayFromBytes(&signature[0], signature.size());
bool rv = true;
if (!::dbus_g_proxy_call(proxy.gproxy(),
op,
&Resetter(&error).lvalue(),
G_TYPE_STRING, email,
DBUS_TYPE_G_UCHAR_ARRAY, sig,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
LOG(WARNING) << op << " failed: " << SCOPED_SAFE_MESSAGE(error);
rv = false;
}
g_array_free(sig, TRUE);
return rv;
}
// static
CryptoBlob* ChromeOSLoginHelpers::CreateCryptoBlob(GArray* in) {
CryptoBlob* blob = new CryptoBlob;
blob->length = in->len;
blob->data = ChromeOSLoginHelpers::NewBufferCopy(
reinterpret_cast<const uint8*>(in->data), in->len);
return blob;
}
// static
Property* ChromeOSLoginHelpers::CreateProperty(const char* name,
const gchar* value,
GArray* sig) {
Property* prop = new Property;
prop->signature = CreateCryptoBlob(sig);
prop->name = NewStringCopy(name);
prop->value = NewStringCopy(value);
return prop;
}
// static
UserList* ChromeOSLoginHelpers::CreateUserList(const char* const* users) {
UserList* list = new UserList;
list->users = NULL;
for (list->num_users = 0; users[list->num_users] != NULL; list->num_users++)
;
list->users = static_cast<const char**>(
::operator new(sizeof(char*) * (list->num_users + 1)));
list->users[list->num_users] = NULL;
for (int i = 0; users[i] != NULL; ++i)
list->users[i] = NewStringCopy(users[i]);
return list;
}
// These Free* methods all use delete (as opposed to delete []) on purpose,
// following the pattern established by code that uses NewStringCopy.
// static
void ChromeOSLoginHelpers::FreeCryptoBlob(CryptoBlob* blob) {
delete blob->data;
delete blob;
}
// static
void ChromeOSLoginHelpers::FreeProperty(Property* property) {
FreeCryptoBlob(property->signature);
delete property->name;
delete property->value;
}
// static
void ChromeOSLoginHelpers::FreeUserList(UserList* userlist) {
for (int i = 0; i < userlist->num_users; ++i)
delete userlist->users[i];
delete userlist->users;
delete userlist;
}
} // namespace chromeos