chromium/chrome/enterprise_companion/mac/mac_utils.mm

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/enterprise_companion/mac/mac_utils.h"

#include <CoreFoundation/CoreFoundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <Foundation/Foundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <sys/types.h>

#include <optional>

#include "base/apple/bridging.h"
#include "base/apple/foundation_util.h"
#include "base/apple/scoped_cftyperef.h"
#include "base/logging.h"
#include "chrome/enterprise_companion/enterprise_companion_branding.h"

namespace enterprise_companion {

std::optional<uid_t> GuessLoggedInUser() {
  base::apple::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate(
      nullptr, CFSTR(PRODUCT_FULLNAME_STRING), nullptr, nullptr));
  if (!store) {
    LOG(ERROR) << "SCDynamicStoreCreate failed";
    return std::nullopt;
  }

  base::apple::ScopedCFTypeRef<CFPropertyListRef> plist(
      SCDynamicStoreCopyValue(store.get(), CFSTR("State:/Users/ConsoleUser")));
  if (!plist) {
    LOG(ERROR) << "SCDynamicStoreCopyValue failed";
    return std::nullopt;
  }

  NSDictionary* plist_dict = base::apple::CFToNSPtrCast(
      base::apple::CFCast<CFDictionaryRef>(plist.get()));
  if (!plist_dict) {
    LOG(ERROR) << "plist not a dictionary.";
    return std::nullopt;
  }

  NSArray<NSDictionary*>* session_info_array =
      base::apple::ObjCCast<NSArray>(plist_dict[@"SessionInfo"]);
  if (!session_info_array) {
    LOG(ERROR) << "SessionInfo not NSArray";
    return std::nullopt;
  }

  for (NSDictionary* session_dict in session_info_array) {
    NSNumber* is_console_session = base::apple::ObjCCast<NSNumber>(
        session_dict[base::apple::CFToNSPtrCast(kCGSessionOnConsoleKey)]);
    if (!is_console_session) {
      LOG(ERROR) << "kCGSSessionOnConsoleKey not NSNumber";
      continue;
    }

    if (is_console_session.boolValue) {
      NSNumber* uid = base::apple::ObjCCast<NSNumber>(
          session_dict[base::apple::CFToNSPtrCast(kCGSessionUserIDKey)]);
      if (!uid) {
        LOG(ERROR) << "kCGSSessionUserIDKey not NSNumber";
        continue;
      }
      return uid.unsignedIntValue;
    }
  }

  return std::nullopt;
}

}  // namespace enterprise_companion