~brandontschaefer/unity/bump-to-new-nux-abi

« back to all changes in this revision

Viewing changes to lockscreen/UserAuthenticatorPam.cpp

  • Committer: Andrea Azzarone
  • Date: 2013-12-28 17:34:36 UTC
  • mto: (3566.5.438 unity)
  • mto: This revision was merged to the branch mainline in revision 3703.
  • Revision ID: azzaronea@gmail.com-20131228173436-jqschonskxaj5xx3
Initial commit for the unity lockscreen. UserAuthenticator added with tests too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
 
2
/*
 
3
 * Copyright (C) 2013 Canonical Ltd
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 3 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 *
 
17
 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
 
18
 */
 
19
 
 
20
// Kindly inspired by user_authenticator_linux.cc of chromium project
 
21
// TODO (andy) Would be nice to make it more thread-safe and to imporve 
 
22
// the API and the cody style
 
23
#include "UserAuthenticatorPam.h"
 
24
 
 
25
#include <security/pam_appl.h>
 
26
#include <UnityCore/GLibWrapper.h>
 
27
 
 
28
namespace unity
 
29
{
 
30
namespace lockscreen
 
31
{
 
32
 
 
33
bool UserAuthenticatorPam::AuthenticateStart(std::string const& username,
 
34
                                             std::string const& password,
 
35
                                             AuthenticateEndCallback authenticate_cb)
 
36
{
 
37
  username_ = username;
 
38
  password_ = password;
 
39
  authenticate_cb_ = authenticate_cb;
 
40
 
 
41
  // FIXME: would be nice to support a fallback in case PAM
 
42
  // is not available.
 
43
  if (!InitPam())
 
44
    return false;
 
45
 
 
46
  glib::Object<GTask> task(g_task_new(nullptr, nullptr, [] (GObject*, GAsyncResult*, gpointer data) {
 
47
    auto self = static_cast<UserAuthenticatorPam*>(data);
 
48
    pam_end(self->pam_handle_, self->status_);
 
49
    self->authenticate_cb_(self->status_ == PAM_SUCCESS);
 
50
  }, this));
 
51
 
 
52
  g_task_set_task_data(task, this, nullptr);
 
53
 
 
54
  g_task_run_in_thread(task, [] (GTask* task, gpointer, gpointer data, GCancellable*) {
 
55
    auto self = static_cast<UserAuthenticatorPam*>(data);
 
56
    self->status_ = pam_authenticate(self->pam_handle_, 0);
 
57
  });
 
58
 
 
59
  return true;
 
60
}
 
61
 
 
62
bool UserAuthenticatorPam::InitPam()
 
63
{
 
64
  pam_conv conversation;
 
65
  conversation.conv = ConverationFunction;
 
66
  conversation.appdata_ptr = static_cast<void*>(this);
 
67
 
 
68
  return pam_start(/*FIXME*/ "gnome_screensaver", username_.c_str(),
 
69
                   &conversation, &pam_handle_) == PAM_SUCCESS;
 
70
}
 
71
 
 
72
int UserAuthenticatorPam::ConverationFunction(int num_msg,
 
73
                                              const pam_message** msg,
 
74
                                              pam_response** resp,
 
75
                                              void* appdata_ptr)
 
76
{
 
77
  if (num_msg <= 0)
 
78
    return PAM_CONV_ERR;
 
79
 
 
80
  auto* tmp_response = static_cast<pam_response*>(malloc(num_msg * sizeof(pam_response)));
 
81
  if (!tmp_response)
 
82
    return PAM_CONV_ERR;
 
83
 
 
84
  UserAuthenticatorPam* user_auth = static_cast<UserAuthenticatorPam*>(appdata_ptr);
 
85
 
 
86
  bool raise_error = false;
 
87
  int count;
 
88
  for (count = 0; count < num_msg && !raise_error; ++count)
 
89
  {
 
90
    pam_response* resp_item = &tmp_response[count];
 
91
    resp_item->resp_retcode = 0;
 
92
    resp_item->resp = nullptr;
 
93
 
 
94
    switch (msg[count]->msg_style)
 
95
    {
 
96
      case PAM_PROMPT_ECHO_ON:
 
97
        resp_item->resp = strdup(user_auth->username_.c_str());
 
98
        if (!resp_item->resp)
 
99
          raise_error = true;
 
100
        break;
 
101
      case PAM_PROMPT_ECHO_OFF:
 
102
        resp_item->resp = strdup(user_auth->password_.c_str());
 
103
        if (!resp_item->resp)
 
104
          raise_error = true;
 
105
        break;
 
106
      case PAM_TEXT_INFO:
 
107
        break;
 
108
      default:
 
109
        raise_error = true;
 
110
    }
 
111
  }
 
112
 
 
113
  if (raise_error)
 
114
  {
 
115
    for (int i = 0; i < count; ++i)
 
116
      if (tmp_response[i].resp)
 
117
        free(tmp_response[i].resp);
 
118
 
 
119
    free(tmp_response);
 
120
    return PAM_CONV_ERR;
 
121
  }
 
122
  else
 
123
  {
 
124
    *resp = tmp_response;
 
125
    return PAM_SUCCESS;
 
126
  }
 
127
}
 
128
 
 
129
}  // lockscreen
 
130
} // unity