// Copyright (c) 2013 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.

// Chaps pam module unit tests. These tests exercise the pam module layer and
// use a mock for the login manager and pam helper.
//

#include <security/pam_appl.h>
#include <security/pam_modules.h>

#include <string>
#include <vector>

#include <brillo/secure_blob.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "chaps/chaps_utility.h"
#include "chaps/isolate_login_client_mock.h"
#include "chaps/pam_helper_mock.h"

using std::string;
using std::vector;
using brillo::SecureBlob;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Return;
using ::testing::SetArgPointee;

namespace chaps {

// Defined in chaps_pam_module.cc.
extern void EnableMock(IsolateLoginClient* login_client, PamHelper* pam_helper);
extern void DisableMock();

class TestPamModule : public ::testing::Test {
 protected:
  virtual void SetUp() {
    user_ = string("user");
    password_old_ = SecureBlob("password_old");
    password_new_ = SecureBlob("password_new");

    EnableMock(&login_client_mock_, &pam_helper_mock_);

    EXPECT_CALL(pam_helper_mock_, GetPamUser(_, _))
        .WillRepeatedly(DoAll(SetArgPointee<1>(user_), Return(true)));
    EXPECT_CALL(pam_helper_mock_, GetPamPassword(_, false, _))
        .WillRepeatedly(DoAll(SetArgPointee<2>(password_new_),
                              Return(true)));
    EXPECT_CALL(pam_helper_mock_, GetPamPassword(_, true, _))
        .WillRepeatedly(DoAll(SetArgPointee<2>(password_old_),
                              Return(true)));
    EXPECT_CALL(pam_helper_mock_, SaveUserAndPassword(_, user_, password_new_))
        .WillRepeatedly(Return(true));
    EXPECT_CALL(pam_helper_mock_,
                RetrieveUserAndPassword(_, _, _))
        .WillRepeatedly(DoAll(SetArgPointee<1>(user_),
                              SetArgPointee<2>(password_new_),
                              Return(true)));
    EXPECT_CALL(pam_helper_mock_, PutEnvironmentVariable(_, _, _))
        .WillRepeatedly(Return(true));
    EXPECT_CALL(pam_helper_mock_, GetEnvironmentVariable(_, _, _))
        .WillRepeatedly(DoAll(SetArgPointee<2>(string("1")),
                              Return(true)));
  }
  void TearDown() {
    DisableMock();
  }
  string user_;
  SecureBlob password_old_;
  SecureBlob password_new_;
  IsolateLoginClientMock login_client_mock_;
  PamHelperMock pam_helper_mock_;
};

TEST_F(TestPamModule, TestPamAuthenticateSuccess) {
  EXPECT_CALL(login_client_mock_, LoginUser(user_, password_new_))
      .WillOnce(Return(true));

  EXPECT_EQ(PAM_SUCCESS, pam_sm_authenticate(NULL, 0, 0, NULL));
  EXPECT_EQ(PAM_SUCCESS, pam_sm_open_session(NULL, 0, 0, NULL));
}

TEST_F(TestPamModule, TestPamOpenWithoutAuthenticate) {
  EXPECT_CALL(pam_helper_mock_, RetrieveUserAndPassword(_, _, _))
      .WillRepeatedly(Return(false));

  EXPECT_EQ(PAM_IGNORE, pam_sm_open_session(NULL, 0, 0, NULL));
}

TEST_F(TestPamModule, TestPamOpenWithoutDifferentUser) {
  EXPECT_CALL(pam_helper_mock_, GetPamUser(_, _))
      .WillOnce(DoAll(SetArgPointee<1>(user_), Return(true)))
      .WillRepeatedly(DoAll(SetArgPointee<1>(string("user_2")),
                            Return(true)));

  EXPECT_EQ(PAM_SUCCESS, pam_sm_authenticate(NULL, 0, 0, NULL));
  EXPECT_EQ(PAM_IGNORE, pam_sm_open_session(NULL, 0, 0, NULL));
}

TEST_F(TestPamModule, TestPamCloseSuccess) {
  EXPECT_CALL(login_client_mock_, LogoutUser(user_))
      .WillOnce(Return(true));

  EXPECT_EQ(PAM_SUCCESS, pam_sm_close_session(NULL, 0, 0, NULL));
}

TEST_F(TestPamModule, TestPamChangeAuthSuccess) {
  EXPECT_CALL(login_client_mock_, ChangeUserAuth(user_, password_old_,
                                                 password_new_))
      .WillOnce(Return(true));

  EXPECT_EQ(PAM_SUCCESS, pam_sm_chauthtok(NULL, PAM_UPDATE_AUTHTOK, 0, NULL));
}

TEST_F(TestPamModule, TestPamChangeAuthPrelimCheck) {
  EXPECT_EQ(PAM_IGNORE,
      pam_sm_chauthtok(NULL, PAM_PRELIM_CHECK | PAM_UPDATE_AUTHTOK, 0, NULL));
  EXPECT_EQ(PAM_IGNORE, pam_sm_chauthtok(NULL, 0, 0, NULL));
}

TEST_F(TestPamModule, TestPamChangeAuthFail) {
  EXPECT_CALL(pam_helper_mock_, GetPamPassword(_, true, _))
      .WillOnce(Return(false))
      .WillRepeatedly(DoAll(SetArgPointee<2>(password_old_),
                            Return(true)));
  EXPECT_CALL(pam_helper_mock_, GetPamPassword(_, false, _))
      .WillOnce(Return(false));

  EXPECT_EQ(PAM_AUTH_ERR, pam_sm_chauthtok(NULL, PAM_UPDATE_AUTHTOK, 0, NULL));
  EXPECT_EQ(PAM_AUTH_ERR, pam_sm_chauthtok(NULL, PAM_UPDATE_AUTHTOK, 0, NULL));
}

}  // namespace chaps

int main(int argc, char** argv) {
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}
